一、服務(wù)發(fā)現(xiàn)(Eureka/Consul/ZooKeeper)
1、Eureka介紹
Netflix Eureka是Spring Cloud服務(wù)注冊(cè)發(fā)現(xiàn)的基礎(chǔ)組件
Eureka提供RESTful風(fēng)格(HTTP協(xié)議)的服務(wù)注冊(cè)與發(fā)現(xiàn)
Eureka采用C/S架構(gòu),Spring Cloud內(nèi)置客戶端
2、Eureka的組成

3、搭建Eureka注冊(cè)中心
啟動(dòng)Idea -> Spring Initializr 向?qū)?
組件向?qū)нx中 Spring Cloud Discovery -> Eureka Server
SpringBoot版本選擇 2.1.8
Spring Boot 2.1.8 對(duì)應(yīng)了Spring Cloud Greewich SR3
pom.xml確保引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
下載慢可以引入阿里云鏡像倉庫
<repositories>
<repository>
<id>aliyun</id>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
application.yml
server:
port: 8761 #端口
eureka:
server:
enable-self-preservation: false #關(guān)閉自我保護(hù)
instance: #設(shè)置注冊(cè)中心應(yīng)用名
appname: provider-service#名稱
hostname: localhost#正式環(huán)境寫域名
client:
service-url:
defaultZone:
http://localhost:8761/eureka/ #設(shè)置默認(rèn)區(qū)域注冊(cè)中心
register-with-eureka: false #禁止自注冊(cè)
fetch-registry: false #是否注冊(cè)中心獲取其他微服務(wù)的注冊(cè)信息
EurekaServerApplication 增加@EnableEurekaServer注解啟用Eureka服務(wù)器
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
啟用應(yīng)用,訪問 http://localhost:8761

4、開發(fā)Eureka客戶端(微服務(wù))

Eureka客戶端開發(fā)要點(diǎn)
maven依賴spring-cloud-starter-netflix-eureka-client application.yml
配置eureka.client.service-url.defaultZone
入口類增加@EnableEurekaClient
創(chuàng)建新工程eureka-client
啟動(dòng)Spring-Initialzr向?qū)?,
選擇
Web -> Spring Web
Spring Cloud Discovery -> Eureka Discovery Client
確認(rèn)Spring Boot 版本為2.1.8
pom.xml確保
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
application.yml
server:
port: 80 #端口
spring:
application:
name: order-service #微服務(wù)名稱 必須全局唯一
eureka:
client:
service-url:
defaultZone:
http://localhost:8761/eureka/ #注冊(cè)中心地址
入口類增加@EnableEurekaClient,啟用Eureka客戶端
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
先啟動(dòng)注冊(cè)中心,在啟動(dòng)客戶端,訪問 localhost:8761查看eureka注冊(cè)中心,看到客戶端注冊(cè)

5、Eureka名詞概念與自我保護(hù)
Eureka名詞概念
Register - 服務(wù)注冊(cè), 向Eureka進(jìn)行注冊(cè)登記
Renew - 服務(wù)續(xù)約,30秒/次心跳包健康檢查.90秒未收到剔除服務(wù)
Fetch Registries - 獲取服務(wù)注冊(cè)列表,獲取其他微服務(wù)地址
Cancel - 服務(wù)下線, 某個(gè)微服務(wù)通知注冊(cè)中心暫停服務(wù)
Eviction - 服務(wù)剔除,90秒未續(xù)約,從服務(wù)注冊(cè)表進(jìn)行剔除
Eureka自我保護(hù)機(jī)制
Eureka在運(yùn)行期去統(tǒng)計(jì)心跳失敗率在15分鐘之內(nèi)是否低于 85%
如果低于 85%,會(huì)將這些實(shí)例保護(hù)起來,讓這些實(shí)例不會(huì)被剔除
關(guān)閉自我保護(hù):eureka.服務(wù)實(shí)例.
enable-self-preservation: false
PS: 如非網(wǎng)絡(luò)特別不穩(wěn)定,建議關(guān)閉
6、Eureka高可用配置

Eureka高可用配置步驟
服務(wù)提供者defaultZone指向其他的Eureka
客戶端添加所有Eureka 服務(wù)實(shí)例 URL
Eureka只能綁定域名,在本地測(cè)試需要修改DNS配置文件hosts
編輯 c:/windows/system32/drivers/etc/hosts
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
127.0.0.1 server1
127.0.0.1 server2
127.0.0.1 server3
高可用配置:
application-p8761.yml
啟動(dòng)項(xiàng) Program arguments:--spring.profiles.active=8761
server:
port: 8761
eureka:
instance:
appname: provider-service
hostname: server1 #必須是域名
client:
service-url:
defaultZone:
http://server2:8762/eureka/,http://server3:8763/eureka/ #向其他注冊(cè)中心節(jié)點(diǎn)注冊(cè)
application-p8762.yml
啟動(dòng)項(xiàng) Program arguments:--spring.profiles.active=8762
server:
port: 8762
eureka:
instance:
appname: provider-service
hostname: server2
client:
service-url:
defaultZone:
http://server1:8761/eureka/,http://server3:8763/eureka/ #向其他注冊(cè)中心節(jié)點(diǎn)注冊(cè)
application-p8763.yml
啟動(dòng)項(xiàng) Program arguments:--spring.profiles.active=8763
server:
port: 8763
eureka:
instance:
appname: provider-service
hostname: server3
client:
service-url:
defaultZone:
http://server1:8761/eureka/,http://server2:8762/eureka/ #向其他注冊(cè)中心節(jié)點(diǎn)注冊(cè)
入口類增加@EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class HaEurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(HaEurekaServerApplication.class, args);
}
}
客戶端指向所有Eureka注冊(cè)中心節(jié)點(diǎn)
server:
port: 80
spring:
application:
name: order-service
eureka:
client:
service-url:
defaultZone:
http://server1:8761/eureka/,http://server1:8762/eureka/,http://server1:8763/eureka/
7、Actuator監(jiān)控組件
Actuator自動(dòng)為微服務(wù)創(chuàng)建一系列的用于監(jiān)控的端點(diǎn)
Actuator在SpringBoot自帶,SpringCloud進(jìn)行擴(kuò)展
pom.xml依賴spring-boot-starter-actuator

二、服務(wù)間通信
1、微服務(wù)之間調(diào)用的兩種方式
RestTemplate + @LoadBalanced 顯式調(diào)用
OpenFeign 隱藏微服務(wù)間通信細(xì)節(jié)
2、Ribbon客戶端負(fù)載均衡
1.Ribbon是Netfilix開源的客戶端負(fù)載均衡組件
Ribbon是RestTemplate與OpenFeign的通信基礎(chǔ)

2.Ribbon負(fù)載均衡策略

##在消費(fèi)者中進(jìn)行設(shè)置
application.yml 針對(duì)某一個(gè)微服務(wù)設(shè)置負(fù)載均衡
book-service: #微服務(wù)id
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #隨機(jī)策略
全局設(shè)置,全局設(shè)置優(yōu)先級(jí)高于application.yml設(shè)置
@SpringBootApplication
@EnableEurekaClient
public class MemberServiceApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Bean //全局負(fù)載均衡策略
public IRule ribbonRule(){
return new RoundRobinRule();
}
public static void main(String[] args) {
SpringApplication.run(MemberServiceApplication.class, args);
}
}
3、RestTemplate + @LoadBalanced 顯式調(diào)用代碼實(shí)現(xiàn)
1.搭建eureka注冊(cè)中心
2.搭建客戶端服務(wù)
圖書服務(wù)
Spring Initializr
Web->Eureka Discovery Client
application.yml
spring:
application:
name: book-service
eureka:
client:
service-url:
defaultZone:
http://localhost:8761/eureka/
BookController
@GetMapping("/bsn")
public Book findBySN(String sn, HttpServletRequest request){
/*try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
Book book = null;
if(sn.equals("1111")){
book = new Book("1111", "測(cè)試圖書1", String.valueOf(request.getLocalPort()));
}else if(sn.equals("2222")){
book = new Book("2222", "測(cè)試圖書2", String.valueOf(request.getLocalPort()));
}else if(sn.equals("3333")){
book = new Book("3333", "測(cè)試圖書3", String.valueOf(request.getLocalPort()));
}
return book;
}
啟動(dòng)兩個(gè)服務(wù),復(fù)制兩個(gè)啟動(dòng)項(xiàng),修改啟動(dòng)端口
Program arguments: --server.port=8000
Program arguments: --server.port=8001

3.搭建消費(fèi)端服務(wù)
RestTemplate介紹
RestTemplate是Spring Cloud訪問Restful API的請(qǐng)求對(duì)象
RestTemplate與HttpClient、OKHttp職能類似
@LoadBalanced注解
@LoadBalanced是Ribbon提供的客戶端負(fù)載均衡注解
通常RestTemplate與@LoadBalanced聯(lián)合使用
創(chuàng)建訂單服務(wù)
Spring Initializr
web->Spring Web
Spring Cloud Discovery -> Eureka Discover Client
Spring Cloud Routing -> Ribbon
確保pom.xml引入ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
appliaction.yml
spring:
application:
name: member-service
eureka:
client:
service-url:
defaultZone:
http://localhost:8761/eureka
入口類注入RestTemplate
@SpringBootApplication
@EnableEurekaClient
public class MemberServiceApplication {
@Bean //注入
@LoadBalanced //Ribbon負(fù)載均衡,默認(rèn)輪詢
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
業(yè)務(wù)開發(fā),服務(wù)間通信
@Controller
public class MemberController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/borrow")
@ResponseBody
public String borrow(String sn){
/*
RestTemplate負(fù)載均衡格式要求:
http://微服務(wù)id/webapi地址
*/
Book book = restTemplate.getForObject("http://book-service/bsn?sn=" + sn, Book.class);#傳入?yún)?shù)為返回值的實(shí)體類
return book.getName() + ":" + book.getDesc() + "圖書借閱成功";
}
}
業(yè)務(wù)實(shí)體Book與JSON屬性對(duì)應(yīng)即可
public class Book {
private String sn;
private String name;
private String desc;
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
4、OpenFeign服務(wù)間通信
1.Feign與OpenFeign
Feign是一個(gè)開源聲明式WebService客戶端,用于簡(jiǎn)化服務(wù)通信
Feign采用“接口+注解”方式開發(fā),屏蔽了網(wǎng)絡(luò)通信的細(xì)節(jié)
OpenFeign是SpringCloud對(duì)Feign的增強(qiáng),支持Spring MVC注解
2.使用openFeign進(jìn)行服務(wù)間調(diào)用
1.新建Spring boot Web項(xiàng)目,application name 為 product-service
在pom.xml中引入依賴
<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>
</dependency>
spring-cloud-starter-alibaba-nacos-discovery作用為向Nacos server注冊(cè)服務(wù)。
spring-cloud-starter-openfeign作用為實(shí)現(xiàn)服務(wù)調(diào)用。
2.修改application.yml配置文件
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
application:
name: product-service
server:
port: 8083
3.在啟動(dòng)類上添加@EnableDiscoveryClient、@EnableFeignClients注解
package com.example.productservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
4.編寫OrderClient Interface
注:/api/v1/order/test 會(huì)在下面order-service聲明。
OrderClient.java
package com.example.productservice.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Component
@FeignClient("order-service")
public interface OrderClient {
@RequestMapping(method = RequestMethod.GET, value = "/api/v1/order/test")
String callOrder();
}
5.編寫Controller和service
ProductController.java
package com.example.productservice.controller;
import com.example.productservice.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@Autowired
ProductService productService;
@RequestMapping(value = "testCallOrder", method = RequestMethod.GET)
public String testCallOrder() {
return productService.callOrder();
}
}
ProductService.java
package com.example.productservice.service;
import com.example.productservice.client.OrderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
@Autowired
OrderClient orderClient;
public String callOrder() {
String response = orderClient.callOrder();
return response;
}
}
3、OpenFeign工作原理

4、OpenFeign負(fù)載均衡策略

5、OpenFeign通信日志
1.OpenFeign開啟通信日志
基于SpringBoot的logback輸出,默認(rèn)debug級(jí)別
設(shè)置項(xiàng):feign.client.config.微服務(wù)id.loggerLevel
微服務(wù)id:default代表全局默認(rèn)配置
2.通信日志輸出格式
NONE: 不輸出任何通信日志
BASIC: 只包含URL、請(qǐng)求方法、狀態(tài)碼、執(zhí)行時(shí)間
HEADERS:在BASIC基礎(chǔ)上,額外包含請(qǐng)求與響應(yīng)頭
FULL:包含請(qǐng)求與響應(yīng)內(nèi)容最完整的信息
3.OpenFeign日志配置項(xiàng)
LoggerLevel開啟通信日志
ConnectionTimeout與ReadTimeout
利用httpclient或okhttp發(fā)送請(qǐng)求
6、替換OpenFeign通信組件
1.OpenFeign通信組件
OpenFeign基于JDK原生URLConnection提供Http通信
OpenFeign支持Apache HttpClient與Square OkHttp
SpringCloud按條件自動(dòng)加載應(yīng)用通信組件
2.應(yīng)用條件
Maven引入feign-okhttp或者feign-httpclient依賴
設(shè)置feign.[httpclient|okhttp].enabled=true
7、OpenFeign多參數(shù)傳遞
@FeignClient(name="book-service")
public interface BookService {
@GetMapping("/bsn")
public Book findBySn
(@RequestParam("sn") String sn,
@RequestParam("p1") String p1,
@RequestParam("p2") String p2);
}
//http://book-service/bsn?sn=...&p1=xxx&p2=xxx
POST方式傳遞對(duì)象使用@RequestBody注解描述參數(shù)
GET方式將對(duì)象轉(zhuǎn)換為Map后利用@RequestParam注解描述
三、熔斷機(jī)制與Hystrix
雪崩效應(yīng):服務(wù)雪崩效應(yīng)產(chǎn)生與服務(wù)堆積在同一個(gè)線程池中,因?yàn)樗械恼?qǐng)求都是同一個(gè)線程池進(jìn)行處理,這時(shí)候如果在高并發(fā)情況下,所有的請(qǐng)求全部訪問同一個(gè)接口,這時(shí)候可能會(huì)導(dǎo)致其他服務(wù)沒有線程進(jìn)行接受請(qǐng)求,這就是服務(wù)雪崩效應(yīng)效應(yīng)。
服務(wù)熔斷:熔斷機(jī)制目的為了保護(hù)服務(wù),在高并發(fā)的情況下,如果請(qǐng)求達(dá)到一定極限(可以自己設(shè)置闊值)如果流量超出了設(shè)置閾值,讓后直接拒絕訪問,保護(hù)當(dāng)前服務(wù)。使用服務(wù)降級(jí)方式返回一個(gè)友好提示,服務(wù)熔斷和服務(wù)降級(jí)一起使用。
1、Hystrix介紹與工作原理
1.Hystrix熔斷器
Hystrix(豪豬)是Netflix開源的熔斷器組件,用于為微服務(wù)提供熔斷機(jī)制預(yù)防雪崩,保護(hù)整體微服務(wù)架構(gòu)的健康
2.Hystrix功能
預(yù)防微服務(wù)由于故障,請(qǐng)求長時(shí)間等待導(dǎo)致Web容器線程崩潰
提供故障備選方案,通過回退(fallback)機(jī)制提供”服務(wù)降級(jí)”
提供監(jiān)控儀表盤,實(shí)時(shí)監(jiān)控運(yùn)行狀態(tài)
3.Hystrix 熔斷器工作原理

服務(wù)的健康狀況 = 請(qǐng)求失敗數(shù) / 請(qǐng)求總數(shù).
熔斷器開關(guān)由關(guān)閉到打開的狀態(tài)轉(zhuǎn)換是通過當(dāng)前服務(wù)健康狀況和設(shè)定閾值比較決定的.
當(dāng)熔斷器開關(guān)關(guān)閉時(shí), 請(qǐng)求被允許通過熔斷器. 如果當(dāng)前健康狀況高于設(shè)定閾值, 開關(guān)繼續(xù)保持關(guān)閉. 如果當(dāng)前健康狀況低于
設(shè)定閾值, 開關(guān)則切換為打開狀態(tài).
當(dāng)熔斷器開關(guān)打開時(shí), 請(qǐng)求被禁止通過.
當(dāng)熔斷器開關(guān)處于打開狀態(tài), 經(jīng)過一段時(shí)間后, 熔斷器會(huì)自動(dòng)進(jìn)入半開狀態(tài), 這時(shí)熔斷器只允許一個(gè)請(qǐng)求通過. 當(dāng)該請(qǐng)求調(diào)用
成功時(shí), 熔斷器恢復(fù)到關(guān)閉狀態(tài). 若該請(qǐng)求失敗, 熔斷器繼續(xù)保持打開狀態(tài), 接下來的請(qǐng)求被禁止通過.
熔斷器的開關(guān)能保證服務(wù)調(diào)用者在調(diào)用異常服務(wù)時(shí), 快速返回結(jié)果, 避免大量的同步等待. 并且熔斷器能在一段時(shí)間后繼續(xù)偵測(cè)請(qǐng)求執(zhí)行結(jié)果, 提供恢復(fù)服務(wù)調(diào)用的可能.
4.什么情況下會(huì)觸發(fā)服務(wù)降級(jí)
FAILURE: 執(zhí)行失敗,拋出異常
TIMEOUT:執(zhí)行超時(shí)(默認(rèn)1秒)
SHORT_CIRCUITED:熔斷器狀態(tài)為Open
THREAD_POOL_REJECTED:線程池拒絕
SEMAPHORE_REJECTED:信號(hào)量拒絕
5.使用Hystrix步驟
1.引入pom文件依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
2.在啟動(dòng)類上方寫入@EnableHystrixDashboard
3.在方法上@HystrixCommand
public class MemberController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/snb")
@ResponseBody
/**
* 模擬新書到貨短信通知客戶的業(yè)務(wù)
*/
@HystrixCommand(fallbackMethod = "sendNewBookError")
public String sendNewBook(String mobile,String bookname){
String message = "[HOTBOOK]您預(yù)購的" + bookname + "已到貨,明日將送到您府上";
CallbackResult result = restTemplate.getForObject("http://message-service/sendsms?mobile=" +mobile+"&message=" + message , CallbackResult.class);
if (result.getCode().equals("0")){
return "短信已成功送達(dá),服務(wù)返回:" +result.getResult();
}else {
return "短信發(fā)送失敗,失敗原因:" + result.getResult();
}
}
public String sendNewBookError(String mobile,String bookname){
return "短信發(fā)送失敗,失敗原因:消息服務(wù)無法正常運(yùn)行,請(qǐng)稍后再試";
}
}
6.OpenFeign與Hystrix整合
OpenFeign中使用Hystrix
OpenFeign內(nèi)置Hystrix,feign.hystrix.enable開啟即可
feign: hystrix: enabled: true
在@FeignClient增加fallback屬性說明Fallback類
@FeignClient(name="message-service",fallback = MessageServiceFallback.class) public interface MessageService { @GetMapping("/sendsms") public CallbackResult sendSMS(@RequestParam("mobile") String mobile , @RequestParam("message") String message); }
Fallback類要實(shí)現(xiàn)相同接口,重寫服務(wù)降級(jí)業(yè)務(wù)邏輯
@Component public class MessageServiceFallback implements MessageService { @Override public CallbackResult sendSMS(String mobile, String message) { return new CallbackResult("INVALID_SERVICE","消息服務(wù)暫時(shí)無法使用,短信發(fā)送失敗"); } }
7.Hystrix超時(shí)設(shè)置


eureka:
client:
service-url:
defaultZone:
http://localhost:8761/eureka
spring:
application:
name: member-service
feign:
hystrix:
enabled: true
client:
config:
default:
connectTimeout: 500
readTimeout: 500 #(3000-2500)/3000=16.7% , (3000-500)/3000=83%
hystrix:
command:
#"類名#方法名(參數(shù)類型1,參數(shù)類型2,參數(shù)類型n)"
"MessageService#sendSMS(String,String)": #HystrixCommandKey
execution:
isolation:
thread:
timeoutInMilliseconds: 1000
#假設(shè):連接500毫秒,處理短信4000毫秒,哪個(gè)timeOut會(huì)觸發(fā)服務(wù)降級(jí)
circuitBreaker:
forceOpen: false #true代表強(qiáng)制熔斷器強(qiáng)制處于Open狀態(tài),即服務(wù)不可用
requestVolumeThreshold: 50
errorThresholdPercentage: 60
sleepWindowInMilliseconds: 10000
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
circuitBreaker:
#在當(dāng)20秒的時(shí)間內(nèi),最近50次調(diào)用請(qǐng)求,請(qǐng)求錯(cuò)誤率超過60%,則觸發(fā)熔斷10秒,期間快速失敗。
requestVolumeThreshold: 50
errorThresholdPercentage: 60
sleepWindowInMilliseconds: 10000
metrics:
rollingStats:
timeInMilliseconds: 20000
8.部署Hystrix Dashboard監(jiān)控
Hystrix Client依賴hystrix-metrics-event-stream
Hystrix Client注冊(cè)HystrixMetricsStreamServlet
監(jiān)控微服務(wù)依賴spring-cloud-starter-netflix-hystrix-dashboard
監(jiān)控微服務(wù)利用@EnableHystrixDashboard開啟儀表盤
9.Hystrix熔斷設(shè)置
產(chǎn)生熔斷的條件:
當(dāng)一個(gè)Rolling Window(滑動(dòng)窗口)的時(shí)間內(nèi)(默認(rèn):10秒),最近20次調(diào)用請(qǐng)求,請(qǐng)求錯(cuò)誤率超過50%,則觸發(fā)熔斷5秒,期間快速失敗。
TIPS: 如10秒內(nèi)未累計(jì)到20次,則不會(huì)觸發(fā)熔斷
Hystrix熔斷設(shè)置項(xiàng):

eureka:
client:
service-url:
defaultZone:
http://localhost:8761/eureka
spring:
application:
name: member-service
feign:
hystrix:
enabled: true
client:
config:
default:
connectTimeout: 500
readTimeout: 500 #(3000-2500)/3000=16.7% , (3000-500)/3000=83%
hystrix:
command:
#"類名#方法名(參數(shù)類型1,參數(shù)類型2,參數(shù)類型n)"
"MessageService#sendSMS(String,String)": #HystrixCommandKey
execution:
isolation:
thread:
timeoutInMilliseconds: 1000
#假設(shè):連接500毫秒,處理短信4000毫秒,哪個(gè)timeOut會(huì)觸發(fā)服務(wù)降級(jí)
circuitBreaker:
forceOpen: false #true代表強(qiáng)制熔斷器強(qiáng)制處于Open狀態(tài),即服務(wù)不可用
requestVolumeThreshold: 50
errorThresholdPercentage: 60
sleepWindowInMilliseconds: 10000
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
circuitBreaker:
#在當(dāng)20秒的時(shí)間內(nèi),最近50次調(diào)用請(qǐng)求,請(qǐng)求錯(cuò)誤率超過60%,則觸發(fā)熔斷10秒,期間快速失敗。
requestVolumeThreshold: 50
errorThresholdPercentage: 60
sleepWindowInMilliseconds: 10000
metrics:
rollingStats:
timeInMilliseconds: 20000
四、API網(wǎng)關(guān)與Zuul
一、初識(shí)API網(wǎng)關(guān)
1.


2.使用網(wǎng)關(guān)的優(yōu)點(diǎn)
統(tǒng)一訪問出入口,微服務(wù)對(duì)前臺(tái)透明
安全、過濾、流控等API管理功能
易于監(jiān)控、方便管理
二、Spring Cloud API網(wǎng)關(guān)
1、
API網(wǎng)關(guān)

2、API網(wǎng)關(guān)產(chǎn)品
Netflix Zuul
Spring Cloud Gateway
3、Netflix Zuul
Zuul 是Netflix開源的一個(gè)API網(wǎng)關(guān), 核心實(shí)現(xiàn)是Servlet
Spring Cloud內(nèi)置Zuul 1.x
Zuul 1.x 核心實(shí)現(xiàn)是Servlet,采用同步方式通信
Zuul 2.x 基于Netty Server,提供異步通信
4、Netflix Zuul架構(gòu)演化

5、Netflix Zuul的功能
認(rèn)證和安全
性能監(jiān)測(cè)
動(dòng)態(tài)路由
負(fù)載卸載
靜態(tài)資源處理
壓力測(cè)試
6、Spring Cloud Gateway
Spring Cloud Gateway,是Spring“親兒子”
Spring Cloud Gateway旨在為微服務(wù)架構(gòu)提供一種簡(jiǎn)單而有效的統(tǒng)一的API路由管理方式
Gateway基于Spring 5.0與Spring WebFlux開發(fā),采用Reactor響應(yīng)式設(shè)計(jì)
7、Netflix Zuul使用入門
1.使用三部曲
依賴spring-cloud-starter-netflix-zuul
入口增加 @EnableZuulProxy
application.yml 增加微服務(wù)映射
2.微服務(wù)映射
zuul:
routes:
book-service-api: #網(wǎng)關(guān)別名
path: /bs/** #映射路徑
serviceId: book-service #微服務(wù)ID
member-service-api:
path: /ms/**
serviceId: member-service
...
8、Zuul負(fù)載均衡與服務(wù)降級(jí)
Zuul負(fù)載均衡配置
Spring Cloud Zuul內(nèi)置Ribbon,與標(biāo)準(zhǔn)配置相同
@Bean #全局配置
public IRule ribbonRule(){
return new RandomRule();
}
局部配置
book-service: #目標(biāo)微服務(wù)id
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
9、Zuul配置服務(wù)降級(jí)
Spring Cloud Zuul內(nèi)置Hystrix
服務(wù)降級(jí)實(shí)現(xiàn)接口:FallbackProvider
10、基于RateLimit實(shí)現(xiàn)網(wǎng)關(guān)限流
1.微服務(wù)網(wǎng)關(guān)流量控制
微服務(wù)網(wǎng)關(guān)是應(yīng)用入口,必須對(duì)入口流量進(jìn)行控制
RateLimit是Spring Cloud Zuul的限流組件
https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit
RateLimit采用“令牌桶”算法實(shí)現(xiàn)限流
2.什么是令牌桶

3.RateLimit使用步驟
依賴spring-cloud-zuul-ratelimit
配置存儲(chǔ)組件(關(guān)系數(shù)據(jù)庫、redis、緩存...)
配置限流策略
11、Zuul的執(zhí)行過程
1.Zuul的執(zhí)行過程

2.Http請(qǐng)求生命周期

3.Zuul內(nèi)置過濾器

12、自定義過濾器
1.需要實(shí)現(xiàn)ZuulFilter接口
shouldFilter() - 是否啟用該過濾器
filterOrder() - 設(shè)置過濾器執(zhí)行次序
filterType() - 過濾器類型:pre|routing|post
run() - 過濾邏輯
2.Zuul內(nèi)置過濾器

3.Zuul+JWT跨域身份驗(yàn)證

4.自定義Zuul過濾器
package com.itlaoqi.springcloud.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class SecurityFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 6;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//從RequestContext獲取上下文
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String token = request.getHeader("token");
if (token == null || token.trim().equals("")) {
//對(duì)該請(qǐng)求禁止路由,也就是禁止訪問下游服務(wù)
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(403);
ctx.setResponseBody("{\"status\":403,\"message\":\"Token not found\"}");
return null;
}else{
//校驗(yàn)Token正確性代碼
//...
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
return null;
}
}
}
五、springCloud配置中心
一、配置中心的分類
1.Spring Cloud Config
2.攜程 Apollo
3.阿里巴巴Nacos
二、微服務(wù)改造步驟
1.依賴"spring-cloud-starter-config"
2.刪除application.yml,新建bootstrap.yml
3.配置"配置中心"服務(wù)地址與環(huán)境信息
三、運(yùn)行時(shí)刷新配置參數(shù)
1、微服務(wù)依賴"spring-boot-starter-actuator";
2、動(dòng)態(tài)刷新類上增加@RefreshScope注解
3、通過/actuator/refresh刷新配置
四、Spring-Retry重試機(jī)制
1、通過加入重試機(jī)制、提高應(yīng)用啟動(dòng)的可靠性;
2、重試觸發(fā)條件1:配置中心無法與倉庫正常通信
3、重試觸發(fā)條件2:微服務(wù)無法配置中心正常通信