javascript
分布式与微服务系列(三)、SpringBoot+Zookeeper集群+Nginx反向代理+Dubbo分布式托管(提供者、消费者)
SpringBoot+Zookeeper集群+Nginx反向代理+Dubbo分布式托管(提供者、消費(fèi)者)
- 一、軟件架構(gòu)和微服務(wù)需求
- 1.1、微服務(wù)需求
- 1.2、框架選擇
- 1.3、集群分布(下面為此圖實(shí)戰(zhàn)演示)
- 二、搭建Zookeeper注冊(cè)中心集群服務(wù)
- 2.1、配置三臺(tái)zookeeper注冊(cè)中心服務(wù)器(數(shù)量可選)
- 2.2、修改三臺(tái)zookeeper配置信息
- 2.3、配置zookeeper集群區(qū)分id
- 2.4、啟動(dòng)zookeeper集群服務(wù)
- 三、啟動(dòng)Dubbo管理控制臺(tái)可視化界面
- 3.1、修改dubbo-admin的配置文件
- 3.2、打包dubbo-admin項(xiàng)目
- 3.3、運(yùn)行`dubbo-admin-0.0.1-SNAPSHOT.jar`包
- 四、創(chuàng)建服務(wù)提供者集群服務(wù)(三個(gè))
- 4.1、新建SpringBoot_dubbo_provider項(xiàng)目
- 4.2、引入pom.xml坐標(biāo)依賴(lài)文件
- 4.3、新建包c(diǎn)om.ebuy.service,在此包下新建HelloService接口
- 4.4、新建包c(diǎn)om.ebuy.service.impl,在此包下新建接口HelloServiceImpl實(shí)現(xiàn)類(lèi)
- 4.5、核心配置文件(使用application.yml樹(shù)狀結(jié)構(gòu))
- 4.6、啟動(dòng)第一臺(tái)provider-8081提供者服務(wù)
- 4.7、啟動(dòng)第二臺(tái)provider-8082提供者服務(wù)
- 4.8、啟動(dòng)第三臺(tái)provider-8083提供者服務(wù)
- 五、創(chuàng)建服務(wù)消費(fèi)者集群服務(wù)(四個(gè))
- 5.1、新建SpringBoot_dubbo_consumer項(xiàng)目
- 5.2、引入pom.xml坐標(biāo)依賴(lài)文件
- 5.3、新建包c(diǎn)om.ebuy.service,在此包下新建HelloService接口,與提供者接口保持一致
- 5.4、新建包c(diǎn)om.ebuy.controller,在此包下新建HelloController類(lèi)
- 5.5、核心配置文件(使用application.yml樹(shù)狀結(jié)構(gòu))
- 5.6、啟動(dòng)第一臺(tái)consumer-2011服務(wù)消費(fèi)者
- 5.7、啟動(dòng)第一臺(tái)consumer-2012服務(wù)消費(fèi)者
- 5.8、啟動(dòng)第一臺(tái)consumer-2013服務(wù)消費(fèi)者
- 5.9、啟動(dòng)第一臺(tái)consumer-2014服務(wù)消費(fèi)者
- 六、使用SwitchHosts工具模擬綁定域名
- 6.1、修改主機(jī)配置文件hosts的只讀屬性
- 6.2、以管理員身份運(yùn)行SwitchHosts工具,新建域名(自定義)
- 七、使用Nginx反向代理(消費(fèi)者)
- 7.1、nginx反向代理作用
- 7.2、修改nginx配置文件
- 7.3、啟動(dòng)nginx
- 八、通過(guò)nginx反向代理,請(qǐng)求消費(fèi)者,通過(guò)消費(fèi)者訪(fǎng)問(wèn)提供者
- 8.1、第一次請(qǐng)求
- 8.2、第二次請(qǐng)求
- 8.3、第三次請(qǐng)求
- 8.4、第四次請(qǐng)求
- 九、解決Dubbo內(nèi)置負(fù)載均衡策略問(wèn)題
- 9.1、Dubbo 的內(nèi)置負(fù)載均衡策略(四種)
- 9.2、什么是輪詢(xún)策略?
- 9.3、如何解決不完全輪詢(xún)策略(忽略性能差異)?
- 9.4、配置負(fù)載均衡策略
- 9.4.1、第一種在消費(fèi)者注解方式配置
- 9.4.2、第二種在消費(fèi)者配置文件yml或者properties中配置
- 9.4.3、第三種在提供者業(yè)務(wù)層注解方式配置
- 9.4.4、第四種在提供者配置文件方式配置
一、軟件架構(gòu)和微服務(wù)需求
1.1、微服務(wù)需求
我們知道軟件架構(gòu)的演化過(guò)程,從單體架構(gòu),到垂直架構(gòu),再到SOA架構(gòu),最后到現(xiàn)在較流行的微服務(wù)架構(gòu)。每個(gè)架構(gòu)都有各自的優(yōu)缺點(diǎn),隨著架構(gòu)體系的演化和現(xiàn)如今軟件整體架構(gòu)的需求在不斷的提高,微服務(wù)之所以比較流行就是因?yàn)樗鼘⑾到y(tǒng)服務(wù)層完全獨(dú)立出來(lái),抽取為一個(gè)一個(gè)的服務(wù);微服務(wù)架構(gòu)采用去中心化思想,服務(wù)之間采用restful等輕量協(xié)議通信,相比ESB更輕量。因?yàn)閯?chuàng)建一個(gè)系統(tǒng)要考慮到全面服務(wù),總體來(lái)說(shuō)要能做到軟件架構(gòu)的三要素:高可用、高性能、高并發(fā)。如果一個(gè)系統(tǒng)做不到這三個(gè)要素,那就不能稱(chēng)為一個(gè)好的軟件系。
本文我們著重講解,使用SpringBoot項(xiàng)目整合Zookeeper注冊(cè)中心,Nginx反向代理和Dubbo遠(yuǎn)程代理分布式托管,最后實(shí)現(xiàn)系統(tǒng)的高可用、高并發(fā)和高性能,其核心就是使所有服務(wù)器面對(duì)海量訪(fǎng)問(wèn)能夠?qū)崿F(xiàn)負(fù)載均衡。
1.2、框架選擇
- SpringBoot是當(dāng)前比較流行的框架,其底層集成了Spring、mybatis、hibernate等多種優(yōu)秀框架,這個(gè)框架的好用程度就不多說(shuō)了,用起來(lái)可以說(shuō)是朗朗上手,帶勁。
- Nginx是一 個(gè)輕量級(jí)/高性能的反向代理Web服務(wù)器,而且Nginx支持跨平臺(tái)、配置簡(jiǎn)單、高并發(fā)連接:處理2-3萬(wàn)并發(fā)連接數(shù),官方監(jiān)測(cè)能支持5萬(wàn)并發(fā),內(nèi)存消耗小:開(kāi)啟10個(gè)nginx才占150M內(nèi)存 ,nginx處理靜態(tài)文件好,耗費(fèi)內(nèi)存少,它能夠?qū)崿F(xiàn)非常高效的反向代理和負(fù)載平衡。
- Dubbo是一款微服務(wù)開(kāi)發(fā)框架,它提供了RPC通信與微服務(wù)治理兩大關(guān)鍵能力。這意味著,使用Dubbo開(kāi)發(fā)的微服務(wù),將具備相互之間的遠(yuǎn)程發(fā)現(xiàn)與通信能力,同時(shí)利用Dubbo提供的豐富服務(wù)治理能力,可以實(shí)現(xiàn)諸如服務(wù)實(shí)現(xiàn)、負(fù)載均衡、流量調(diào)度等服務(wù)治理訴求。同時(shí)Dubbo是高度可擴(kuò)展的,用戶(hù)幾乎可以在任意功能點(diǎn)去定制自己的實(shí)現(xiàn),以改變框架的默認(rèn)行為來(lái)滿(mǎn)足自己的業(yè)務(wù)需求。
- Zookeeper是Apache Hadoop的子項(xiàng)目,是一個(gè)樹(shù)型的目錄服務(wù),支持變更推送,適合作為Dubbo服務(wù)的注冊(cè)中心,工業(yè)強(qiáng)度較高,可用于生產(chǎn)環(huán)境,并推薦使用。
- 我們最終要實(shí)現(xiàn)的效果如下圖(讓其Dubbo分布式中的服務(wù)器全部使用集群,實(shí)現(xiàn)負(fù)載均衡):
1.3、集群分布(下面為此圖實(shí)戰(zhàn)演示)
簡(jiǎn)單集成應(yīng)用可以詳細(xì)觀看分布式與微服務(wù)系列(二)、分布式RPC框架Apache Dubbo服務(wù)。
二、搭建Zookeeper注冊(cè)中心集群服務(wù)
因?yàn)楸敬螠y(cè)試是在一臺(tái)電腦上做測(cè)試,所以暫不使用Linux虛擬機(jī)啟動(dòng)Zookeeper集群服務(wù)了,怕到時(shí)候電腦啊承受不住,掛掉。我們就先在Windows下使用Zookeeper測(cè)試即可。
2.1、配置三臺(tái)zookeeper注冊(cè)中心服務(wù)器(數(shù)量可選)
2.2、修改三臺(tái)zookeeper配置信息
修改zoo.cfg配置文件信息:
這三行代碼(不要修改)依次粘到后兩臺(tái)zookeeper配置文件中,別忘了更改端口號(hào)依次為2082、2083:
2.3、配置zookeeper集群區(qū)分id
2.4、啟動(dòng)zookeeper集群服務(wù)
在啟動(dòng)過(guò)程中,發(fā)現(xiàn)第一臺(tái)有報(bào)錯(cuò),莫要慌,不要緊,因?yàn)樵诘谝慌_(tái)啟動(dòng)的時(shí)候會(huì)自動(dòng)尋找靈臺(tái)兩臺(tái)zokkeeper,找不到你說(shuō)急不急,所以就報(bào)錯(cuò)了,等三臺(tái)zookeeper都啟動(dòng)成功了,就不會(huì)報(bào)錯(cuò)了!
如果實(shí)在不放心,可以連接zookeeper自帶的客戶(hù)端,查看下當(dāng)前節(jié)點(diǎn)是否已創(chuàng)建!
出現(xiàn)上述節(jié)點(diǎn)就說(shuō)明zookeeper集群此時(shí)已經(jīng)啟動(dòng)成功了,最后一個(gè)客戶(hù)端窗口可以關(guān)閉,但是上述仨窗口放著,可千萬(wàn)別關(guān)哈!!!
三、啟動(dòng)Dubbo管理控制臺(tái)可視化界面
我們?nèi)巳绻胍婪?wù)提供者和消費(fèi)者是是否成功注冊(cè)和訂閱到zookeeper注冊(cè)中心,Dubbo官方為我們提供了一個(gè)Dubbo管理控制臺(tái)可視化界面。
啟動(dòng)Dubbo控制臺(tái)界面有兩種方式,詳情可以查看我的上篇文章分布式與微服務(wù)系列(二)、分布式RPC框架Apache Dubbo服務(wù),第四點(diǎn)有詳細(xì)介紹如何使用,此處我們就簡(jiǎn)單介紹下jar包形式啟動(dòng)Dubbo可視化管理控制臺(tái),另一個(gè)是war包形式。
3.1、修改dubbo-admin的配置文件
3.2、打包dubbo-admin項(xiàng)目
在打開(kāi)的DOS命令窗口中執(zhí)行命令mvn clean package,先清除一下,然后打包項(xiàng)目,第一次執(zhí)行可能會(huì)有點(diǎn)慢,大概一分鐘左右,稍安勿躁:
打包完成出現(xiàn)target目錄:
進(jìn)入target目錄:
3.3、運(yùn)行dubbo-admin-0.0.1-SNAPSHOT.jar包
首先你要確保你的此jar包所在的路徑?jīng)]有中文,你就可以直接在打開(kāi)DOS命令窗口,切換到此路徑下,執(zhí)行命令java -jar dubbo-admin-0.0.1-SNAPSHOT.jar即可運(yùn)行;如果有中文,將此jar包直接拷貝到另外一個(gè)沒(méi)有中文的目錄下,再執(zhí)行命令:
如果覺(jué)得每次啟動(dòng)打開(kāi)DOS窗口比較麻煩,那就jar包所在目錄下創(chuàng)建一個(gè)批處理:
如果你得jar包運(yùn)行出現(xiàn)錯(cuò)誤,那就是你上述的配置或路徑寫(xiě)錯(cuò)了,仔細(xì)檢查一遍按照我上述的步驟重新打包很快的。
啟動(dòng)成功,然后我們就可以在瀏覽器地址欄輸入localhost:7001直接訪(fǎng)問(wèn)了
四、創(chuàng)建服務(wù)提供者集群服務(wù)(三個(gè))
4.1、新建SpringBoot_dubbo_provider項(xiàng)目
4.2、引入pom.xml坐標(biāo)依賴(lài)文件
<!--springboot啟動(dòng)器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--springboot web啟動(dòng)器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--springboot 測(cè)試啟動(dòng)器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--dubbo與springboot集成啟動(dòng)器--><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.6</version></dependency><!--dubbo與注冊(cè)中心zookeeper整合包--><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-registry-zookeeper</artifactId><version>2.7.6</version><exclusions><exclusion><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId></exclusion></exclusions></dependency><!--實(shí)現(xiàn)自動(dòng)化創(chuàng)建節(jié)點(diǎn)路徑的父節(jié)點(diǎn)--><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.2.0</version></dependency>4.3、新建包c(diǎn)om.ebuy.service,在此包下新建HelloService接口
package com.ebuy.service;public interface HelloService {public String sayHello(String name); }4.4、新建包c(diǎn)om.ebuy.service.impl,在此包下新建接口HelloServiceImpl實(shí)現(xiàn)類(lèi)
package com.ebuy.service.impl;import com.ebuy.service.HelloService; import org.apache.dubbo.config.annotation.Service;@Service(loadbalance = "roundrobin",interfaceClass = HelloService.class) public class HelloServiceImpl implements HelloService {@Overridepublic String sayHello(String name){return "hello---"+name;} }上述loadbalance=“roundrobin”指的是用戶(hù)通過(guò)消費(fèi)者服務(wù),訪(fǎng)問(wèn)提供者時(shí),按照輪詢(xún)的負(fù)載均衡策略訪(fǎng)問(wèn)每一臺(tái)服務(wù)提供者;
- random:默認(rèn)就是隨機(jī)策略的;(推薦)
- roundrobin:依次輪詢(xún);(推薦)
- leastactive:最少活躍調(diào)用數(shù)(權(quán)重)活躍數(shù)指調(diào)用前后計(jì)數(shù)差,優(yōu)先調(diào)用高的,相同活躍數(shù)的隨機(jī)。使慢的提供者收到更少請(qǐng)求,因?yàn)樵铰奶峁┱叩恼{(diào)用前后計(jì)數(shù)差會(huì)越大;
- consistenthash :一致性策略,同參數(shù)的請(qǐng)求一定分發(fā)到同一個(gè) Provider 如果需要某一類(lèi)請(qǐng)求都到一個(gè)節(jié)點(diǎn),那么可以使用一致性 Hash 策略。
注意:@Service注解是org.apache.dubbo.config.annotation.Service包下的,不是spring包下的。
4.5、核心配置文件(使用application.yml樹(shù)狀結(jié)構(gòu))
server:port: 8081 #服務(wù)器端口號(hào) dubbo:application:name: springboot_provider #提供者應(yīng)用名registry:address: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183 #連接注冊(cè)中心集群protocol: zookeeper #dubbo采用的注冊(cè)中心協(xié)議protocol: #連接注冊(cè)中心協(xié)議port: 20881 #dubbo端口號(hào)為20880,此處我們一會(huì)為了做集群區(qū)分,先改成20881name: dubbo config-center: #配置中心timeout: 25000 #最大超時(shí)時(shí)間scan:base-packages: com.ebuy.service.impl #掃描哪個(gè)包下提供的服務(wù)4.6、啟動(dòng)第一臺(tái)provider-8081提供者服務(wù)
在maven webapps項(xiàng)目下,可以直接使用tomcat7插件,只需修改端口號(hào),就可以啟動(dòng)多臺(tái)服務(wù),在SpringBoot項(xiàng)目下,當(dāng)然也可以啟動(dòng)多臺(tái)服務(wù),如下所示:
進(jìn)入配置中心:
啟動(dòng)之前,確認(rèn)服務(wù)器端口號(hào)和dubbo端口號(hào),以及提供服務(wù)方法的返回值:
4.7、啟動(dòng)第二臺(tái)provider-8082提供者服務(wù)
修改application.yml配置文件中的端口號(hào),兩處port:
4.8、啟動(dòng)第三臺(tái)provider-8083提供者服務(wù)
修改application.yml配置文件中的端口號(hào),兩處port:
此時(shí)三臺(tái)服務(wù)提供者已經(jīng)全部啟動(dòng),但是是否成功注冊(cè)到zookeeper中心了,我們可以通過(guò)上述dubbo-admin管理控制臺(tái),查看:
到這,我們就可以很安心的往下接著走下去了,三個(gè)服務(wù)者已經(jīng)注冊(cè)到registory服務(wù)中心了。
五、創(chuàng)建服務(wù)消費(fèi)者集群服務(wù)(四個(gè))
5.1、新建SpringBoot_dubbo_consumer項(xiàng)目
5.2、引入pom.xml坐標(biāo)依賴(lài)文件
<!--springboot啟動(dòng)器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--springboot web啟動(dòng)器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--springboot 測(cè)試啟動(dòng)器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--dubbo與springboot集成啟動(dòng)器--><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.6</version></dependency><!--dubbo與注冊(cè)中心zookeeper整合包--><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-registry-zookeeper</artifactId><version>2.7.6</version><exclusions><exclusion><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId></exclusion></exclusions></dependency><!--實(shí)現(xiàn)自動(dòng)化創(chuàng)建節(jié)點(diǎn)路徑的父節(jié)點(diǎn)--><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.2.0</version></dependency><!-- 實(shí)現(xiàn)對(duì) Spring Session 使用 Redis 作為數(shù)據(jù)源的自動(dòng)化配置 --><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><!-- 實(shí)現(xiàn)對(duì) Spring Data Redis 的自動(dòng)化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><!-- 去掉對(duì) Lettuce 的依賴(lài),因?yàn)?Spring Boot 優(yōu)先使用 Lettuce 作為 Redis 客戶(hù)端 --><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><!-- 引入 Jedis 的依賴(lài),這樣 Spring Boot 實(shí)現(xiàn)對(duì) Jedis 的自動(dòng)化配置 --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>5.3、新建包c(diǎn)om.ebuy.service,在此包下新建HelloService接口,與提供者接口保持一致
package com.ebuy.service;public interface HelloService {public String sayHello(String name); }5.4、新建包c(diǎn)om.ebuy.controller,在此包下新建HelloController類(lèi)
package com.ebuy.controller;import com.ebuy.service.HelloService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest;@Controller @RequestMapping("/demo") public class HelloController {@ReferenceHelloService helloService;int port=2011;@RequestMapping("/hello")@ResponseBodypublic String getName(String name){//遠(yuǎn)程調(diào)用,獲取響應(yīng)結(jié)果String result = helloService.sayHello(name);System.out.println("consumer-" + port + "\t" + result);return result;} }注意:
@Reference HelloService helloService;此處的HelloService訪(fǎng)問(wèn)的是遠(yuǎn)程的Provider所提供的服務(wù),所有使用@Autowire注解是加載不到的,要使用@Reference注解調(diào)用遠(yuǎn)程提供者發(fā)布的@Service注解標(biāo)注的服務(wù)注冊(cè)接口。
5.5、核心配置文件(使用application.yml樹(shù)狀結(jié)構(gòu))
server:port: 2011 #服務(wù)器端口號(hào) dubbo:application:name: springboot_consumer #消費(fèi)者服務(wù)名稱(chēng)registry: #注冊(cè)中心address: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183 #zookeeper集群protocol: zookeeper #dubbo采用zookeeper注冊(cè)中心協(xié)議consumer: #消費(fèi)者節(jié)點(diǎn)check: false #啟動(dòng)時(shí)不用檢測(cè)提供者是否已經(jīng)注冊(cè)config-center:timeout: 25000 #超時(shí)時(shí)間 單位秒在啟動(dòng)消費(fèi)者前,要注意一點(diǎn),因?yàn)镾pringBoot內(nèi)部機(jī)制會(huì)自動(dòng)加載DataSource數(shù)據(jù)源和Redis相關(guān)配置,即使你沒(méi)有配任何置數(shù)據(jù)庫(kù)相關(guān)配置信息,它內(nèi)部也會(huì)默認(rèn)加載,這個(gè)時(shí)候我們啟動(dòng)消費(fèi)者服務(wù)就會(huì)出現(xiàn)如下錯(cuò)誤:
Error creating bean with name ‘enableRedisKeyspaceNotificationsInitializer‘這個(gè)時(shí)候如果你配置了數(shù)據(jù)庫(kù)和redis相關(guān)配置,暫時(shí)先全部注釋掉,然后在消費(fèi)者主入口類(lèi)的@SpringBootApplication排除運(yùn)行期間不包括的服務(wù),如下:
package com.ebuy;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, RedisAutoConfiguration.class}) public class SpringbootDubboConsumerApplication {public static void main(String[] args) {SpringApplication.run(SpringbootDubboConsumerApplication.class, args);} }@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, RedisAutoConfiguration.class}),exclude就代表不包括,排除的意思,這個(gè)時(shí)候再去逐個(gè)啟動(dòng)消費(fèi)者服務(wù)就可以了。
5.6、啟動(dòng)第一臺(tái)consumer-2011服務(wù)消費(fèi)者
5.7、啟動(dòng)第一臺(tái)consumer-2012服務(wù)消費(fèi)者
5.8、啟動(dòng)第一臺(tái)consumer-2013服務(wù)消費(fèi)者
5.9、啟動(dòng)第一臺(tái)consumer-2014服務(wù)消費(fèi)者
此時(shí)再去Dubbo-admin管理控制臺(tái)可視化界面查看:
六、使用SwitchHosts工具模擬綁定域名
6.1、修改主機(jī)配置文件hosts的只讀屬性
6.2、以管理員身份運(yùn)行SwitchHosts工具,新建域名(自定義)
七、使用Nginx反向代理(消費(fèi)者)
7.1、nginx反向代理作用
上述我們開(kāi)啟了四臺(tái)消費(fèi)者服務(wù),那么我們?cè)趺粗烂看卧L(fǎng)問(wèn)的是哪一臺(tái)服務(wù)消費(fèi)者,既然我們配置了四臺(tái)就要實(shí)現(xiàn)集群的機(jī)制,那么怎么實(shí)現(xiàn)?
這個(gè)時(shí)候Nginx作用就來(lái)了,Nginx反向代理可以實(shí)現(xiàn)負(fù)載均衡,也即是我們只需在Nginx的配置文件中配置需要通過(guò)的消費(fèi)者服務(wù),nginx內(nèi)部機(jī)制算法會(huì)自動(dòng)幫我們實(shí)現(xiàn)負(fù)載均衡,配置如下:
7.2、修改nginx配置文件
7.3、啟動(dòng)nginx
nginx啟動(dòng)之后,此時(shí)我們就可以通過(guò)www.ebuy.com域名進(jìn)行測(cè)試訪(fǎng)問(wèn)了!直接訪(fǎng)問(wèn)應(yīng)該會(huì)進(jìn)入nginx的內(nèi)置默認(rèn)頁(yè)面。
八、通過(guò)nginx反向代理,請(qǐng)求消費(fèi)者,通過(guò)消費(fèi)者訪(fǎng)問(wèn)提供者
在地址欄輸入http://www.ebuy.com/demo/hello?name=jason
8.1、第一次請(qǐng)求
查看控制臺(tái),請(qǐng)求到的是哪一臺(tái)消費(fèi)者:
8.2、第二次請(qǐng)求
查看控制臺(tái),請(qǐng)求到的是哪一臺(tái)消費(fèi)者:
8.3、第三次請(qǐng)求
查看控制臺(tái),請(qǐng)求到的是哪一臺(tái)消費(fèi)者:
8.4、第四次請(qǐng)求
查看控制臺(tái),請(qǐng)求到的是哪一臺(tái)消費(fèi)者:
由上述測(cè)試可以看出,nginx反向代理在我們第一次請(qǐng)求會(huì)隨機(jī)幫我們選一臺(tái)消費(fèi)者,然后后續(xù)請(qǐng)求就會(huì)輪詢(xún)?cè)L問(wèn)消費(fèi)者,這樣我們就實(shí)現(xiàn)了服務(wù)器的負(fù)載均衡,避免了當(dāng)訪(fǎng)問(wèn)量巨大時(shí)導(dǎo)致某一臺(tái)服務(wù)器超負(fù)載的情況。
九、解決Dubbo內(nèi)置負(fù)載均衡策略問(wèn)題
-
細(xì)心的伙子應(yīng)該可以看出上述的四次測(cè)試中,消費(fèi)者使用Nginx的反向代理實(shí)現(xiàn)了第一次隨機(jī)訪(fǎng)問(wèn),后續(xù)是依次輪詢(xún)的負(fù)載均衡策略;
-
然而but提供者卻沒(méi)有真正實(shí)現(xiàn)我們所謂的loadbalance="roundrobin"輪詢(xún)負(fù)載均衡策略,第一次8083、第二次和第三次都是8081,第四次才是8082,這顯然不符合我們所期望的輪詢(xún)機(jī)制,為什么會(huì)出現(xiàn)這樣的情況呢?
9.1、Dubbo 的內(nèi)置負(fù)載均衡策略(四種)
- Random(默認(rèn)是隨機(jī)負(fù)載)
- 隨機(jī)訪(fǎng)問(wèn)集群中節(jié)點(diǎn)。訪(fǎng)問(wèn)概率和權(quán)重有關(guān)。是 Dubbo 的默認(rèn)負(fù)載均衡策略。
- 權(quán)重(weight):
占有比例。集群中每個(gè)項(xiàng)目部署的服務(wù)器的性能可能是不同,性能好的服務(wù)器權(quán)重應(yīng)該高一些。
- RoundRobin(下面著重講解)
輪詢(xún)。訪(fǎng)問(wèn)頻率和 權(quán)重(weight) 有關(guān)。
- LeastActive
最少活躍調(diào)用數(shù),相同活躍數(shù)的隨機(jī)。如果某個(gè)機(jī)器性能越差,那么接收的請(qǐng)求越少,越不活躍,此時(shí)就會(huì)給不活躍的性能差的機(jī)器分配更少的請(qǐng)求
- ConsistentHash
一致性 Hash 算法,相同參數(shù)的請(qǐng)求一定分發(fā)到同一個(gè) Provider 如果需要某一類(lèi)請(qǐng)求都到一個(gè)節(jié)點(diǎn),那么可以使用一致性 Hash 策略。
9.2、什么是輪詢(xún)策略?
-
所謂輪詢(xún)是指將請(qǐng)求輪流分配為每臺(tái)提供者服務(wù)器,舉個(gè)栗子:假設(shè)我們有三臺(tái)服務(wù)器A、B、C。我們將第一個(gè)請(qǐng)求分配給服務(wù)器A,第二個(gè)請(qǐng)求分配給服務(wù)器B,第三個(gè)請(qǐng)求分配給服務(wù)器C,第四個(gè)請(qǐng)求分配給服務(wù)器A,也即是當(dāng)所有服務(wù)器請(qǐng)求一遍后,再次請(qǐng)求將會(huì)從第一臺(tái)服務(wù)器輪流請(qǐng)求,這個(gè)過(guò)程就叫做輪詢(xún)。
-
輪詢(xún)負(fù)載均衡策略(并不完全是輪詢(xún)的),不可忽略的一點(diǎn)是,每臺(tái)服務(wù)器之間多少都會(huì)存在一些性能上的差異,如果我們將等量的請(qǐng)求分配給某一臺(tái)性能較差的服務(wù)器,由于這臺(tái)服務(wù)器性能較差,那么再次發(fā)出請(qǐng)求,請(qǐng)求還是會(huì)在這臺(tái)性能較差的服務(wù)器上出現(xiàn),很明顯我們上述出現(xiàn)的情況就是因?yàn)槿绱?。盡管我們上述所有的服務(wù)器是在同一臺(tái)電腦上啟動(dòng)的(為了模擬),其實(shí)這也驗(yàn)證了即使是同一臺(tái)電腦,自身的服務(wù)器也會(huì)對(duì)不同的tomcat進(jìn)程分配不同的進(jìn)程占用時(shí)長(zhǎng),所以就導(dǎo)致了上述第二次和第三次請(qǐng)求訪(fǎng)問(wèn)的都是8081的情況!!!說(shuō)到這應(yīng)該可以理解了吧!
-
要知道一般情況下,每個(gè)服務(wù)都會(huì)部署到不同的電腦上,一般很少出現(xiàn)連續(xù)性能問(wèn)題的這種情況。
9.3、如何解決不完全輪詢(xún)策略(忽略性能差異)?
-
想要解決上述問(wèn)題,這個(gè)時(shí)候我們就需要對(duì)輪詢(xún)過(guò)程進(jìn)行加權(quán)(weight),以調(diào)控每臺(tái)服務(wù)器的負(fù)載,經(jīng)過(guò)加權(quán)后,每臺(tái)服務(wù)器能夠得到的請(qǐng)求數(shù)比例,接近或等于它們自身的權(quán)重比。
-
注解方式
@Service(loadbalance = "roundrobin",weight = "權(quán)重?cái)?shù)") -
配置文件方式
dubbo:provider:loadbalance: roundrobin #輪詢(xún)負(fù)載均衡策略weight: "權(quán)重?cái)?shù)" #針對(duì)每一臺(tái)服務(wù)提供者所在服務(wù)器的性能進(jìn)行權(quán)重?cái)?shù)配置(一般情況下默認(rèn)都是100)
9.4、配置負(fù)載均衡策略
配置負(fù)載均衡策略有很多種方式:
9.4.1、第一種在消費(fèi)者注解方式配置
@Controller @RequestMapping("/demo") public class HelloController {//表示在當(dāng)前業(yè)務(wù)層中所有方法都會(huì)輪詢(xún)?cè)L問(wèn)所有provider集群@Reference(loadbalance = "roundrobin") HelloService helloService;}9.4.2、第二種在消費(fèi)者配置文件yml或者properties中配置
dubbo:consumer: loadbalance: roundrobiin #此處代表針對(duì)當(dāng)前服務(wù)的所有controller層都會(huì)輪詢(xún)的訪(fǎng)問(wèn)provider集群9.4.3、第三種在提供者業(yè)務(wù)層注解方式配置
//此處配置,只在provider集群中所有服務(wù)中的(當(dāng)前業(yè)務(wù)層)對(duì)外提供輪詢(xún)服務(wù) @Service(loadbalance = "roundrobin") public class HelloServiceImpl implements HelloService {@Overridepublic String sayHello(String name){return "hello---8081----"+name;} }9.4.4、第四種在提供者配置文件方式配置
dubbo:provider:loadbalance: roundrobin #針對(duì)provider集群中所有服務(wù)的所有業(yè)務(wù)層對(duì)外提供輪詢(xún)負(fù)載均衡策略其實(shí)上述四種配置中,不推薦在消費(fèi)者一方使用負(fù)載均衡策略配置,因?yàn)樘峁┱吲渲玫氖羌悍绞?#xff0c;該怎么提供對(duì)外服務(wù),很顯然在提供者方配置最為合適,也比較高效。
一起學(xué)編程,讓生活更隨和!如果你覺(jué)得是個(gè)同道中人,歡迎關(guān)注博主公眾號(hào):【隨和的皮蛋桑】。專(zhuān)注于Java基礎(chǔ)、進(jìn)階、面試以及計(jì)算機(jī)基礎(chǔ)知識(shí)分享🐳。偶爾認(rèn)知思考、日常水文🐌。
總結(jié)
以上是生活随笔為你收集整理的分布式与微服务系列(三)、SpringBoot+Zookeeper集群+Nginx反向代理+Dubbo分布式托管(提供者、消费者)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 教育培训行业APP开发功能明细
- 下一篇: NLP+词法系列(一)︱中文分词技术小结