灰度发布(Gray Release,也称为灰度发布或金丝雀发布)是指在软件或服务发布过程中,将新版本的功能或服务以较小的比例引入到生产环境中,仅向部分用户或节点提供新功能的一种发布策略。
成都创新互联公司是一家专业提供荔波企业网站建设,专注与做网站、网站设计、H5技术、小程序制作等业务。10年已为荔波众多企业、政府机构等服务。创新互联专业网站设计公司优惠进行中。
在传统的全量发布中,新版本的功能会一次性全部部署到所有的用户或节点上。然而,这种方式潜在的风险是,如果新版本存在缺陷或问题,可能会对所有用户或节点产生严重的影响,导致系统崩溃或服务不可用。
相比之下,灰度发布采用较小的规模,并逐步将新版本的功能引入到生产环境中,仅向一小部分用户或节点提供新功能。通过持续监测和评估,可以在发现问题时及时回滚或修复。这种逐步引入新版本的方式可以降低风险,并提高系统的稳定性和可靠性。
灰色发布的常见实现思路有以下几种:
而在生产环境中,比较常用的是根据用户标识来实现灰色发布,也就是说先让一小部分用户体验新功能,以发现新服务中可能存在的某种缺陷或不足。
Spring Cloud 全链路灰色发布的关键实现思路如下图所示:
灰度发布的具体实现步骤如下:
经过第四步的反复传递之后,整个 Spring Cloud 全链路的灰度发布就完成了。
灰度发布的关键实现技术和代码如下。
在灰度发布的执行流程中,有一个核心的问题,如果在 Spring Cloud LoadBalancer 进行服务调用时,区分正式服务和灰度服务呢?
这个问题的解决方案是:在灰度服务既注册中心的 MetaData(元数据)中标识自己为灰度服务即可,而元数据中没有标识(灰度服务)的则为正式服务,以 Nacos 为例,它的设置如下:
spring:
application:
name: canary-user-service
cloud:
nacos:
discovery:
username: nacos
password: nacos
server-addr: localhost:8848
namespace: public
register-enabled: true
metadata: { "grap-tag":"true" } # 标识自己为灰度服务
Spring Cloud LoadBalancer 判断并调用灰度服务的关键实现代码如下:
private Response getInstanceResponse(List instances,
Request request) {
// 实例为空
if (instances.isEmpty()) {
if (log.isWarnEnabled()) {
log.warn("No servers available for service: " + this.serviceId);
}
return new EmptyResponse();
} else { // 服务不为空
RequestDataContext dataContext = (RequestDataContext) request.getContext();
HttpHeaders headers = dataContext.getClientRequest().getHeaders();
// 判断是否为灰度发布(请求)
if (headers.get(GlobalVariables.GRAY_KEY) != null &&
headers.get(GlobalVariables.GRAY_KEY).get(0).equals("true")) {
// 灰度发布请求,得到新服务实例列表
List findInstances = instances.stream().
filter(s -> s.getMetadata().get(GlobalVariables.GRAY_KEY) != null &&
s.getMetadata().get(GlobalVariables.GRAY_KEY).equals("true"))
.toList();
if (findInstances.size() > 0) { // 存在灰度发布节点
instances = findInstances;
}
} else { // 查询非灰度发布节点
// 灰度发布测试请求,得到新服务实例列表
instances = instances.stream().
filter(s -> s.getMetadata().get(GlobalVariables.GRAY_KEY) == null ||
!s.getMetadata().get(GlobalVariables.GRAY_KEY).equals("true"))
.toList();
}
// 随机正数值 ++i( & 去负数)
int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;
// ++i 数值 % 实例数 取模 -> 轮询算法
int index = pos % instances.size();
// 得到服务实例方法
ServiceInstance instance = (ServiceInstance) instances.get(index);
return new DefaultResponse(instance);
}
}
以上代码为自定义负载均衡器,并使用了轮询算法。如果 Header 中有灰度标签,则只查询灰度服务的节点实例,否则则查询出所有的正式节点实例(以供服务调用或服务转发)。
要在网关 Spring Cloud Gateway 中传递灰度标识,只需要在 Gateway 的全局自定义过滤器中设置 Response 的 Header 即可,具体实现代码如下:
package com.example.gateway.config;
import com.loadbalancer.canary.common.GlobalVariables;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class LoadBalancerFilter implements GlobalFilter {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 得到 request、response 对象
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
if (request.getQueryParams().getFirst(GlobalVariables.GRAY_KEY) != null) {
// 设置金丝雀标识
response.getHeaders().set(GlobalVariables.GRAY_KEY,
"true");
}
// 此步骤正常,执行下一步
return chain.filter(exchange);
}
}
HTTP 调用工具 Openfeign 传递灰度标签的实现代码如下:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
@Component
public class FeignRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 从 RequestContextHolder 中获取 HttpServletRequest
ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
// 获取 RequestContextHolder 中的信息
Map headers = getHeaders(attributes.getRequest());
// 放入 openfeign 的 RequestTemplate 中
for (Map.Entry entry : headers.entrySet()) {
template.header(entry.getKey(), entry.getValue());
}
}
/**
* 获取原请求头
*/
private Map getHeaders(HttpServletRequest request) {
Map map = new LinkedHashMap<>();
Enumeration enumeration = request.getHeaderNames();
if (enumeration != null) {
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
}
}
灰度发布是微服务时代保证生产环境安全的必备措施,而其关键实现思路是:
这样,我们就完整的实现 Spring Cloud 全链路灰度发布功能了。
本文标题:SpringCloud全链路灰色具体发布!
转载源于:http://www.shufengxianlan.com/qtweb/news27/271727.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联