eureka註冊中心
- eureka註冊中心是spring cloud微服務的基石.
- 所有微服務都需要註冊到eureka上,提供自己的請求地址給其他註冊到eureka上的微服務已發現。
每間隔30s微服務會向eureka發送一次心跳數據,當eureka90s沒有收到響應心跳時,會認爲該服務不可用,默認不會剔除該服務(可調整) - 和zookeeper比較,zookeeper注重數據的一致性,而eureka更注重系統的可用性
- application.yml簡單配置
application.name=eureka
server.port=2001
defaultZone=http://localhost:2001/eureka
ribbon負載均衡和重試
- 單獨使用 ribbon,開啓重試需要自己寫代碼,添加重試參數配置
後面 ribbon 被 feign 和 zuul 封裝,不做任何配置,不寫任何代碼,可以
直接使用負載均衡和重試 - 簡單代碼演示
- 負載均衡
@LoadBalanced //負載均衡註解
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
- 重試添加 spring-retry 依賴
ribbon:
MaxAutoRetriesNextServer: 2 #更換實例的次數
MaxAutoRetries: 1 #當前實例重試次數,嘗試失敗會更換下一個實例
OkToRetryOnAllOperations: true #默認只對GET請求重試, 當設置爲true時, 對POST等所有類型請求都重試
代碼
@LoadBalanced
@Bean
public RestTemplate getRestTemplate() {
SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
f.setConnectTimeout(1000);
f.setReadTimeout(1000);
return new RestTemplate(f);
}
hystrix斷路器 降級和熔斷
- 降級:
當服務不可用,或者訪問超時,可以執行降級代碼,可以返回錯誤信息,或者返回緩存數據 - 熔斷:
10秒內請求數量達到20個,並且,有50% 出現失敗降級的情況,會打開斷路器,所有的請求,都直接降級,不再向後臺微服務轉發
斷路器打開5秒後,會處於半開狀態,當請求到達時,會嘗試向後臺符轉發,如果成功,會關閉斷路器,如果仍然失敗,保持打開狀態
Hystrix dashboard 儀表盤
圖形化展示各個請求的情況
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
暴露 hystrix.stream 監控端點
management:
endpoints:
web:
exposure:
include: hystrix.stream
訪問hystrix微服務
http://localhost:4001/hystrix
填入 hystrix 的監控端點,開啓監控
http://localhost:3001/actuator/hystrix.stream
feign 聲明式客戶端,只定義遠程調用接口
- 整合 ribbon 和 部分hystrix
- 默認啓用負載均衡和重試
- 啓用 hystrix: yml文件中添加配置 feign.hystrix.enabled=true
@FeignClient(name="服務id", fallback=XxxFB.class)//降級實現類,建議(接口名+FB)結尾
interface A {
@GetMapping("/xxxx")
JsonResult f(@RequestParameter String name);
}
zuul API網關
spring cloud 對外的統一大門,提供統一的調用入口,所有的系統請求都需要經過zuul的攔截過濾
- yml路徑配置,當微服務名和請求路徑前綴一致時可不配置
zuul:
routes:
item-service: /item-service/**
user-service: /user-service/**
order-service: /order-service/**
依然默認啓用負載均衡,不過重試需要添加spring-retry依賴
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
並yml中配置重試參數啓動
zuul:
retryable: true
ribbon:
ConnectTimeout: 1000
ReadTimeout: 1000
MaxAutoRetriesNextServer: 1
MaxAutoRetries: 1
-
zuul + hystrix 降級
-
需要實現FallbackProvider 接口,並在方法getRoute() 中指定應用此降級類的服務id,星號或null值可以通配所有服務
-
定義過濾器,需要繼承 ZuulFilter
package cn.tedu.sp11.filter;
import javax.servlet.http.HttpServletRequest;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import cn.tedu.web.util.JsonResult;
@Component
public class AccessFilter extends ZuulFilter{
@Override
public boolean shouldFilter() {
//對指定的serviceid過濾,如果要過濾所有服務,直接返回 true
RequestContext ctx = RequestContext.getCurrentContext();
String serviceId = (String) ctx.get(FilterConstants.SERVICE_ID_KEY);
if(serviceId.equals("item-service")) {
return true;
}
return false;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest req = ctx.getRequest();
String token = req.getParameter("token");
if (token == null) {
//此設置會阻止請求被路由到後臺微服務
ctx.setSendZuulResponse(false);
//向客戶端的響應
ctx.setResponseStatusCode(200);
ctx.setResponseBody(JsonResult.err().code(JsonResult.NOT_LOGIN).toString());
}
//zuul過濾器返回的數據設計爲以後擴展使用,
//目前該返回值沒有被使用
return null;
}
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
//該過濾器順序要 > 5,才能得到 serviceid
return FilterConstants.PRE_DECORATION_FILTER_ORDER+1;
}
}
- zuul + hystrix 數據監控
- zuul中已經包含 actuator 依賴,所以只需要暴露 hystrix.stream 監控端點即可
management:
endpoints:
web:
exposure:
include: hystrix.stream
turbine 聚合監控
hystrix dashboard 一次只能監控一個服務實例,使用 turbine 可以彙集監控信息,將聚合後的信息提供給 hystrix dashboard 來集中展示和監控
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
turbine:
app-config: zuul
cluster-name-expression: new String("default")
sleuth 鏈路跟蹤及zipkin 鏈路分析
隨着系統規模越來越大,微服務之間調用關係變得錯綜複雜,一條調用鏈路中可能調用多個微服務,任何一個微服務不可用都可能造整個調用過程失敗
sleuth 可以跟蹤調用鏈路,分析鏈路中每個節點的執行情況
添加pom依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
此時通過zull網關,在微服務的控制檯日誌中,可以看到以下信息:
[服務id,請求id,span id,是否發送到zipkin]
- 請求id:請求到達第一個微服務時生成一個請求id,該id在調用鏈路中會一直向後面的微服務傳遞
- span id:鏈路中每一步微服務調用,都生成一個新的id
[zuul,6c24c0a7a8e7281a,6c24c0a7a8e7281a,false]
[order-service,6c24c0a7a8e7281a,993f53408ab7b6e3,false]
[item-service,6c24c0a7a8e7281a,ce0c820204dbaae1,false]
[user-service,6c24c0a7a8e7281a,fdd1e177f72d667b,false]
zipkin 可以收集鏈路跟蹤數據,提供可視化的鏈路分析
下載 zipkin 服務器
啓動 zipkin 時,連接到 rabbitmq
java -jar zipkin-server-2.12.9-exec.jar --zipkin.collector.rabbitmq.uri=amqp://admin:[email protected]:5672
訪問zipkin服務器
在微服務中添加zipkin 起步依賴
- 如果沒有配置過 spring cloud bus,還需要添加 rabbitmq 依賴和連接信息
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
鏈路跟蹤數據中,默認只有 10% 會被收集到zipkin,如果沒有看到多請求幾次就好
參考資料
Spring Cloud入門操作手冊