SpringCloud灰度發(fā)布的設(shè)計與實現(xiàn)詳解
灰度發(fā)布
什么是灰度發(fā)布呢?要想了解這個問題就要先明白什么是灰度。
灰度從字面意思理解就是存在于黑與白之間的一個平滑過渡的區(qū)域,所以說對于互聯(lián)網(wǎng)產(chǎn)品來說,上線和未上線就是黑與白之分,而實現(xiàn)未上線功能平穩(wěn)過渡的一種方式就叫做灰度發(fā)布。
在一般情況下,升級服務(wù)器端應(yīng)用,需要將應(yīng)用源碼或程序包上傳到服務(wù)器,然后停止掉老版本服務(wù),再啟動新版本。
但是這種簡單的發(fā)布方式存在兩個問題,一方面,在新版本升級過程中,服務(wù)是暫時中斷的,另一方面,如果新版本有BUG,升級失敗,回滾起來也非常麻煩,容易造成更長時間的服務(wù)不可用。
在了解了什么是灰度發(fā)布的定義以后,就可以來了解一下灰度發(fā)布的具體操作方法了。
可以通過抽取一部分用戶,比如說選擇自己的測試用戶,使這些用戶的請求全部訪問灰度發(fā)布的服務(wù),正式用戶請求走正常上線的服務(wù),那么就能夠?qū)⑿枰叶劝l(fā)布的版本也連接到正常上線服務(wù)中進行測試,沒有問題之后將其設(shè)置為正常服務(wù)即完成版本的上線測試和發(fā)布。
實現(xiàn)設(shè)計
實現(xiàn)重點主要在:
- 利用 ThreadLocal+Feign 實現(xiàn) http head 中實現(xiàn)信息的傳遞
- 使用Nacos的元數(shù)據(jù),定義需要的灰度服務(wù)
- 自定義Ribbon的路由規(guī)則,根據(jù)Nacos的元數(shù)據(jù)選擇服務(wù)節(jié)點
公共配置
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; }
請求頭常量
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請求攔截處理
@Aspect @Order(1) @Component public class PermissionsValidationAspect { private final Logger logger = LoggerFactory.getLogger(getClass()); /** * 權(quá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)限校驗,不要去查數(shù)據(jù)庫?。。?! // 來這里的token肯定都是有用的,因為在網(wǎng)關(guān)那里就會進行token有效的校驗 // 校驗成功之后進行用戶身份的賦值,比如uid、username等關(guān)鍵信息 // 本次請求涉及到的灰度發(fā)布 // FIXME: 通過用戶所屬的用戶組或其他標(biāo)識信息,專門指定某些用戶是灰度發(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請求規(guī)則
將會從Nacos中獲取元服務(wù)器的信息,并根據(jù)這個信息選擇服務(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: 補充其他需要傳遞的內(nèi)容 } }
Feign攔截器
將需要傳遞給下個微服務(wù)中的數(shù)據(jù)進行賦值
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: 補充其他需要傳遞的內(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進行配置
# 服務(wù)的元數(shù)據(jù) spring: cloud: nacos: discovery: metadata.grayPublish: HAHAHA_TEST
到此這篇關(guān)于SpringCloud灰度發(fā)布的設(shè)計與實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)SpringCloud灰度發(fā)布內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java獲取當(dāng)前時間并轉(zhuǎn)化為yyyy-MM-dd?HH:mm:ss格式的多種方式
這篇文章主要介紹了Java獲取當(dāng)前時間并轉(zhuǎn)化為yyyy-MM-dd?HH:mm:ss格式的多種方式,每種方式結(jié)合實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-03-03IDEA 集成log4j將SQL語句打印在控制臺上的實現(xiàn)操作
這篇文章主要介紹了IDEA 集成log4j將SQL語句打印在控制臺上的實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02關(guān)于SpringMVC在Controller層方法的參數(shù)解析詳解
在SpringMVC中,控制器Controller負責(zé)處理由DispatcherServlet分發(fā)的請求,下面這篇文章主要給大家介紹了關(guān)于SpringMVC在Controller層方法的參數(shù)解析的相關(guān)資料,需要的朋友可以參考下2021-12-12JAVA實現(xiàn)Excel和PDF上下標(biāo)的操作代碼
這篇文章主要介紹了JAVA實現(xiàn)Excel和PDF上下標(biāo),本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09SpringBoot整合Netty+Websocket實現(xiàn)消息推送的示例代碼
WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù),本文主要介紹了SpringBoot整合Netty+Websocket實現(xiàn)消息推送的示例代碼,具有一定的參考價值,感興趣的可以了解一下2024-01-01