"微服務」一詞源於 Martin Fowler的名爲 Microservices的,博文,能夠在他的官方博客上找到http:/ /martinfowler . com/articles/microservices.html簡單地說,微服務是系統架構上的一種設計風格,它的主旨是將一個本來獨立的系統拆分紅多個小型服務,這些小型服務都在各自獨立的進程中運行,服務之間經過基於HTTP的 RESTfuL AP進行通訊協做。常見微服務框架:Spring的spring cloud、阿里dubbo、華爲ServiceComb、騰訊Tars、Facebook thrift、新浪微博Motan。本章節咱們先從瞭解組成完整系統的各個組件開始,下章節將利用這些組件,搭建出一個完善的分佈式系統。html
這就不用多說了,官網有詳細的介紹。java
Spring Cloud ɵɹibaba 致力於提供微服務開發的一站式解決方案。此項目包含開發分佈式應用微服務的必需組件,方便開發者經過 Spring Cloud 編程模型輕鬆使用這些組件來開發分佈式應用服務mysql
主要組件
Sentinel:把流量做爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。
Nacos:一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平臺。
RocketMQ:一款開源的分佈式消息系統,基於高可用分佈式集羣技術,提供低延時的、高可靠的消息發佈與訂閱服務。
Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。
Seata:阿里巴巴開源產品,一個易於使用的高性能微服務分佈式事務解決方案。git
Eureka:官方宣佈2.x再也不開源(閉源),以前的版本已經中止更新;也就說Eureka未來更多的技術提高已經沒有了。因此,若是但願註冊中心有更多強大功能的話,還須要另闢蹊徑 。
Zookeeper:在企業級Zookeeper註冊中心與 Dubbo組合比較多一些,kafka使用的也是,隨着Eureka的停更,咱們能夠經過spring-cloud-starter-zookeeper-discovery這個啓動器,將Zookeeper作爲springcloud的註冊中心。
Consul:go語言開發的,也是一個優秀的服務註冊框架,使用量也比較多。
Nacos:來自於SpringCloudɵɹibaba,在企業中通過了百萬級註冊考驗的,不但能夠完美替換Eureka,還能作其餘組件的替換,因此,Naocs也強烈建議使用。github
Nacos(Dynamic Naming and Configur ation Service) 是阿里巴巴2018年7月開源的項目,致力於發現、配置和管理微服務。web
--下載鏡像 docker pull nacos/nacos-server:1.3.1 --啓動容器 docker run --name nacos --env MODE=standalone --privileged=true -p 8848:8848 --restart=always -d dc833dc45d8f
訪問:spring
http://127.0.0.1:8848/nacos 帳號密碼都是nacossql
安裝前提docker
64 bit OS Linux/Unix/Mac,推薦使用Linux系統。 集羣須要依賴mysql,單機可沒必要 3個或3個以上Nacos節點才能構成集羣
一、須要去Nacos官網clone Nacos集羣項目nacos-docker
二、nacos-docker是使用的Docker Compose對容器進行編排,因此首先須要安裝Docker Compose詳細信息可參照Nacos官網:https:/ /nacos.io/zh-cn/docs/quick-start-docker.htmlshell
1)安裝Docker Compose
什麼是Docker Compose
Compose項目是Docker官方的開源項目,負責實現對Docker容器集羣的快速編排。
#在Linux下下載(下載到/usr/local/bin) curl -L https://github.com/docker/compose/releases/download/1.25.0/run.sh > /usr/local/bin/docker-compose # 設置文件可執行權限 chmod +x /usr/local/bin/docker-compose # 查看版本信息 docker-compose --version
2)克隆Nacos-docker項目
#切換到自定義目錄 cd /usr/local/nacos #開始clone git clone https://github.com/nacos-group/nacos-docker.git
3)運行nacos-docker腳本
#執行編排命令 docker-compose -f /usr/local/nacos/nacos-docker/example/cluster-hostname.yaml up
上面的編排命令主要下載mysql鏡像和nacos鏡像,自動完成鏡像下載/容器啓動
Pulling from nacos/nacos-mysql,版本是5. 7(執行初始化腳本)
Pulling nacos3 (nacos/nacos-server:latest)最新版本
4)中止、啓動
#啓動 docker-compose -f /usr/local/nacos/nacos-docker/example/cluster-hostname.yaml start
#中止 docker-compose -f /usr/local/nacos/nacos-docker/example/cluster-hostname.yaml stop
5)訪問Nacos
http://192.168.1.1:8848/nacos http://192.168.1.1:8849/nacos http://192.168.1.1:8850/nacos
服務提供者能夠經過 Nacos 的服務註冊發現功能將其服務註冊到 Nacos server 上。
添加nacos依賴
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>${latest.version}</version> </dependency>
添加配置
server.port=8070 spring.application.name=nacos-demo spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
啓動類
@SpringBootApplication @EnableDiscoveryClient public class NacosProviderApplication { public static void main(String[] args) { SpringApplication.run(NacosProviderApplication.class, args); } @RestController class EchoController { @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET) public String echo(@PathVariable String string) { return "Hello Nacos Discovery " + string; } } }
啓動後,控制檯:
說明註冊成功,後臺查看該服務:
下面咱們用spring cloud 整合naocs實現服務調用
添加配置
server.port=8080 spring.application.name=service-consumer spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
添加啓動類:服務消費者使用 @LoadBalanced RestTemplate 實現服務調用
@SpringBootApplication @EnableDiscoveryClient public class NacosConsumerApplication { @LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(NacosConsumerApplication.class, args); } @RestController public class TestController { private final RestTemplate restTemplate; @Autowired public TestController(RestTemplate restTemplate) {this.restTemplate = restTemplate;} @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET) public String echo(@PathVariable String str) { return restTemplate.getForObject("http://service-provider/echo/" + str, String.class); } } }
啓動 ProviderApplication
和 ConsumerApplication
,調用 http://localhost:8080/echo/2018
,返回內容爲 Hello Nacos Discovery 2018
。
目前市面上用的比較多的配置中心有(時間順序)
Disconf:2014年7月百度開源的配置管理中心,一樣具有配置的管理能力,不過目前已經不維護了,最近的一次提交是4-5年前了。
Spring Cloud Config:2014年9月開源,Spring Cloud 生態組件,能夠和Spring Cloud體系無縫整合。
Apollo:2016年5月,攜程開源的配置管理中心,具有規範的權限、流程治理等特性。
Nacos:2018年6月,阿里開源的配置中心,也能夠作DNS和RPC的服務發現
啓動了 Nacos server 後,您就能夠參考如下示例代碼,爲您的 Spring Cloud 應用啓動 Nacos 配置管理服務了。完整示例代碼請參考:nacos-spring-cloud-config-example
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>${latest.version}</version> </dependency>
注意:版本 2.1.x.RELEASE 對應的是 Spring Boot 2.1.x 版本。版本 2.0.x.RELEASE 對應的是 Spring Boot 2.0.x 版本,版本 1.5.x.RELEASE 對應的是 Spring Boot 1.5.x 版本。
更多版本對應關係參考:版本說明 Wiki
bootstrap.properties
中配置 Nacos server 的地址和應用名spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.application.name=example
說明:之因此須要配置 spring.application.name
,是由於它是構成 Nacos 配置管理 dataId
字段的一部分。
在 Nacos Spring Cloud 中,dataId
的完整格式以下:
${prefix}-${spring.profiles.active}.${file-extension}
prefix
默認爲 spring.application.name
的值,也能夠經過配置項 spring.cloud.nacos.config.prefix
來配置。spring.profiles.active
即爲當前環境對應的 profile,詳情能夠參考 Spring Boot文檔。 注意:當 spring.profiles.active
爲空時,對應的鏈接符 -
也將不存在,dataId 的拼接格式變成 ${prefix}.${file-extension}
file-exetension
爲配置內容的數據格式,能夠經過配置項 spring.cloud.nacos.config.file-extension
來配置。目前只支持 properties
和 yaml
類型。@RefreshScope
實現配置自動更新:@RestController @RequestMapping("/config") @RefreshScope public class ConfigController { @Value("${useLocalCache:false}") private boolean useLocalCache; @RequestMapping("/get") public boolean get() { return useLocalCache; } }
example.properties
,內容爲useLocalCache=true
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example.properties&group=DEFAULT_GROUP&content=useLocalCache=true"
NacosConfigApplication
,調用 curl http://localhost:8080/config/get
,返回內容是 true
。example.properties
,內容爲useLocalCache=false
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example.properties&group=DEFAULT_GROUP&content=useLocalCache=false"
http://localhost:8080/config/get
,此時返回內容爲false
,說明程序中的useLocalCache
值已經被動態更新了。RPC 的主要功能目標是讓構建分佈式計算(應用)更容易,在提供強大的遠程調用能力時不損失本地調用的語義簡潔性。爲實現該目標,RPC 框架需提供一種透明調用機制,讓使用者沒必要顯式的區分本地調用和遠程調用。
RPC的優勢:分佈式設計、部署靈活、解耦服務、擴展性強。
Dubbo:國內最先開源的 RPC 框架,由阿里巴巴公司開發並於 2011 年底對外開源,僅支持 Java 語言。
Motan:微博內部使用的 RPC 框架,於 2016 年對外開源,僅支持 Java 語言。
Tars:騰訊內部使用的 RPC 框架,於 2017 年對外開源,僅支持 C++ 語言。
Spring Cloud:國外 Pivotal 公司 2014 年對外開源的 RPC 框架,提供了豐富的生態組件。
gRPC:Google 於 2015 年對外開源的跨語言 RPC 框架,支持多種語言。
Thrift:最初是由 Facebook 開發的內部系統跨語言的 RPC 框架,2007 年貢獻給了 Apache 基金,成爲
Apache:開源項目之一,支持多種語言。
RPC框架通常使用長連接,沒必要每次通訊都要3次握手,減小網絡開銷。
RPC框架通常都有註冊中心,有豐富的監控管理髮布、下線接口、動態擴展等,對調用方來講是無感知、統一化的操做協議私密,安全性較高
RPC 協議更簡單內容更小,效率更高,服務化架構、服務化治理,RPC框架是一個強力的支撐。
因爲 Dubbo Spring Cloud 構建在原生的 Spring Cloud 之上, 其服務治理方面的能力可認爲是 Spring Cloud Plus,不只徹底覆蓋 Spring Cloud 原生特性,並且提供更爲穩定和成熟的實現,特性比對以下表所示:
默認狀況,Spring Cloud Open Feign 以及@LoadBalanced`RestTemplate 做爲 Spring Cloud 的兩種服務調用方式。 Dubbo Spring Cloud 爲其提供了第三種選擇,即 Dubbo 服務將做爲 Spring Cloud 服務調用的同等公民出現,應用可經過 Apache Dubbo 註解@Service 和@Reference 暴露和引用 Dubbo 服務,實現服務間多種協議的通信。同時,也能夠利用 Dubbo 泛化接口輕鬆實現服務網關。
按照傳統的 Dubbo 開發模式,在構建服務提供者以前,第一個步驟是爲服務提供者和服務消費者定義 Dubbo 服務接口。
爲了確保契約的一致性,推薦的作法是將 Dubbo 服務接口打包在第二方或者第三方的 artifact(jar)中,該 artifact 甚至無需添加任何依賴。
對於服務提供方而言,不只經過依賴 artifact 的形式引入 Dubbo 服務接口,並且須要將其實現。對應的服務消費端,一樣地須要依賴該 artifact,並以接口調用的方式執行遠程方法。接下來的步驟則是建立 artifact。
建立一個api模塊,專門寫各類接口的:
/** * @author 原 * @date 2020/12/8 * @since 1.0 **/ public interface TestService { String getMsg(); }
導入依賴
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.2.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> <!-- api接口的依賴包--> <dependency> <groupId>com.dubbo.demo</groupId> <artifactId>dubbo-demo-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
編寫配置
dubbo: scan: # dubbo 服務掃描基準包 base-packages: org.springframework.cloud.alibaba.dubbo.bootstrap protocol: # dubbo 協議 name: dubbo # dubbo 協議端口( -1 表示自增端口,從 20880 開始) port: -1 spring: cloud: nacos: # Nacos 服務發現與註冊配置 discovery: server-addr: 127.0.0.1:8848實現
/** * @author 原 * @date 2021/1/28 * @since 1.0 **/ @Service//dubbo的service註解 public class TestServiceImpl implements TestService { @Override public String getMsg() { return "123123"; } }
啓動類
/** * @author 原 * @date 2021/1/28 * @since 1.0 **/ @SpringBootApplication @EnableDiscoveryClient public class DubboProviderApplication { public static void main(String[] args) { SpringApplication.run(DubboProviderApplication.class,args); } }
除了api的實現類 其餘複用提供者的代碼
編寫測試類
/** * @author 原 * @date 2021/1/28 * @since 1.0 **/ @RestController public class TestController { @Reference TestService testService; @GetMapping("/dubbo/test") public String getMsg(){ return testService.getMsg(); } }
訪問:
返回111
流量是很是隨機性的、不可預測的。前一秒可能還風平浪靜,後一秒可能就出現流量洪峯了(例如雙十一零點的場景)。然而咱們系統的容量老是有限的,若是忽然而來的流量超過了系統的承受能力,就可能會致使請求處理不過來,堆積的請求處理緩慢,CPU/Load飆高,最後致使系統崩潰。所以,咱們須要針對這種突發的流量來進行限制,在儘量處理請求的同時來保障服務不被打垮,這就是流量控制。
一個服務經常會調用別的模塊,多是另外的一個遠程服務、數據庫,或者第三方API 等。例如,支付的時候,可能須要遠程調用銀聯提供的 API;查詢某個商品的價格,可能須要進行數據庫查詢。然而,這個被依賴服務的穩定性是不能保證的。若是依賴的服務出現了不穩定的狀況,請求的響應時間變長,那麼調用服務的方法的響應時間也會變長,線程會產生堆積,最終可能耗盡業務自身的線程池,服務自己也變得不可用。
現代微服務架構都是分佈式的,由很是多的服務組成。不一樣服務之間相互調用,組成複雜的調用鏈路。以上的問題在鏈路調用中會產生放大的效果。複雜鏈路上的某一環不穩定,就可能會層層級聯, 最終致使整個鏈路都不可用。 所以咱們須要對不穩定的弱依賴服務進行熔斷降級,暫時切斷不穩定調用,避免局部不穩定因素致使總體的雪崩。
關於容錯組件的停更/升級/替換
服務降級:
Hystrix:官網不極力推薦,可是中國企業中還在大規模使用,對於限流和熔斷降級雖然在1 .5版本官方還支持(版本穩定),
但如今官方已經開始推薦你們使用Resilience4j
Resilience4J:官網推薦使用,可是國內不多用這個。
Sentienl:來自於Spring Cloud Alibaba,在中國企業替換Hystrix的組件,國內強烈建議使用
這裏就主要介紹下Sentinel。
Sentinel是阿里開源的項目,提供了流量控制、熔斷降級、系統負載保護等多個維度來保障服務之間的穩定性。
Sentinel的流控操做起來很是簡單,在控制檯進行配置便可看見效,所見即所得
Sentinel 具備如下特徵:
官網
https://github.com/alibaba/Sentinel 中文 https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D https://sentinelguard.io/zh-cn/docs/introduction.html
Sentinel 的使用能夠分爲兩個部分:
核心庫(Java 客戶端):不依賴任何框架/庫,可以運行於 Java 7 及以上的版本的運行時環境,同時對Dubbo / Spring Cloud 等框架也有較好的支持。
控制檯(Dashboard):控制檯主要負責管理推送規則、監控、集羣限流分配管理、機器發現等
使用場景
在服務提供方(Service Provider)的場景下,咱們須要保護服務提供方自身不被流量洪峯打垮。 這時候一般根據服務提供方的服務能力進行流量控制, 或針對特定的服務調用方進行限制。咱們能夠結合前期壓測評估核心口的承受能力,配置 QPS 模式的限流,當每秒的請求量超過設定的閾值時,會自動拒絕多餘的請求。
爲了不調用其餘服務時被不穩定的服務拖垮自身,咱們須要在服務調用端(Service Consumer)對不穩定服務依賴進行隔離和熔斷。手段包括信號量隔離、異常比例降級、RT 降級等多種手段。
當系統長期處於低水位的狀況下, 流量忽然增長時, 直接把系統拉昇到高水位可能瞬間把系統壓垮。這時候咱們能夠藉助 Sentinel 的 WarmUp 流控模式控制經過的流量緩慢增長,在必定時間內逐漸增長到閾值上限,而不是在一瞬間所有放行。這樣能夠給冷系統一個預熱的時間,避免冷系統被壓垮。
利用 Sentinel 的勻速排隊模式進行「削峯填谷」, 把請求突刺均攤到一段時間內, 讓系統負載保持在請求處理水位以內,同時儘量地處理更多請求。
利用 Sentinel 的網關流控特性,在網關入口處進行流量防禦,或限制 API 的調用頻率。
一、下載jar包https://github.com/alibaba/Sentinel/releases
二、啓動
java -Dserver.port=8787 -Dcsp.sentinel.dashboard.server=127.0.0.1:8787 -Dproject.name=sentinel-dashboard -jar /home/sentinel/sentinel-dashboard-1.8.0.jar
三、訪問
http://127.0.0.1:8787/#/login
初始帳號密碼sentinel/sentinel
能夠看到sentinel是本身自己的監控
一、導入依賴
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> <version>1.8.0</version> </dependency>
二、測試類
public class TestService { public static void main(String[] args) { initFlowRules(); while (true) { Entry entry = null; try { entry = SphU.entry("HelloWorld"); /*您的業務邏輯 - 開始*/ System.out.println("hello world"); /*您的業務邏輯 - 結束*/ } catch (BlockException e1) { /*流控邏輯處理 - 開始*/ System.out.println("block!"); /*流控邏輯處理 - 結束*/ } finally { if (entry != null) { entry.exit(); } } } } //設置流量控制規則 設置當QPS達到20時 會限制流量(拋出異常,能夠執行處理) private static void initFlowRules(){ List<FlowRule> rules = new ArrayList<>(); FlowRule rule = new FlowRule(); rule.setResource("HelloWorld"); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // Set limit QPS to 20. rule.setCount(20); rules.add(rule); FlowRuleManager.loadRules(rules); } }
執行結果:
能夠看到,這個程序每秒穩定輸出 "hello world" 20 次,和規則中預先設定的閾值是同樣的。 block表示被阻止的請求。
官方使用文檔:https://github.com/alibaba/Sentinel/wiki/如何使用
導入依賴
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> </dependencies>
配置
server.port=8082 spring.application.name=sentinel-demo spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.sentinel.transport.dashboard=127.0.0.1:8787
//在須要流控的方法加上@SentinelResource @RestController public class TestController { @GetMapping("/sentinel") @SentinelResource public String getMsg(){ return "11"; } }
啓動應用,訪問http://127.0.0.1:8082/sentinel後去sentinel後臺
下面咱們來配一條最簡單的流控規則。針對 sentinel_spring_web_context /sentinel 這個服務調用配置限流規則(須要有過訪問量才能看到)。咱們配一條 QPS 爲 1的流控規則,這表明針對該服務方法的調用每秒鐘不能超過 1 次,超出會直接拒絕。
如今快速訪問:http://localhost:8082/sentinel
查看實時監控頁面:
其餘功能的使用,你們能夠參考官方文檔自行摸索。
如下是 Sent inel 與其它fault-tolerance 組件的對比:
待續...