SpringCloud總結
微服務化
微服務化的核心就是將傳統的一站式應用,根據業務拆分成一個一個的服務,徹底 地去耦合,每一個微服務提供單個業務功能的服務,一個服務做一件事, 從技術角度看就是一種小而獨立的處理過程,類似進程概念,能夠自行單獨啟動 或銷毀,擁有自己獨立的數據庫。
微服務條目落地技術備注
服務開發Springboot、Spring、SpringMVC
服務配置與管理Netflix公司的Archaius、阿里的Diamond等
服務注冊與發現Eureka、Consul、Zookeeper等
服務調用Rest、RPC、gRPC
服務熔斷器Hystrix、Envoy等
負載均衡Ribbon、Nginx等
服務接口調用(客戶端調用服務的簡化工具)Feign等
消息隊列Kafka、RabbitMQ、ActiveMQ等
服務配置中心管理SpringCloudConfig、Chef等
服務路由(API網關)Zuul等
服務監控Zabbix、Nagios、Metrics、Spectator等
全鏈路追蹤Zipkin,Brave、Dapper等
服務部署Docker、OpenStack、Kubernetes等
數據流操作開發包SpringCloud Stream(封裝與Redis,Rabbit、Kafka等發送接收消息)
事件消息總線Spring Cloud Bus......
SpringCloud是什么?
SpringCloud,基於SpringBoot提供了一套微服務解決方案,包括服務注冊與發現,配置中心,全鏈路監控,服務網關,負載均衡,熔斷器等組件,除了基於NetFlix的開源組件做高度抽象封裝之外,還有一些選型中立的開源組件。
SpringCloud利用SpringBoot的開發便利性巧妙地簡化了分布式系統基礎設施的開發,SpringCloud為開發人員提供了快速構建分布式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理、事件總線、全局鎖、決策競選、分布式會話等等,它們都可以用SpringBoot的開發風格做到一鍵啟動和部署。
SpringBoot並沒有重復制造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過SpringBoot風格進行再封裝屏蔽掉了復雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分布式系統開發工具包
SpringCloud=分布式微服務架構下的一站式解決方案, 是各個微服務架構落地技術的集合體,俗稱微服務全家桶
SpringCloud和SpringBoot是什么關系?
SpringBoot專注於快速方便的開發單個個體微服務。
SpringCloud是關注全局的微服務協調整理治理框架,它將SpringBoot開發的一個個單體微服務整合並管理起來, 為各個微服務之間提供,配置管理、服務發現、斷路器、路由、微代理、事件總線、全局鎖、決策競選、分布式會話等等集成服務
SpringBoot可以離開SpringCloud獨立使用開發項目,但是SpringCloud離不開SpringBoot,屬於依賴的關系.
SpringBoot專注於快速、方便的開發單個微服務個體,SpringCloud關注全局的服務治理框架。
上手
1.Rest微服務構建案例工程模塊
microservicecloud整體父工程Project
1.新建父工程microservicecloud
切記是Packageing是pom模式
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
2.microservicecloud-api公共子模塊Module
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent><!-- 子類里面顯示聲明才能有明確的繼承表現,無意外就是父類的默認版本否則自己定義 -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
新建部門Entity且配合lombok使用放在該包下,這個模塊是用來被引用的
3.microservicecloud-provider-dept-8001 部門微服務提供者Module
1.新建microservicecloud-provider-dept-8001
2.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
3.application.yml
server
4.工程src/main/resources目錄下新建mybatis文件夾后新建mybatis.cfg.xml文件
5.MySQL創建部門數據庫腳本
DROP DATABASE IF EXISTS cloudDB01;
CREATE DATABASE cloudDB01 CHARACTER SET UTF8;
USE cloudDB01;
CREATE TABLE dept
(
deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
dname VARCHAR(60),
db_source VARCHAR(60)
);
INSERT INTO dept(dname,db_source) VALUES('開發部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('財務部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('市場部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('運維部',DATABASE());
SELECT * FROM dept;
6.DeptDao部門接口
package com.atguigu.springcloud.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.atguigu.springcloud.entities.Dept;
7.工程src/main/resources/mybatis目錄下新建mapper文件夾后再建DeptMapper.xml
8.DeptService部門服務接口
package com.atguigu.springcloud.service;
import java.util.List;
import com.atguigu.springcloud.entities.Dept;
public interface DeptService
{
public boolean add(Dept dept);
public Dept get(Long id);
public List<Dept> list();
}
9.DeptServiceImpl部門服務接口實現類
package com.atguigu.springcloud.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.atguigu.springcloud.dao.DeptDao; import com.atguigu.springcloud.entities.Dept; import com.atguigu.springcloud.service.DeptService; @Service public class DeptServiceImpl implements DeptService { @Autowired private DeptDao dao ; @Override public boolean add(Dept dept) { return dao.addDept(dept); } @Override public Dept get(Long id) { return dao.findById(id); } @Override public List<Dept> list() { return dao.findAll(); } }
10.DeptController部門微服務提供者REST
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.atguigu.springcloud.entities.Dept; import com.atguigu.springcloud.service.DeptService; @RestController public class DeptController { @Autowired private DeptService service; @RequestMapping(value="/dept/add",method=RequestMethod.POST) public boolean add(@RequestBody Dept dept) { return service.add(dept); } @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET) public Dept get(@PathVariable("id") Long id) { return service.get(id); } @RequestMapping(value="/dept/list",method=RequestMethod.GET) public List<Dept> list() { return service.list(); } }
11.DeptProvider8001_App主啟動類DeptProvider8001_App
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class, args); } }
12.測試
http://localhost:8001/dept/get/2
http://localhost:8001/dept/list
4.microservicecloud-consumer-dept-80部門微服務消費者Module
1.新建microservicecloud-consumer-dept-80
2.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-consumer-dept-80</artifactId> <description>部門微服務消費者</description> <dependencies> <dependency><!-- 自己定義的api --> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 修改后立即生效,熱部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
3.YML
server: port: 80
4.com.atguigu.springcloud.cfgbeans包下ConfigBean的編寫(類似spring里面的applicationContext.xml寫入的注入Bean)
package com.atguigu.springcloud.cfgbeans; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ConfigBean { @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } }
5.com.atguigu.springcloud.controller包下新建DeptController_Consumer部門微服務消費者REST
RestTemplate是什么?
RestTemplate提供了多種便捷訪問遠程Http服務的方法, 是一種簡單便捷的訪問restful服務模板類,是Spring提供的用於訪問Rest服務的客戶端模板工具集
(url, requestMap, ResponseBean.class)這三個參數分別代表 REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型。
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.atguigu.springcloud.entities.Dept; @RestController public class DeptController_Consumer { private static final String REST_URL_PREFIX = "http://localhost:8001"; @Autowired private RestTemplate restTemplate; @RequestMapping(value="/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class); } @RequestMapping(value="/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id, Dept.class); } @SuppressWarnings("unchecked") @RequestMapping(value="/consumer/dept/list") public List<Dept> list() { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class); } }
6.DeptConsumer80_App主啟動類
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DeptConsumer80_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_App.class, args); } }
7.測試
http://localhost/consumer/dept/get/2
http://localhost/consumer/dept/list
http://localhost/consumer/dept/add?dname=AI
2.Eureka服務注冊與發現
Eureka是什么
Eureka是Netflix的一個子模塊,也是核心模塊之一。Eureka是一個基於REST的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。
服務注冊與發現對於微服務架構來說是非常重要的,有了服務發現與注冊,只需要使用服務的標識符,就可以訪問到服務,而不需要修改服務調用的配置文件了。功能類似於dubbo的注冊中心,比如Zookeeper。
Eureka的基本架構
Spring Cloud 封裝了 Netflix 公司開發的 Eureka 模塊來實現服務注冊和發現(請對比Zookeeper)。
Eureka 采用了 C-S 的設計架構。Eureka Server 作為服務注冊功能的服務器,它是服務注冊中心。
而系統中的其他微服務,使用 Eureka 的客戶端連接到 Eureka Server並維持心跳連接。這樣系統的維護人員就可以通過 Eureka Server 來監控系統中各個微服務是否正常運行。SpringCloud 的一些其他模塊(比如Zuul)就可以通過 Eureka Server 來發現系統中的其他微服務,並執行相關的邏輯。 請注意和Dubbo的架構對比
Eureka包含兩個組件:Eureka Server和Eureka Client Eureka Server提供服務注冊服務 各個節點啟動后,會在EurekaServer中進行注冊,這樣EurekaServer中的服務注冊表中將會存儲所有可用服務節點的信息,服務節點的信息可以在界面中直觀的看到
EurekaClient是一個Java客戶端,用於簡化Eureka Server的交互,客戶端同時也具備一個內置的、使用輪詢(round-robin)負載算法的負載均衡器。在應用啟動后,將會向Eureka Server發送心跳(默認周期為30秒)。如果Eureka Server在多個心跳周期內沒有接收到某個節點的心跳,EurekaServer將會從服務注冊表中把這個服務節點移除(默認90秒)
Eureka Server 提供服務注冊和發現
Service Provider服務提供方將自身服務注冊到Eureka,從而使服務消費方能夠找到
Service Consumer服務消費方從Eureka獲取注冊服務列表,從而能夠消費服務
1.microservicecloud-eureka-7001
eureka服務注冊中心Module
1.新建microservicecloud-eureka-7001
2.POM.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-eureka-7001</artifactId> <dependencies> <!--eureka-server服務端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <!-- 修改后立即生效,熱部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
3.YML
server: port: 7001 eureka: instance: hostname: localhost #eureka服務端的實例名稱 client: register-with-eureka: false #false表示不向注冊中心注冊自己。 fetch-registry: false #false表示自己端就是注冊中心,我的職責就是維護服務實例,並不需要去檢索服務 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #設置與Eureka Server交互的地址查詢服務和注冊服務都需要依賴這個地址。
4.EurekaServer7001_App主啟動類
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer//EurekaServer服務器端啟動類,接受其它微服務注冊進來 public class EurekaServer7001_App { public static void main(String[] args) { SpringApplication.run(EurekaServer7001_App.class, args); } }
5.測試
No application available 沒有服務被發現 O(∩_∩)O 因為沒有注冊服務進來當然不可能有服務被發現
2.microservicecloud-provider-dept-8001
將已有的部門微服務注冊進eureka服務中心
1.修改microservicecloud-provider-dept-8001
2.pom
修改的部分
<!-- 將微服務provider側注冊進eureka --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
完整
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-provider-dept-8001</artifactId> <dependencies> <!-- 引入自己定義的api通用包,可以使用Dept部門Entity --> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <!-- 將微服務provider側注冊進eureka --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- 修改后立即生效,熱部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
3.YML
修改
eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7001/eureka
完整
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路徑 type-aliases-package: com.atguigu.springcloud.entities # 所有Entity別名類所在包 mapper-locations: - classpath:mybatis/mapper/**/*.xml # mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource # 當前數據源操作類型 driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包 url: jdbc:mysql://localhost:3306/cloudDB01 # 數據庫名稱 username: root password: 123456 dbcp2: min-idle: 5 # 數據庫連接池的最小維持連接數 initial-size: 5 # 初始化連接數 max-total: 5 # 最大連接數 max-wait-millis: 200 # 等待連接獲取的最大超時時間 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7001/eureka
4.DeptProvider8001_App主啟動類
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient //本服務啟動后會自動注冊進eureka服務中 public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class, args); } }
5.測試
先要啟動EurekaServer
微服務注冊名配置說明
actuator與注冊微服務信息完善
1.問題:含有主機名稱
主機名稱:服務名稱修改
<1>修改microservicecloud-provider-dept-8001
修改部分
eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001
完整
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路徑 type-aliases-package: com.atguigu.springcloud.entities #entity別名類 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001
2.當前問題:沒有IP提示
修改microservicecloud-provider-dept-8001
eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001 #自定義服務名稱信息 prefer-ip-address: true #訪問路徑可以顯示IP地址
3.微服務info內容詳細信息
超鏈接點擊服務報告ErrorPage
修改microservicecloud-provider-dept-8001
修改
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-provider-dept-8001</artifactId> <dependencies> <!-- 引入自己定義的api通用包,可以使用Dept部門Entity --> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <!-- 將微服務provider側注冊進eureka --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!-- actuator監控信息完善 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- 修改后立即生效,熱部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
總的父工程microservicecloud修改pom.xml添加構建build信息
<build> <finalName>microservicecloud</finalName> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <delimiters> <delimit>$</delimit> </delimiters> </configuration> </plugin> </plugins> </build>
修改microservicecloud-provider-dept-8001
info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路徑 type-aliases-package: com.atguigu.springcloud.entities #entity別名類 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001 #自定義服務名稱信息 prefer-ip-address: true #訪問路徑可以顯示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
eureka自我保護
導致原因:一句話:某時刻某一個微服務不可用了,eureka不會立刻清理,依舊會對該微服務的信息進行保存
eureka集群配置
新建microservicecloud-eureka-7002/microservicecloud-eureka-7003
找到C:\Windows\System32\drivers\etc路徑下的hosts文件
127.0.0.1 eureka7001.com,127.0.0.1 eureka7002.com,127.0.0.1 eureka7003.com
7001
server: port: 7001 eureka: instance: hostname: eureka7001.com #eureka服務端的實例名稱 client: register-with-eureka: false #false表示不向注冊中心注冊自己。 fetch-registry: false #false表示自己端就是注冊中心,我的職責就是維護服務實例,並不需要去檢索服務 service-url: #單機 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #設置與Eureka Server交互的地址查詢服務和注冊服務都需要依賴這個地址(單機)。 defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
7002
server: port: 7002 eureka: instance: hostname: eureka7002.com #eureka服務端的實例名稱 client: register-with-eureka: false #false表示不向注冊中心注冊自己。 fetch-registry: false #false表示自己端就是注冊中心,我的職責就是維護服務實例,並不需要去檢索服務 service-url: #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #設置與Eureka Server交互的地址查詢服務和注冊服務都需要依賴這個地址。 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
7003
server: port: 7003 eureka: instance: hostname: eureka7003.com #eureka服務端的實例名稱 client: register-with-eureka: false #false表示不向注冊中心注冊自己。 fetch-registry: false #false表示自己端就是注冊中心,我的職責就是維護服務實例,並不需要去檢索服務 service-url: #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #設置與Eureka Server交互的地址查詢服務和注冊服務都需要依賴這個地址。 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
microservicecloud-provider-dept-8001 微服務發布到上面3台eureka集群配置中
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路徑 type-aliases-package: com.atguigu.springcloud.entities #entity別名類 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8001 #自定義服務名稱信息 prefer-ip-address: true #訪問路徑可以顯示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
3.Ribbon負載均衡
Ribbon負載均衡是什么?
Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端 負載均衡的工具。
簡單的說,Ribbon是Netflix發布的開源項目,主要功能是提供客戶端的軟件負載均衡算法,將Netflix的中間層服務連接在一起。Ribbon客戶端組件提供一系列完善的配置項如連接超時,重試等。簡單的說,就是在配置文件中列出Load Balancer(簡稱LB)后面所有的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連接等)去連接這些機器。我們也很容易使用Ribbon實現自定義的負載均衡算法。
Ribbon配置初步
-
修改microservicecloud-consumer-dept-80工程
-
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-consumer-dept-80</artifactId> <description>部門微服務消費者</description> <dependencies> <dependency><!-- 自己定義的api --> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 修改后立即生效,熱部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!-- Ribbon相關 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> </dependencies> </project>
3.yml
server: port: 80 eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
4.對ConfigBean進行新注解@LoadBalanced 獲得Rest時加入Ribbon的配置
package com.atguigu.springcloud.cfgbeans; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ConfigBean { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
5.主啟動類DeptConsumer80_App添加@EnableEurekaClient
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class DeptConsumer80_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_App.class, args); } }
6.修改DeptController_Consumer客戶端訪問類
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.atguigu.springcloud.entities.Dept; @RestController public class DeptController_Consumer { //private static final String REST_URL_PREFIX = "http://localhost:8001"; //因為使用了注冊中心,所以不用url直接寫名字 private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT"; @Autowired private RestTemplate restTemplate; @RequestMapping(value="/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class); } @RequestMapping(value="/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id, Dept.class); } @SuppressWarnings("unchecked") @RequestMapping(value="/consumer/dept/list") public List<Dept> list() { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class); } }
7.測試
先啟動3個eureka集群后,再啟動microservicecloud-provider-dept-8001並注冊進eureka
啟動microservicecloud-consumer-dept-80
http://localhost/consumer/dept/get/1
http://localhost/consumer/dept/list
http://localhost/consumer/dept/add?dname=大數據部
小結:Ribbon和Eureka整合后Consumer可以直接調用服務而不用再關心地址和端口號
Ribbon負載均衡
1.參考microservicecloud-provider-dept-8001,新建兩份,分別命名為8002,8003
2.修改8002/8003各自YML
3.啟動3個eureka集群配置區
4.客戶端通過Ribbo完成負載均衡並訪問上一步的Dept微服務
http://localhost/consumer/dept/list
注意觀察看到返回的數據庫名字,各不相同,負載均衡實現
自定義Rule
在ConfigBean 中創建一個IRule的實現類加上@Bean
@Bean
public IRule myRule() { return new RandomRule(); }
4.Feign負載均衡
官網解釋: http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign
Feign是一個聲明式WebService客戶端。使用Feign能讓編寫Web Service客戶端更加簡單, 它的使用方法是定義一個接口,然后在上面添加注解,同時也支持JAX-RS標准的注解。Feign也支持可拔插式的編碼器和解碼器。Spring Cloud對Feign進行了封裝,使其支持了Spring MVC標准注解和HttpMessageConverters。Feign可以與Eureka和Ribbon組合使用以支持負載均衡。
Feign是一個聲明式的Web服務客戶端,使得編寫Web服務客戶端變得非常容易, 只需要創建一個接口,然后在上面添加注解即可。 參考官網:https://github.com/OpenFeign/feign
Feign能干什么 Feign旨在使編寫Java Http客戶端變得更容易。 前面在使用Ribbon+RestTemplate時,利用RestTemplate對http請求的封裝處理,形成了一套模版化的調用方法。但是在實際開發中,由於對服務依賴的調用可能不止一處,往往一個接口會被多處調用,所以通常都會針對每個微服務自行封裝一些客戶端類來包裝這些依賴服務的調用。所以,Feign在此基礎上做了進一步封裝,由他來幫助我們定義和實現依賴服務接口的定義。在Feign的實現下,我們只需創建一個接口並使用注解的方式來配置它(以前是Dao接口上面標注Mapper注解,現在是一個微服務接口上面標注一個Feign注解即可),即可完成對服務提供方的接口綁定,簡化了使用Spring cloud Ribbon時,自動封裝服務調用客戶端的開發量。
Feign集成了Ribbon 利用Ribbon維護了MicroServiceCloud-Dept的服務列表信息,並且通過輪詢實現了客戶端的負載均衡。而與Ribbon不同的是,通過feign只需要定義服務綁定接口且以聲明式的方法,優雅而簡單的實現了服務調用
1.參考microservicecloud-consumer-dept-80
2.新建microservicecloud-consumer-dept-feign,修改主啟動類名字
3.microservicecloud-consumer-dept-feign工程pom.xml修改,主要添加對feign的支持
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
4.修改microservicecloud-api工程
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent><!-- 子類里面顯示聲明才能有明確的繼承表現,無意外就是父類的默認版本否則自己定義 --> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-api</artifactId><!-- 當前Module我自己叫什么名字 --> <dependencies><!-- 當前Module需要用到的jar包,按自己需求添加,如果父類已經包含了,可以不用寫版本號 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> </dependencies> </project>
新建DeptClientService接口並新增注解@FeignClient
package com.atguigu.springcloud.service; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.atguigu.springcloud.entities.Dept; @FeignClient(value = "MICROSERVICECLOUD-DEPT") public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list",method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add",method = RequestMethod.POST) public boolean add(Dept dept); }
5.microservicecloud-consumer-dept-feign工程修改Controller,添加上一步新建的DeptClientService接口
microservicecloud-consumer-dept-feign工程修改主啟動類
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; @SpringBootApplication @EnableEurekaClient @EnableFeignClients(basePackages= {"com.atguigu.springcloud"}) @ComponentScan("com.atguigu.springcloud") public class DeptConsumer80_Feign_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_Feign_App.class, args); } }
6.測試
啟動3個eureka集群
啟動3個部門微服務8001/8002/8003
啟動Feign自己啟動
http://localhost/consumer/dept/list
Feign自帶負載均衡配置項
總結: Feign通過接口的方法調用Rest服務(之前是Ribbon+RestTemplate), 該請求發送給Eureka服務器(http://MICROSERVICECLOUD-DEPT/dept/list), 通過Feign直接找到服務接口,由於在進行服務調用的時候融合了Ribbon技術,所以也支持負載均衡作用。
5.zuul路由網關
Zuul包含了對請求的路由和過濾兩個最主要的功能: 其中路由功能負責將外部請求轉發到具體的微服務實例上,是實現外部訪問統一入口的基礎而過濾器功能則負責對請求的處理過程進行干預,是實現請求校驗、服務聚合等功能的基礎.
Zuul和Eureka進行整合,將Zuul自身注冊為Eureka服務治理下的應用,同時從Eureka中獲得其他微服務的消息,也即以后的訪問微服務都是通過Zuul跳轉后獲得。
注意:Zuul服務最終還是會注冊進Eureka
提供=代理+路由+過濾三大功能
路由基本配置
1.新建Module模塊microservicecloud-zuul-gateway-9527
2.POM
修改
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency>
全部
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-zuul-gateway-9527</artifactId> <dependencies> <!-- zuul路由網關 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!-- actuator監控 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- hystrix容錯--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!-- 日常標配 --> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- 熱部署插件 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>
3.YML
server: port: 9527 spring: application: name: microservicecloud-zuul-gateway eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: gateway-9527.com prefer-ip-address: true info: app.name: atguigu-microcloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
4.hosts修改
127.0.0.1 myzuul.com
5.主啟動類
@EnableZuulProxy
6.啟動
三個eureka集群
一個服務提供類microservicecloud-provider-dept-8001
一個路由
測試
不用路由 http://localhost:8001/dept/get/2
啟用路由http://myzuul.com:9527/microservicecloud-dept/dept/get/2
路由訪問映射規則
1.工程microservicecloud-zuul-gateway-9527
before http://myzuul.com:9527/microservicecloud-dept/dept/get/2 zuul: routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/** after http://myzuul.com:9527/mydept/dept/get/1
此時的問題
路由訪問OK:http://myzuul.com:9527/mydept/dept/get/1
原路徑訪問OK:http://myzuul.com:9527/microservicecloud-dept/dept/get/2
原真實服務名忽略
yml
zuul: ignored-services: microservicecloud-dept #單個具體,多個可以用"*" routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/**
設置統一公共前綴
zuul: prefix: /atguigu ignored-services: "*" routes: mydept.serviceId: microservicecloud-dept mydept.path: /mydept/**
http://myzuul.com:9527/atguigu/mydept/dept/get/1
6.Hystrix斷路器
分布式系統面臨的問題 復雜分布式體系結構中的應用程序有數十個依賴關系,每個依賴關系在某些時候將不可避免地失敗。
服務雪崩 多個微服務之間調用的時候,假設微服務A調用微服務B和微服務C,微服務B和微服務C又調用其它的微服務,這就是所謂的“扇出”。如果扇出的鏈路上某個微服務的調用響應時間過長或者不可用,對微服務A的調用就會占用越來越多的系統資源,進而引起系統崩潰,所謂的“雪崩效應”.
對於高流量的應用來說,單一的后端依賴可能會導致所有服務器上的所有資源都在幾秒鍾內飽和。比失敗更糟糕的是,這些應用程序還可能導致服務之間的延遲增加,備份隊列,線程和其他系統資源緊張,導致整個系統發生更多的級聯故障。這些都表示需要對故障和延遲進行隔離和管理,以便單個依賴關系的失敗,不能取消整個應用程序或系統。
Hystrix是一個用於處理分布式系統的延遲和容錯的開源庫,在分布式系統里,許多依賴不可避免的會調用失敗,比如超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分布式系統的彈性。
“斷路器”本身是一種開關裝置,當某個服務單元發生故障之后,通過斷路器的故障監控(類似熔斷保險絲),向調用方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者拋出調用方無法處理的異常,這樣就保證了服務調用方的線程不會被長時間、不必要地占用,從而避免了故障在分布式系統中的蔓延,乃至雪崩。
能干嘛
服務降級,服務熔斷,服務限流
服務熔斷
熔斷機制是應對雪崩效應的一種微服務鏈路保護機制。 當扇出鏈路的某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速返回"錯誤"的響應信息。當檢測到該節點微服務調用響應正常后恢復調用鏈路。在SpringCloud框架里熔斷機制通過Hystrix實現。Hystrix會監控微服務間調用的狀況,當失敗的調用到一定閾值,缺省是5秒內20次調用失敗就會啟動熔斷機制。熔斷機制的注解是@HystrixCommand。
參考microservicecloud-provider-dept-8001
新建microservicecloud-provider-dept-hystrix-8001
修改
pom.xml
<!-- hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
yml
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路徑 type-aliases-package: com.atguigu.springcloud.entities #entity別名類 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8001-hystrix #自定義服務名稱信息 prefer-ip-address: true #訪問路徑可以顯示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
修改DeptController
package com.atguigu.springcloud.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.atguigu.springcloud.entities.Dept; import com.atguigu.springcloud.service.DeptService; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; @RestController public class DeptController { @Autowired private DeptService service = null; @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET) @HystrixCommand(fallbackMethod = "processHystrix_Get") public Dept get(@PathVariable("id") Long id) { Dept dept = this.service.get(id); if(null == dept) { throw new RuntimeException("該ID:"+id+"沒有沒有對應的信息"); } return dept; } public Dept processHystrix_Get(@PathVariable("id") Long id) { return new Dept().setDeptno(id) .setDname("該ID:"+id+"沒有沒有對應的信息,null--@HystrixCommand") .setDb_source("no this database in MySQL"); } }
@HystrixCommand報異常后如何處理
一旦調用服務方法失敗並拋出了錯誤信息后,會自動調用@HystrixCommand標注好的fallbackMethod調用類中的指定方法
修改主啟動類DeptProvider8001_Hystrix_App並添加新注解@EnableCircuitBreaker
測試
1.3個eureka先啟動
2.主啟動類DeptProvider8001_Hystrix_App
3.Consumer啟動microservicecloud-consumer-dept-80
4.http://localhost/consumer/dept/get/112
服務降級
整體資源快不夠了,忍痛將某些服務先關掉,待渡過難關,再開啟回來。
服務降級處理是在客戶端實現完成的,與服務端沒有關系
1.修改microservicecloud-api工程, 根據已經有的DeptClientService接口新建一個實現了 FallbackFactory接口的類DeptClientServiceFallbackFactory
2.修改microservicecloud-api工程,DeptClientService接口在注解@FeignClient中添加fallbackFactory屬性值
package com.atguigu.springcloud.service; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.atguigu.springcloud.entities.Dept; @FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory=DeptClientServiceFallbackFactory.class) public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list",method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add",method = RequestMethod.POST) public boolean add(Dept dept); }
package com.atguigu.springcloud.service; import java.util.List; import org.springframework.stereotype.Component; import com.atguigu.springcloud.entities.Dept; import feign.hystrix.FallbackFactory; @Component // 不要忘記添加,不要忘記添加 public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { return new Dept().setDeptno(id).setDname("該ID:" + id + "沒有沒有對應的信息,Consumer客戶端提供的降級信息,此刻服務Provider已經關閉") .setDb_source("no this database in MySQL"); } @Override public List<Dept> list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } }
3.microservicecloud-consumer-dept-feign工程修改YML
server: port: 80 feign: hystrix: enabled: true eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
4.測試
3個eureka先啟動
微服務microservicecloud-provider-dept-8001啟動
microservicecloud-consu
mer-dept-feign啟動
http://localhost/consumer/dept/get/1
故意關閉微服務microservicecloud-provider-dept-8001
http://localhost/consumer/dept/get/1
此時服務端provider已經down了,但是我們做了服務降級處理,讓客戶端在服務端不可用時也會獲得提示信息而不會掛起耗死服務器
服務監控hystrixDashboard
除了隔離依賴服務的調用以外,Hystrix還提供了准實時的調用監控(Hystrix Dashboard),Hystrix會持續地記錄所有通過Hystrix發起的請求的執行信息,並以統計報表和圖形的形式展示給用戶,包括每秒執行多少請求多少成功,多少失敗等。Netflix通過hystrix-metrics-event-stream項目實現了對以上指標的監控。Spring Cloud也提供了Hystrix Dashboard的整合,對監控內容轉化成可視化界面。
1.新建工程microservicecloud-consumer-hystrix-dashboard
2.pom
修改
<!-- hystrix和 hystrix-dashboard相關--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency>
全部
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-consumer-hystrix-dashboard</artifactId> <dependencies> <!-- 自己定義的api --> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 修改后立即生效,熱部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!-- Ribbon相關 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!-- feign相關 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <!-- hystrix和 hystrix-dashboard相關--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency> </dependencies> </project>
3.yml
server: port: 9001
4.主啟動類改名+新注解@EnableHystrixDashboard
5.所有Provider微服務提供類(8001/8002/8003)都需要監控依賴配置
<!-- actuator監控信息完善 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
6.啟動microservicecloud-consumer-hystrix-dashboard該微服務監控消費端
7.啟動3個eureka集群
8.啟動microservicecloud-provider-dept-hystrix-8001
http://localhost:8001/dept/get/1
http://localhost:8001/hystrix.stream
啟動的相關微服務工程
9.監控測試
多次刷新http://localhost:8001/dept/get/1
觀察監控窗口