擴充套件Zuul實現敏捷開發的小小技巧
分析下目前遇到的痛點
你在開發工作的是否遇到這個問題,微服務模組劃分過細,基礎模組依賴的比較多?
比如你要進行微服務開發則需要啟動以下基礎模組
- 註冊中心(eureka)
- 配置中心(spring cloud config)
- 閘道器(zuul)
- 認證中心(oauth)
- …
如上圖紅色標註的服務模組,而你需要編碼或者需要的只有那麼一個業務微服務模組,本地啟動這麼微服務模組對開發機器的要求效能較高,並且影響開發效率。
為了解決這種問題,團隊一般都會把通用的基礎模組部,提供統一的開發環境,方便大家開發,如上圖 只需要考慮你的業務模組(serviceA、serviceB) 即可,提高開發效率。
這種統一開發基礎環境問題存在小小的問題,比如當開發A維護serviceA,開發B維護serviceB 不會出現衝突;如果開發A、B同時維護一個模組時候,就會出現衝突如下圖所示:A的本地請求會被路由到B正在開發的biz-service,而不是目標的A的biz-service,因為zuul 是更具服務名稱進行路由的
解決原理
重寫閘道器的轉發規則,其實就是重寫ribbon的路由規則,根據客戶端不同的使用者請求(可以根據入參不同區分)路由到對應的微服務上,所以對應的微服務上要打上標籤。biz-service A開發版本,biz-service B開發版本
程式碼實現
- 在微服務的eureka客戶端宣告版本所屬
eureka:
instance:
metadata-map:
version: v1.0 # A的開發版本
- 自定義ribbon 的斷言
/**
* @author lengleng
* @date 2018/10/16
* <p>
* 路由微服務斷言
* <p>
* 1. eureka metadata 存在版本定義時候進行判斷
* 2. 不存在 metadata 直接返回true
*/
@Slf4j
public class MetadataCanaryRuleHandler extends ZoneAvoidanceRule {
@Override
public AbstractServerPredicate getPredicate() {
return new AbstractServerPredicate() {
@Override
public boolean apply(PredicateKey predicateKey) {
String targetVersion = RibbonVersionHolder.getContext();
RibbonVersionHolder.clearContext();
if (StrUtil.isBlank(targetVersion)) {
log.debug("客戶端未配置目標版本直接路由");
return true;
}
DiscoveryEnabledServer server = (DiscoveryEnabledServer) predicateKey.getServer();
final Map<String, String> metadata = server.getInstanceInfo().getMetadata();
if (StrUtil.isBlank(metadata.get(SecurityConstants.VERSION))) {
log.debug("當前微服務{} 未配置版本直接路由");
return true;
}
if (metadata.get(SecurityConstants.VERSION).equals(targetVersion)) {
return true;
} else {
log.debug("當前微服務{} 版本為{},目標版本{} 匹配失敗", server.getInstanceInfo().getAppName()
, metadata.get(SecurityConstants.VERSION), targetVersion);
return false;
}
}
};
}
}
- 版本上下文TTL
public class RibbonVersionHolder {
private static final ThreadLocal<String> context = new TransmittableThreadLocal<>();
public static String getContext() {
return context.get();
}
public static void setContext(String value) {
context.set(value);
}
public static void clearContext() {
context.remove();
}
}
- 初始化ribbon 路由配置
@Configuration
@ConditionalOnClass(DiscoveryEnabledNIWSServerList.class)
@AutoConfigureBefore(RibbonClientConfiguration.class)
@ConditionalOnProperty(value = "zuul.ribbon.metadata.enabled")
public class RibbonMetaFilterAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public ZoneAvoidanceRule metadataAwareRule() {
return new MetadataCanaryRuleHandler();
}
}
- 客戶端呼叫時 header 傳入版本,以 axios 為例
axios.interceptors.request.use(config => {
NProgress.start() // start progress bar
if (store.getters.access_token) {
config.headers[`Authorization`] = `Bearer ` + token
config.headers[`version`] = `v1.0` // 開發人員自己的版本標誌,對應eureka metadata 配置
}
return config
}
總結
- 擴充套件ribbon 的路由規則,根據客戶端來去不同版本的服務,也可以理解為灰度釋出。
- 生產環境可以藉助Kong、Traefik 集合zuul 來實現灰度釋出
- 程式碼請參考微服務許可權框架pig的灰度釋出功能,已經全部開源
- 關於pig:
基於Spring Cloud、oAuth2.0開發基於Vue前後分離的開發平臺,支援賬號、簡訊、SSO等多種登入,提供配套視訊開發教程。
相關文章
- Chrome 擴充套件的開發實戰Chrome套件
- 你們是如何敏捷開發 Laravel 私有擴充套件包的?敏捷Laravel套件
- 小程式開發實用技巧——擴充套件 Page 頁面物件套件物件
- 開發php擴充套件PHP套件
- JMeter 擴充套件開發:擴充套件 TCP 取樣器JMeter套件TCP
- PHP擴充套件開發就是一個自己的PHP擴充套件PHP套件
- Chrome瀏覽器擴充套件開發系列之十九:擴充套件開發示例Chrome瀏覽器套件
- 擴充套件JAAS,XMLPolicyFile實現套件XML
- chrome擴充套件程式開發Chrome套件
- Go開發PHP擴充套件GoPHP套件
- php擴充套件開發初探PHP套件
- LLM 擴充套件開發工具套件
- Chrome 擴充套件程式的開發與釋出 — 手把手教你開發擴充套件程式Chrome套件
- php利用pcntl擴充套件實現高併發PHP套件
- 如何開發Chrome擴充套件程式Chrome套件
- Chrome 擴充套件程開發初探Chrome套件
- 基於PHP擴充套件的WAF實現PHP套件
- dubbo是如何實現可擴充套件的?套件
- 基於 GatewayWorker 開發的 Laravel 擴充套件GatewayLaravel套件
- iOS開發的分類和擴充套件iOS套件
- MOSN 多協議擴充套件開發實踐協議套件
- CONNECT BY 擴充套件用法,實現獲取bom級聯擴充套件數量套件
- PHP擴充套件開發教程2 – 編寫第一個擴充套件 hello worldPHP套件
- [開發效率]Kotlin之擴充套件Kotlin套件
- Chrome 擴充套件外掛開發DEMOChrome套件
- 報表開發之擴充套件GROUP BY套件
- 如何擴充套件開發團隊(譯)套件
- Laravel 是自動發現擴充套件包是怎樣實現的Laravel套件
- django實現自定義manage命令的擴充套件Django套件
- PHP實現Bitmap的探索 - GMP擴充套件使用PHP套件
- dubbo是如何實現可擴充套件的?(二)套件
- 用 TDD 的方式為 Laravel 開發擴充套件Laravel套件
- VSCode WebView外掛(擴充套件)開發實戰VSCodeWebView套件
- JMeter 擴充套件開發:BeanShell 資料模擬實現及效能探討JMeter套件Bean
- Chrome瀏覽器擴充套件開發系列之八:Chrome擴充套件的資料儲存Chrome瀏覽器套件
- Chrome瀏覽器擴充套件開發系列之一:初識Google Chrome擴充套件Chrome瀏覽器套件Go
- kotlin 擴充套件(擴充套件函式和擴充套件屬性)Kotlin套件函式
- JWT 擴充套件具體實現詳解JWT套件