SpringCloud灰度發(fā)布的設(shè)計(jì)與實(shí)現(xiàn)詳解
灰度發(fā)布
什么是灰度發(fā)布呢?要想了解這個(gè)問題就要先明白什么是灰度。
灰度從字面意思理解就是存在于黑與白之間的一個(gè)平滑過渡的區(qū)域,所以說對(duì)于互聯(lián)網(wǎng)產(chǎn)品來說,上線和未上線就是黑與白之分,而實(shí)現(xiàn)未上線功能平穩(wěn)過渡的一種方式就叫做灰度發(fā)布。
在一般情況下,升級(jí)服務(wù)器端應(yīng)用,需要將應(yīng)用源碼或程序包上傳到服務(wù)器,然后停止掉老版本服務(wù),再啟動(dòng)新版本。
但是這種簡單的發(fā)布方式存在兩個(gè)問題,一方面,在新版本升級(jí)過程中,服務(wù)是暫時(shí)中斷的,另一方面,如果新版本有BUG,升級(jí)失敗,回滾起來也非常麻煩,容易造成更長時(shí)間的服務(wù)不可用。
在了解了什么是灰度發(fā)布的定義以后,就可以來了解一下灰度發(fā)布的具體操作方法了。
可以通過抽取一部分用戶,比如說選擇自己的測試用戶,使這些用戶的請(qǐng)求全部訪問灰度發(fā)布的服務(wù),正式用戶請(qǐng)求走正常上線的服務(wù),那么就能夠?qū)⑿枰叶劝l(fā)布的版本也連接到正常上線服務(wù)中進(jìn)行測試,沒有問題之后將其設(shè)置為正常服務(wù)即完成版本的上線測試和發(fā)布。
實(shí)現(xiàn)設(shè)計(jì)
實(shí)現(xiàn)重點(diǎn)主要在:
- 利用 ThreadLocal+Feign 實(shí)現(xiàn) http head 中實(shí)現(xiàn)信息的傳遞
- 使用Nacos的元數(shù)據(jù),定義需要的灰度服務(wù)
- 自定義Ribbon的路由規(guī)則,根據(jù)Nacos的元數(shù)據(jù)選擇服務(wù)節(jié)點(diǎn)
公共配置
ThreadLocal
public class PassParameters {
private static final Logger log = LoggerFactory.getLogger(PassParameters.class);
private static final ThreadLocal localParameters = new ThreadLocal();
public static PassParametersModel get(){
PassParametersModel model = (PassParametersModel) localParameters.get();
log.info("ThreadID:{}, threadLocal {}", Thread.currentThread().getId(), model.toString());
return model;
}
public static void set(PassParametersModel model){
log.info("ThreadID:{}, threadLocal set {}", Thread.currentThread().getId(), model.toString());
localParameters.set(model);
}
}攜帶灰度發(fā)布相關(guān)數(shù)據(jù)的類
public class PassParametersModel {
private String token;
private String grayPublish;
}請(qǐng)求頭常量
public class HttpConstants {
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String GRAY_PUBLISH = "Gray-Publish";
public static final String GRAY_PUBLISH_MEAT_KEY = "grayPublish";
}AOP請(qǐng)求攔截處理
@Aspect
@Order(1)
@Component
public class PermissionsValidationAspect {
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 權(quán)限校驗(yàn)以及一些參數(shù)的賦值O
* @param joinPoint
* @return
* @throws Throwable
*/
@Around(value = "需要攔截的方法")
public Object check(ProceedingJoinPoint joinPoint) throws Throwable {
// 獲取一些參數(shù)
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader(HttpConstants.AUTHORIZATION_HEADER);
// FIXME:
// token權(quán)限校驗(yàn),不要去查數(shù)據(jù)庫!?。?!
// 來這里的token肯定都是有用的,因?yàn)樵诰W(wǎng)關(guān)那里就會(huì)進(jìn)行token有效的校驗(yàn)
// 校驗(yàn)成功之后進(jìn)行用戶身份的賦值,比如uid、username等關(guān)鍵信息
// 本次請(qǐng)求涉及到的灰度發(fā)布
// FIXME: 通過用戶所屬的用戶組或其他標(biāo)識(shí)信息,專門指定某些用戶是灰度發(fā)布測試用戶,來設(shè)置灰度發(fā)布的字段
String grayPublish = request.getHeader(HttpConstants.GRAY_PUBLISH);
PassParametersModel model = new PassParametersModel();
model.setToken(token);
model.setGrayPublish(grayPublish);
PassParameters.set(model);
return joinPoint.proceed();
}
}Feign配置
Ribbon請(qǐng)求規(guī)則
將會(huì)從Nacos中獲取元服務(wù)器的信息,并根據(jù)這個(gè)信息選擇服務(wù)器。
public class GrayPublishInterceptor implements RequestInterceptor {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public void apply(RequestTemplate requestTemplate) {
PassParametersModel model = PassParameters.get();
// token
if (StringUtils.isNotEmpty(model.getToken())) {
requestTemplate.header(HttpConstants.AUTHORIZATION_HEADER, model.getToken());
}
// grayPublish
if (StringUtils.isNotEmpty(model.getGrayPublish())) {
requestTemplate.header(HttpConstants.GRAY_PUBLISH, model.getGrayPublish());
}
// FIXME: 補(bǔ)充其他需要傳遞的內(nèi)容
}
}Feign攔截器
將需要傳遞給下個(gè)微服務(wù)中的數(shù)據(jù)進(jìn)行賦值
public class GrayPublishInterceptor implements RequestInterceptor {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public void apply(RequestTemplate requestTemplate) {
PassParametersModel model = PassParameters.get();
// token
if (StringUtils.isNotEmpty(model.getToken())) {
requestTemplate.header(HttpConstants.AUTHORIZATION_HEADER, model.getToken());
}
// grayPublish
if (StringUtils.isNotEmpty(model.getGrayPublish())) {
requestTemplate.header(HttpConstants.GRAY_PUBLISH, model.getGrayPublish());
}
// FIXME: 補(bǔ)充其他需要傳遞的內(nèi)容
}
}配置使用
這里是全局配置使用
@Configuration
public class FeignConfig {
// 灰度發(fā)布Ribbon規(guī)則
@Bean
public IRule getRule(){
return new GrayPublishRibbonRule();
}
// header傳遞
@Bean
public GrayPublishInterceptor getInterceptor(){
return new GrayPublishInterceptor();
}
}Nacos元數(shù)據(jù)配置
通過在application.yml進(jìn)行配置
# 服務(wù)的元數(shù)據(jù)
spring:
cloud:
nacos:
discovery:
metadata.grayPublish: HAHAHA_TEST到此這篇關(guān)于SpringCloud灰度發(fā)布的設(shè)計(jì)與實(shí)現(xiàn)詳解的文章就介紹到這了,更多相關(guān)SpringCloud灰度發(fā)布內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring Cloud 優(yōu)雅下線以及灰度發(fā)布實(shí)現(xiàn)
- SpringCloud實(shí)現(xiàn)灰度發(fā)布的方法步驟
- springcloud+nacos實(shí)現(xiàn)灰度發(fā)布示例詳解
- 關(guān)于SpringCloud灰度發(fā)布的實(shí)現(xiàn)
- SpringCloud的全鏈路灰度發(fā)布方案詳解
- Spring?Cloud實(shí)現(xiàn)灰度發(fā)布的示例代碼
- SpringCloud實(shí)現(xiàn)全鏈路灰度發(fā)布的示例詳解
- Spring Cloud Gateway實(shí)現(xiàn)灰度發(fā)布方案
相關(guān)文章
SpringBoot整合RabbitMQ處理死信隊(duì)列和延遲隊(duì)列
這篇文章將通過示例為大家詳細(xì)介紹SpringBoot整合RabbitMQ時(shí)如何處理死信隊(duì)列和延遲隊(duì)列,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-05-05
Spring?web開發(fā)教程之Request獲取3種方式
這篇文章主要給大家介紹了關(guān)于Spring?web開發(fā)教程之Request獲取3種方式的相關(guān)資料,request對(duì)象是從客戶端向服務(wù)器發(fā)出請(qǐng)求,包括用戶提交的信息以及客戶端的一些信息,需要的朋友可以參考下2023-11-11
springboot項(xiàng)目中后端接收前端傳參的方法示例詳解
這篇文章主要介紹了springboot項(xiàng)目中一些后端接收前端傳參的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06

