尚硅谷2020最新版SpringCloud【筆記】1
2.從2.2.x和H版開始說起
技術 | 版本 |
---|---|
Spring Cloud | Hoxton.SR1 |
Spring Boot | 2.2.2.RELEASE |
Spring Cloud Alibaba | 2.1.0.RELEASE |
4.微服務架構編碼構建
配置熱部署Devtools
-
改 POM,添加依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
-
在父工程中添加 Maven 插件
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.2.2.RELEASE</version> <configuration> <fork>true</fork> <addResources>true</addResources> </configuration> </plugin> </plugins> </build>
-
IDEA 設置
- File | Settings | Build, Execution, Deployment | Compiler 中,全部勾選
- 快捷鍵 Ctrl+Shift+Alt+/ -> 1.Registry... -> 勾選 compiler.automake.allow.when.app.running 和 actionSystem.assertFocusAccessFromEdt
-
重啟 IDEA
開啟 Run Dashboard
Services 視圖中添加 Run Configuration Type,選擇 Spring Boot
遵循原則
約定 > 配置 > 編碼
創建父工程 Project
創建步驟:
- New Project
- 聚合總工程名字
- Maven選版本
- 工程名字
- 字符編碼
- 注解生效激活
- java編譯版本選8
- File Type過濾(可選)
父工程 POM
<?xml version="1.0" encoding="UTF-8"?>
<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>mycloud2020</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cloud-provider-payment8001</module>
...
</modules>
<!-- 統一管理jar包版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>
<!-- 子模塊繼承之后,提供作用:鎖定版本+子modlue不用寫groupId和version -->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.2.RELEASE</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 注意其中的 packaging 標簽值為 pom
創建 cloud-provider-payment8001 微服務提供者支付Module模塊,即生產者
創建步驟:
- 建 module,名為 cloud-provider-payment8001
- 改 POM
- 寫 YML
- 主啟動類
- 業務類
創建 cloud-consumer-order80 微服務消費者訂單Module模塊,即
工程重構
創建 cloud-api-commons Module模塊
-
將重復代碼放入此模塊
-
打包此模塊,maven命令clean install
-
在其他模塊中刪除重復代碼,添加此模塊依賴
<dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency>
5.Eureka 服務注冊與發現
定位
Eureka 類比物業公司,服務類比入駐企業
單機 Eureka 服務中心構建
-
建Module,cloud-eureka-server7001
-
改POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
-
寫 YML
eureka: instance: hostname: localhost # eureka服務端的實例名字 client: register-with-eureka: false # 表示不向注冊中心注冊自己 fetch-registry: false #表示自己就是注冊中心,職責是維護服務實例,並不需要去檢索服務 # 設置與eureka server交互的地址查詢服務和注冊服務都需要依賴這個地址 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
-
主啟動,添加
@EnableEurekaServer
業務模塊配置 Eureka 客戶端
-
改 POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
-
改 YML
eureka: client: # 表示是否將自己注冊進EurekaServer默認為true。 register-with-eureka: true # 是否從EurekaServer抓取已有的注冊信息,默認為true。單節點無所謂,集群必須設置為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
-
主啟動類,添加注解
@EnableEurekaClient
集群 Eureka 服務中心構建
-
新建 cloud-eureka-server7002 模塊
-
修改 hosts 文件
hosts 文件路徑為
C:\Windows\System32\drivers\etc\hosts
127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com
-
改 YML
eureka: instance: hostname: eureka7001.com # eureka服務端的實例名字 client: register-with-eureka: false # 表示不向注冊中心注冊自己 fetch-registry: false #表示自己就是注冊中心,職責是維護服務實例,並不需要去檢索服務 service-url: # 7001 配置 7002,7002 配置7001 defaultZone: http://eureka7002.com:7002/eureka/
-
業務模塊改 YML
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
生產者模塊配置集群
-
復制生產者模塊,cloud-provider-payment8002
-
注意 YML 配置中,應用名稱保持一致
spring: application: name: cloud-payment-service
消費者模塊配置負載均衡
-
修改配置類
@Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); }
-
修改 Controller
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE"; return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
-
測試負載均衡
actuator微服務信息完善
-
改 POM ,添加依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
主機名稱:服務名稱修改
eureka: instance: # 服務實例 ID instance-id: payment8001
-
訪問信息有ip信息提示
eureka: instance: # 訪問路徑可以顯示IP地址 prefer-ip-address: true
服務發現 Discovery
對於注冊進eureka里面的微服務,可以通過服務發現來獲得該服務的信息
-
主啟動類,添加注解
@EnableDiscoveryClient
-
業務代碼
@Autowired private DiscoveryClient discoveryClient; @GetMapping("/discovery") public Object discovery() { List<String> services = discoveryClient.getServices(); for (String service : services) { log.info("service *** {}" + service); List<ServiceInstance> instances = discoveryClient.getInstances(service); for (ServiceInstance instance : instances) { log.error("instance *** {}", instance); } } return discoveryClient; }
Eureka自我保護
某時刻某一個微服務不可用了,Eureka不會立刻清理,依舊會對該微服務的信息進行保存
屬於CAP里面的AP分支
禁止自我保護
-
Eureka 服務中心配置
eureka: server: enable-self-preservation: false # 關閉自我保護機制,保證不可用服務被及時踢除 eviction-interval-timer-in-ms: 2000
-
Eureka 客戶端配置
eureka: instance: # Eureka客戶端向服務端發送心跳的時間間隔,單位為秒(默認是30秒) lease-renewal-interval-in-seconds: 1 # Eureka服務端在收到最后一次心跳后等待時間上限,單位為秒(默認是90秒),超時將剔除服務 lease-expiration-duration-in-seconds: 2
6.Zookeeper服務注冊與發現
結論
服務在 Zookeeper 中創建的是臨時節點,一旦服務停止,一段時間后,節點被 Zookeeper 刪除。
SpringCloud整合Zookeeper代替Eureka
注冊中心Zookeeper
-
啟動 Zookeeper
-
在 Windows 服務中開啟 VMware DHCP Service 和 VMware NAT Service
-
關閉虛擬機中的防火牆
systemctl stop firewalld.service
-
啟動 Zookeeper
# 啟動服務 ./zkServer.sh start # 驗證狀態 ./zkServer.sh status # 啟動客戶端 ./zkCli.sh
-
服務提供者
-
創建生產者服務
-
建 Module,cloud-provider-payment8004
-
改 POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> </dependency>
如果啟動時報錯,可能是依賴的 ZooKeeper 的 jar 包與使用的 ZooKeeper 版本不一致,可以通過調整依賴解決:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> <!--先排除自帶的zookeeper3.5.3--> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <!--添加zookeeper3.4.9版本--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.9</version> </dependency>
-
改 YML
#8004表示注冊到zookeeper服務器的支付服務提供者端口號 server: port: 8004 #服務別名----注冊zookeeper到注冊中心名稱 spring: application: name: cloud-provider-payment cloud: zookeeper: connect-string: 192.168.181.128:2181
-
主啟動類,添加注解
@EnableDiscoveryClient
-
-
驗證
- 啟動無報錯
- Zookeeper 客戶端中查看,會產生新的節點
services
,services
下有cloud-provider-payment
節點
服務消費者
- 建 Module ,cloud-consumerzk-order80
- 改 POM,同上
- 改 YML,同上
- 主啟動類,同上
- 測試
- Zookeeper 客戶端中查看,
services
節點下有新的節點cloud-consumer-order
- Zookeeper 客戶端中查看,
7.Consul服務注冊與發現
Consul簡介
功能
- 服務發現
提供HTTP和DNS兩種發現方式 - 健康監測
支持多種協議,HTTP、TCP、Docker、Shell腳本定制化 - KV存儲
key , Value的存儲方式 - 多數據中心
Consul支持多數據中心 - 可視化Web界面
安裝並運行Consul
-
下載 Windows 64位程序;
-
查看版本信息
.\consul.exe --version
-
使用開發模式啟動
consul agent -dev
-
訪問Consul的首頁
http;//localhost:8500
服務提供者
-
建 Module,cloud-providerconsul-payment8006
-
改 POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency>
-
改 YML
###服務端口號 server: port: 8006 spring: application: name: consul-provider-payment ####consul注冊中心地址 cloud: consul: host: localhost port: 8500 discovery: #hostname: 127.0.0.1 service-name: ${spring.application.name}
-
主啟動類,添加注解
@EnableDiscoveryClient
-
測試
- Consul 的圖形化界面中出現新的 Service,consul-provider-payment
服務消費者
- 建 Module ,cloud-consumerconsul-order80
- 改 POM,同上
- 改 YML,同上
- 主啟動類,同上
- 測試
- Consul 的圖形化界面中出現新的 Service,cloud-consumer-order
三個注冊中心異同點
組件名 | 語言 | CAP | 健康檢查 | 對外暴露接口 | Spring Cloud 集成 |
---|---|---|---|---|---|
Eureka | Java | AP | 可配支持 | HTTP | 已集成 |
Consul | Go | CP | 支持 | HTTP/DNS | 已集成 |
ZooKeeper | Java | CP | 支持 | 客戶端 | 已集成 |
8.Ribbon負載均衡服務調用
概述
是什么
客戶端 負載均衡 的工具
主要功能是提供客戶端的軟件負載均衡算法和服務調用
Ribbon目前也進入維護模式,未來可以使用 Spring Cloud LoadBalancer 替代
能干嗎
LB(負載均衡)
-
集中式LB
即在消費方和服務方之間使用獨立的 LB 設施
例如 Nginx,Nginx 是服務器負載均衡,客戶端所有請求都會交給 Nginx ,然后由 Nginx 實現轉發請求。即負載均衡是由服務端實現的。
-
進程內LB
將 LB 邏輯集成到消費方,消費方從服務注冊中心獲知有哪些地址可用,然后從這些地址中選擇一個合適的服務器。
Ribbon 本地負載均衡,在調用微服務接口時,會在注冊中心上獲取注冊信息服務列表之后緩存到 JVM 本地,從而在本地實現 RPC 遠程服務調用技術。
負載均衡+RestTemplate調用
Ribbon負載均衡演示
總結:Ribbon其實就是一個軟負載均衡的客戶端組件,他可以和其他所需請求的客戶端結合使用,和eureka結合只是其中的一個實例。
POM
spring-cloud-starter-netflix-eureka-client
依賴中自帶了 spring-cloud-starter-netflix-ribbon
,所以無需手動引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
二說RestTemplate的使用
-
getForObject:返回對象
CommonResult commonResult = restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
-
getForEntity:返回 ResponseEntity
ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
Ribbon核心組件IRule
com.netflix.loadbalancer.IRule
IRule:根據特定算法從服務列表中選取一個要訪問的服務
com.netflix.loadbalancer.RoundRobinRule
輪詢com.netflix.loadbalancer.RandomRule
隨機com.netflix.loadbalancer.RetryRule
先按照RoundRobinRule的策略獲取服務,如果獲取服務失敗則在指定時間內會進行重試WeightedResponseTimeRule
對RoundRobinRule的擴展,響應速度越快的實例選擇權重越大,越容易被選擇BestAvailableRule
會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然后選擇一個並發量最小的服務AvailabilityFilteringRule
先過濾掉故障實例,再選擇並發較小的實例ZoneAvoidanceRule
默認規則,復合判斷server所在區域的性能和server的可用性選擇服務器
替換負載均衡算法
注意:算法的配置類不能位於包掃描范圍內,需要獨立出來。例如,啟動類在包 com.atguigu.springcloud
下,算法的配置類就不能位於此包及其子包下,可以位於包 com.atguigu.myrule
下。
替換步驟:
-
新建配置類,
com.atguigu.myrule.MySelfRule
@Configuration public class MySelfRule { @Bean public IRule myRule() { return new RandomRule(); //定義為隨機 } }
-
主啟動類,配置
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration= MySelfRule.class)
9.OpenFeign服務接口調用
概述
Feign是一個聲明式的web服務客戶端,讓編寫web服務客戶端變得非常容易,只需創建一個接口並在接口上添加注解即可
OpenFeign 依賴 Ribbon,自帶負載均衡功能
服務消費者使用 OpenFeign 步驟
-
建 Module,cloud-consumer-feign-order80
-
改 POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
改 YML
-
主啟動類,添加注解
@EnableFeignClients
-
業務類,Feign 接口類
@Component @FeignClient(value = "CLOUD-PAYMENT-SERVICE") public interface PaymentFeignService { @GetMapping(value = "/payment/get/{id}") public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id); }
-
調用 Feign 接口類
@Resource private PaymentFeignService paymentFeignService; @GetMapping(value = "/consumer/payment/get/{id}") public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) { return paymentFeignService.getPaymentById(id); }
OpenFeign超時控制
改 YML:
#設置feign客戶端超時時間(OpenFeign默認支持ribbon)
ribbon:
#指的是建立連接所用的時間,適用於網絡狀況正常的情況下,兩端連接所用的時間,默認為1s
ReadTimeout: 5000
#指的是建立連接后從服務器讀取到可用資源所用的時間,默認為1s
ConnectTimeout: 5000
OpenFeign日志打印功能
日志級別
級別 | 描述 |
---|---|
NONE | 默認,不顯示任何日志 |
BASIC | 僅記錄請求方法、URL、響應狀態碼及執行時間 |
HEADERS | 除了 BASIC 中定義的信息之外,還有請求和相應的頭信息 |
FULL | 除了 HEADERS 中定義的信息之外,還有請求和響應的正文及元數據 |
配置步驟
-
新建配置類
@Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
-
改 YML
logging: level: # feign日志以什么級別監控哪個接口 com.atguigu.springcloud.service.PaymentFeignService: debug