您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何理解灰度發(fā)布”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“如何理解灰度發(fā)布”吧!
灰度發(fā)布就是已一種平滑過渡的方式來發(fā)布,通過切換線上新舊版本之間的路由權(quán)重,逐步從舊版本切換到新版本;比如要上線新功能,首先只是更新少量的服務(wù)節(jié)點,通過路由權(quán)重,讓少部分用戶體驗新版本,如果沒有什么問題,再更新所有服務(wù)節(jié)點;這樣可以在出現(xiàn)問題把影響面降到最低,保證了系統(tǒng)的穩(wěn)定性。
一個系統(tǒng)往往有接入層比如nginx(Openresty),網(wǎng)關(guān)層比如zuul,以及服務(wù)層比如各種rpc框架;在這幾層都有路由功能,也就是說這幾層都可以做灰度;接入層可以使用nginx+lua來實現(xiàn)灰度,網(wǎng)關(guān)層zuul可以結(jié)合ribbon來實現(xiàn)灰度,rpc框架如dubbo本身提供了路由功能可以直接做灰度處理;下面看看具體如何去實現(xiàn);
接入層我們這里使用功能更強大的Openresty,然后使用lua進行路由轉(zhuǎn)發(fā),相關(guān)的路由策略可以配置在分布式緩存redis里面,當然也可以持久化到數(shù)據(jù)庫里面;
準備
準備一臺Openresty,兩臺web服務(wù)器tomcat(端口分別是8081,8082),以及redis;為了方便模擬在redis里面配置白名單,如果在白名單里面就走8082,不在則走8081;
Openresty配置
需要在Openresty中配置支持lua,以及相關(guān)路由的lua腳本,nginx.conf配置如下:
http {...lua_package_path "/lualib/?.lua;;"; #lua 模塊 lua_package_cpath "/lualib/?.so;;"; #c模塊 upstream tomcat1 { server 127.0.0.1:8081;}upstream tomcat2 { server 127.0.0.1:8082;}server {listen 80;server_name localhost;location / { content_by_lua_file lua/gray.lua;}location @tomcat1 { proxy_pass http://tomcat1;}location @tomcat2 { proxy_pass http://tomcat2;}}...}
配置了所有請求都會經(jīng)過lua目錄下的gray.lua腳本,如下所示:
local redis = require "resty.redis";local redis_obj = redis:new(); redis_obj:set_timeout(2000);local ok,err = redis_obj:connect("127.0.0.1", 6379);if not ok then ngx.say("failed to connect redis ",err); return;end--獲取請求iplocal_ip = ngx.var.remote_addr;--redis中獲取白名單local whitelist = redis_obj:get("whitelist");--判斷是否在白名單然后轉(zhuǎn)到對應(yīng)服務(wù)if string.find(whitelist,local_ip) == nil then ngx.exec("@tomcat1");else ngx.exec("@tomcat2");endlocal ok,err = redis_obj:close();
Openresty內(nèi)置的功能模塊可以直接連接redis,然后從redis里面取出白名單,看當前的請求ip是否在白名單內(nèi),然后做簡單的路由功能;可以動態(tài)修改redis里面的白名單,實時更新。
localhost:0>set whitelist 127.0.0.1"OK"localhost:0>get whitelist"127.0.0.1"
啟動測試
分別啟動tomcat1,tomcat2以及Openresty,訪問http://localhost即可,可以動態(tài)修改redis里面的白名單,然后訪問查看結(jié)果驗證。
網(wǎng)關(guān)層已zuul為例,zuul的灰度需要修改ribbon的負載策略,就是根據(jù)eureka的metadata進行自定義元數(shù)據(jù),然后修改ribbon的策略規(guī)則;
準備
測試服務(wù)分別準備兩臺端口分別為:8765,8766,application.yml配置如下:
server: port: 8765eureka: instance:metadata-map: route: 1
同時準備請求地址/hiGray,返回值為route1;
server: port: 8766eureka: instance:metadata-map: route: 2
同時準備請求地址/hiGray,返回值為route2;用于區(qū)分是否走了灰度服務(wù)器;然后在zuul端需要引入一個插件:
<dependency><groupId>io.jmnarloch</groupId><artifactId>ribbon-discovery-filter-spring-cloud-starter</artifactId><version>2.1.0</version></dependency>
然后需要準備一個pre類型的filter,具體如下:
@Configurationpublic class GrayFilter extends ZuulFilter {@Overridepublic Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); String ip = request.getRemoteAddr();//ipv6本地地址,也就是127.0.0.1if ("0:0:0:0:0:0:0:1".equals(ip)) { RibbonFilterContextHolder.getCurrentContext() .add("route", "1"); } else { RibbonFilterContextHolder.getCurrentContext() .add("route", "2"); }return null; } ... }
以上也是使用白名單為例子,這里為了方便就沒有把白名單配置在redis里面,配置的白名單地址為ipv6:0:0:0:0:0:0:0:1,如果是白名單地址則路由到8765端口服務(wù),否則為8766端口服務(wù);
測試
分別啟動eureka-server,兩個eureka-client,以及zuul網(wǎng)關(guān),訪問網(wǎng)關(guān)地址即可;分別通過127.0.0.1和本地ip訪問即可測試;
服務(wù)器已rpc框架dubbo為例,dubbo本身提供了各種路由規(guī)則包括:條件路由,腳本路由等,這里同樣使用腳本路由為例,腳本路由規(guī)則支持JDK 腳本引擎的所有腳本,比如:javascript, jruby, groovy 等,這里使用缺省的JavaScript為例;
準備
注冊中心zookeeper,兩臺Provider可以在本地分別指定端口為20881和20882,消費者,以及下面重點介紹的路由腳本:
function gray_rule(invokers, context) {var tag = context.getAttachment("tag"); var result = new java.util.ArrayList(invokers.size());if(tag == "gray"){for (i = 0; i < invokers.size(); i ++) {if (invokers.get(i).getUrl().getPort()==20881) { result.add(invokers.get(i)); } } } else {for (i = 0; i < invokers.size(); i ++) {if (invokers.get(i).getUrl().getPort()==20882) { result.add(invokers.get(i)); } } }return result; } (invokers,context)
dubbo在運行腳本的時候會傳入三個參數(shù)分別是:invokers,Invocation以及RpcContext.getContext();通過在消費端在RpcContext中設(shè)置tag:
RpcContext.getContext().setAttachment("tag", "gray");
這樣就可以在腳本中進行判斷,tag為gray的消費端才走20881端口的服務(wù)端,其余走20882服務(wù)端;
以上的腳本需要注冊到zookeeper中,手動注冊代碼如下,當然也可以使用dubbo提供的dubbo-admin來設(shè)置路由腳本:
URL registryUrl = URL.valueOf("zookeeper://127.0.0.1:2181"); ZookeeperRegistryFactory zookeeperRegistryFactory = new ZookeeperRegistryFactory(); zookeeperRegistryFactory.setZookeeperTransporter(new CuratorZookeeperTransporter()); Registry zookeeperRegistry = (ZookeeperRegistry) zookeeperRegistryFactory.createRegistry(registryUrl); URL routerURL = URL.valueOf("script://0.0.0.0/com.dubboApi.DemoService?category=routers&dynamic=false"); routerURL = routerURL.addParameter("rule", URL.encode("(..JavaScript腳本..)")); zookeeperRegistry.register(routerURL); // 注冊
具體可以參考官方文檔:舊路由規(guī)則
測試
啟動zookeeper,然后分別啟動兩臺生產(chǎn)者,啟動消費者時通過修改tag然后觀察路由
感謝各位的閱讀,以上就是“如何理解灰度發(fā)布”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對如何理解灰度發(fā)布這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。