自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SpringCloud之Hystrix Turbine的簡(jiǎn)介與使用

運(yùn)維 系統(tǒng)運(yùn)維
Hystrix Dashboard 前面已經(jīng)知道了,它的主要功能是可以對(duì)某一項(xiàng)微服務(wù)進(jìn)行監(jiān)控,但真實(shí)情況下,不可能只對(duì)一個(gè)微服務(wù)進(jìn)行監(jiān)控。

[[408799]]

Spring Cloud Hystrix Turbine

Hystrix Dashboard 前面已經(jīng)知道了,它的主要功能是可以對(duì)某一項(xiàng)微服務(wù)進(jìn)行監(jiān)控,但真實(shí)情況下,不可能只對(duì)一個(gè)微服務(wù)進(jìn)行監(jiān)控,我們有很多微服務(wù),所以我們需要對(duì)很多微服務(wù)進(jìn)行監(jiān)控,這個(gè)時(shí)候就需要使用到turbine [ˈtɜːbaɪn] 來(lái)完成;

單個(gè)hystrix服務(wù)的監(jiān)控(如下圖):

多個(gè)hystrix服務(wù)的監(jiān)控(如下圖):

具體步驟:

首先準(zhǔn)備一個(gè)turbine模塊

1、創(chuàng)建一個(gè)

34-sprinGCloud-service-turbine項(xiàng)目,該項(xiàng)目依然是一個(gè)Springboot項(xiàng)目;

2、添加依賴:

  1. <!-- spring-cloud-starter-netflix-turbine --> 
  2. <dependency> 
  3.     <groupId>org.springframework.cloud</groupId> 
  4.     <artifactId>spring-cloud-starter-netflix-turbine</artifactId> 
  5. </dependency> 

 3、配置文件:

  1. server.port=3722 

#不向注冊(cè)中心注冊(cè)自己

  1. eureka.client.register-with-eureka=false 

#eureka注冊(cè)中心的連接地址

  1. eureka.client.service-url.defaultZone=http://192.168.10.128:8761/eureka,http://192.168.10.128:8762/eureka,http://192.168.10.128:8763/eureka 

#配置turbine

  1. turbine.app-config=34-SPRINGCLOUD-SERVICE-PORTAL,34-SPRINGCLOUD-SERVICE-PORTAL-2 

#需要有這個(gè),沒(méi)有的話聚合不了多個(gè)項(xiàng)目

  1. turbine.cluster-name-expression="default" 

4、在main方法的入口類上添加注解:

  1. @EnableTurbine //開(kāi)啟turbine 
  2. @SpringBootApplication 
  3. public class TurbineApplication { 
  4.     public static void main(String[] args) { 
  5.         SpringApplication.run(TurbineApplication.class, args); 
  6.     } 

接下來(lái)為了能對(duì)多個(gè)使用了hystrix的項(xiàng)目進(jìn)行監(jiān)控,我們?cè)贉?zhǔn)備一份項(xiàng)目,并且里面使用了hystrix:

34-sprinGCloud-service-portal-2(可以拷貝一份34-sprinGCloud-service-portal項(xiàng)目來(lái)制作)

注意點(diǎn)就是要先訪問(wèn)一下各個(gè)使用了hystrix的優(yōu)熔斷功能的接口,然后再測(cè)試turbine,否則你不訪問(wèn)的話,測(cè)試是不會(huì)有數(shù)據(jù)的;

  1. http://localhost:8080/cloud/goodsFeignHystrix 
  2.  
  3. http://localhost:8081/cloud/goodsLimit 
  4.  
  5. http://localhost:8080/actuator/hystrix.stream 
  6.  
  7. http://localhost:8081/actuator/hystrix.stream 
  8.  
  9. http://localhost:3722/turbine.stream 

Spring Cloud Zuul

通過(guò)前面內(nèi)容的學(xué)習(xí),我們已經(jīng)可以基本搭建出一套簡(jiǎn)略版的微服務(wù)架構(gòu)了,我們有注冊(cè)中心 Eureka,可以將服務(wù)注冊(cè)到該注冊(cè)中心中,我們有 Ribbon 或Feign 可以實(shí)現(xiàn)對(duì)服務(wù)負(fù)載均衡地調(diào)用,我們有 Hystrix 可以實(shí)現(xiàn)服務(wù)的熔斷;

我們來(lái)看一下下面的微服務(wù)架構(gòu)圖:

在上面的架構(gòu)圖中,我們的服務(wù)包括:內(nèi)部服務(wù) Service A 和內(nèi)部服務(wù) ServiceB,這兩個(gè)服務(wù)都是集群部署,每個(gè)服務(wù)部署了 3 個(gè)實(shí)例,他們都會(huì)通過(guò) EurekaServer 注冊(cè)中心注冊(cè)與訂閱服務(wù),而 Open Service 是一個(gè)對(duì)外的服務(wù),也是集群部署,外部調(diào)用方通過(guò)負(fù)載均衡設(shè)備調(diào)用 Open Service 服務(wù),比如負(fù)載均衡使用 Nginx、LVS、HAProxy,這樣的實(shí)現(xiàn)是否合理,或者是否有更好的實(shí)現(xiàn)方式呢?接下來(lái)我們主要圍繞該問(wèn)題展開(kāi)討論。

1、如果我們的微服務(wù)中有很多個(gè)獨(dú)立服務(wù)都要對(duì)外提供服務(wù),那么我們要如何去管理這些接口?特別是當(dāng)項(xiàng)目非常龐大的情況下要如何管理?

2、在微服務(wù)中,一個(gè)獨(dú)立的系統(tǒng)被拆分成了很多個(gè)獨(dú)立的服務(wù),為了確保安全,權(quán)限管理也是一個(gè)不可回避的問(wèn)題,如果在每一個(gè)服務(wù)上都添加上相同的權(quán)限驗(yàn)證代碼來(lái)確保系統(tǒng)不被非法訪問(wèn),那么工作量也就太大了,而且維護(hù)也非常不方便。

為了解決上述問(wèn)題,微服務(wù)架構(gòu)中提出了API網(wǎng)關(guān)的概念,它就像一個(gè)安檢站一樣,所有外部的請(qǐng)求都需要經(jīng)過(guò)它的調(diào)度與過(guò)濾,然后 API 網(wǎng)關(guān)來(lái)實(shí)現(xiàn)請(qǐng)求路由、負(fù)載均衡、權(quán)限驗(yàn)證等功能;

那么 Spring Cloud 這個(gè)一站式的微服務(wù)開(kāi)發(fā)框架基于 Netflix Zuul 實(shí)現(xiàn)了Spring Cloud Zuul,采用 Spring Cloud Zuul 即可實(shí)現(xiàn)一套 API 網(wǎng)關(guān)服務(wù);

Zuul

Zuul包含了對(duì)請(qǐng)求的路由和過(guò)濾兩個(gè)最主要的功能:

其中路由功能負(fù)責(zé)將外部請(qǐng)求轉(zhuǎn)發(fā)到具體的微服務(wù)實(shí)例上,是實(shí)現(xiàn)外部訪問(wèn)統(tǒng)一入口的基礎(chǔ),過(guò)濾功能則負(fù)責(zé)對(duì)請(qǐng)求的處理過(guò)程進(jìn)行干預(yù),是實(shí)現(xiàn)請(qǐng)求校驗(yàn)、服務(wù)聚合等功能的基礎(chǔ);

Zuul和Eureka進(jìn)行整合,將Zuul自身注冊(cè)為Eureka服務(wù)治理下的應(yīng)用,同時(shí)從Eureka中獲得其他微服務(wù)的信息,也即以后的訪問(wèn)微服務(wù)都是通過(guò)Zuul跳轉(zhuǎn)后獲得。

路由功能:

項(xiàng)目加入依賴:

  1. <!--spring-cloud-starter-netflix-eureka-client--> 
  2. <dependency> 
  3.     <groupId>org.springframework.cloud</groupId> 
  4.     <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 
  5. </dependency> 
  6. <!-- spring-cloud-starter-netflix-zuul --> 
  7. <dependency> 
  8.     <groupId>org.springframework.cloud</groupId> 
  9.     <artifactId>spring-cloud-starter-netflix-zuul</artifactId> 
  10. </dependency> 

由于Zuul最終會(huì)注冊(cè)進(jìn)eureka,所以我們此處也依賴了eureka;

配置文件:

  1. server.port=80 

#是eureka注冊(cè)中心首頁(yè)的Application這一欄

  1. spring.application.name=34-sprinGCloud-service-zuul 

#每間隔2s,向服務(wù)端發(fā)送一次心跳,證明自己依然"存活"

  1. eureka.instance.lease-renewal-interval-in-seconds=2 

#告訴服務(wù)端,如果我10s之內(nèi)沒(méi)有給你發(fā)心跳,就代表我故障了,將我踢出掉

  1. eureka.instance.lease-expiration-duration-in-seconds=10 

#告訴服務(wù)端,服務(wù)實(shí)例以IP作為鏈接,而不是取機(jī)器名

  1. eureka.instance.prefer-ip-address=true 

#告訴服務(wù)端,服務(wù)實(shí)例的id,id必須要唯一,是eureka注冊(cè)中心首頁(yè)的Status這一欄

  1. eureka.instance.instance-id=34-sprinGCloud-service-zuul 

#eureka注冊(cè)中心的連接地址

  1. eureka.client.service-url.defaultZone=http://192.168.10.128:8761/eureka,http://192.168.10.128:8762/eureka,http://192.168.10.128:8763/eureka 

啟動(dòng)類上:

  1. @EnableZuulProxy 
  2. @SpringBootApplication 
  3. public class ZuulApplication { 
  4.     public static void main(String[] args) { 
  5.         SpringApplication.run(ZuulApplication.class, args); 
  6.     } 

這樣簡(jiǎn)單的zuul就搭建好了, 啟動(dòng)項(xiàng)目我們即可通過(guò)zuul然后加上對(duì)應(yīng)的微服務(wù)名字訪問(wèn)微服務(wù),比如:

  1. http://localhost/34-sprinGCloud-service-portal/cloud/goodsFeign 
  2.  
  3. http://localhost:80/ 

這個(gè)是zuul本身的

  1. 34-sprinGCloud-service-portal 

這個(gè)是要調(diào)用的項(xiàng)目名稱

  1. /cloud/goodsFeign 

這個(gè)是被調(diào)用的contrller上的接口路徑;

在實(shí)際開(kāi)發(fā)當(dāng)中我們肯定不會(huì)通過(guò)微服務(wù)名去調(diào)用,比如我要調(diào)用消費(fèi)者可能只要一個(gè)/cloud/goodsFeign就好了,而不是

/34-sprinGCloud-service-portal/cloud/goodsFeign

加入以下配置即可:

#配置路由規(guī)則

  1. zuul.routes.portal.service-id=34-sprinGCloud-service-portal 
  2. zuul.routes.portal.path=/portal/** 

然后:

  1. http://localhost/portal/cloud/goodsFeignHystrix 
  2.  
  3. / **代表是所有(多個(gè))層級(jí) /cloud/goodsFeignHystrix 
  4.  
  5. / * 是代表一層; 
  6.  
  7. 如果是/ * 的話 /api/goods 就不會(huì)被路由; 

此時(shí)我們能通過(guò)自定義的規(guī)則進(jìn)行訪問(wèn),但是我們現(xiàn)在依然能用之前的微服務(wù)名調(diào)用,這是不合理的,第一是有多重地址了, 第二一般微服務(wù)名這種最好不要暴露在外,所以我們一般會(huì)禁用微服務(wù)名方式調(diào)用。

加入配置:

  1. zuul.ignored-services=34-sprinGCloud-service-portal 

這里能發(fā)現(xiàn)我們不能通過(guò)微服務(wù)名來(lái)調(diào)用了, 不過(guò)這個(gè)配置如果一個(gè)一個(gè)通過(guò)微服務(wù)名來(lái)配置難免有點(diǎn)復(fù)雜,所以一般這樣配置來(lái)禁用所有:

  1. zuul.ignored-services=* 

可能有時(shí)候我們的接口調(diào)用需要一定的規(guī)范,比如調(diào)用微服務(wù)的API URL前綴需要加上/api 對(duì)于這種情況,zuul也考慮到了并給出了解決方案:

  1. zuul.prefix=/api 

比如:

http://localhost/api/portal/cloud/goodsFeignHystrix

通配符

過(guò)濾器:

限流、權(quán)限驗(yàn)證、記錄日志

過(guò)濾器 (filter) 是zuul的核心組件,zuul大部分功能都是通過(guò)過(guò)濾器來(lái)實(shí)現(xiàn)的。 zuul中定義了4種標(biāo)準(zhǔn)過(guò)濾器類型,這些過(guò)濾器類型對(duì)應(yīng)于請(qǐng)求的典型生命周期。

  • PRE:這種過(guò)濾器在請(qǐng)求被路由之前調(diào)用??衫眠@種過(guò)濾器實(shí)現(xiàn)身份驗(yàn)證、在 集群中選擇請(qǐng)求的微服務(wù)、記錄調(diào)試信息等。
  • ROUTING:這種過(guò)濾器將請(qǐng)求路由到微服務(wù)。這種過(guò)濾器用于構(gòu)建發(fā)送給微服 務(wù)的請(qǐng)求,并使用 Apache HttpClient或 Netfilx Ribbon請(qǐng)求微服務(wù)
  • POST:這種過(guò)濾器在路由到微服務(wù)以后執(zhí)行。這種過(guò)濾器可用來(lái)為響應(yīng)添加標(biāo)準(zhǔn) 的 HTTP Header、收集統(tǒng)計(jì)信息和指標(biāo)、將響應(yīng)從微服務(wù)發(fā)送給客戶端等。
  • ERROR:在其他階段發(fā)生錯(cuò)誤時(shí)執(zhí)行該過(guò)濾器。

如果要編寫(xiě)一個(gè)過(guò)濾器,則需繼承ZuulFilter類實(shí)現(xiàn)其中的方法:

  1. @Component 
  2. public class LogFilter extends ZuulFilter { 
  3.     @Override 
  4.     public String filterType() { 
  5.         return FilterConstants.ROUTE_TYPE; 
  6.     } 
  7.     @Override 
  8.     public int filterOrder() { 
  9.         return FilterConstants.PRE_DECORATION_FILTER_ORDER; 
  10.     } 
  11.     @Override 
  12.     public boolean shouldFilter() { 
  13.         return true
  14.     } 
  15.     @Override 
  16.     public Object run() throws ZuulException { 
  17.         RequestContext currentContext = RequestContext.getCurrentContext(); 
  18.         HttpServletRequest request = currentContext.getRequest(); 
  19.         String remoteAddr = request.getServerName(); 
  20.         System.out.println("訪問(wèn)地址:"+request.getRequestURI()); 
  21.         return null
  22.     } 

由代碼可知,自定義的 zuul Filter需實(shí)現(xiàn)以下幾個(gè)方法。

filterType: 返回過(guò)濾器的類型。

有 pre、 route、 post、 error等幾種取值,分別對(duì)應(yīng)上文的幾種過(guò)濾器。

詳細(xì)可以參考

com.netflix.zuul.ZuulFilter.filterType()中的注釋;

filter0rder:返回一個(gè) int值來(lái)指定過(guò)濾器的執(zhí)行順序,不同的過(guò)濾器允許返回相同的數(shù)字。

shouldFilter:返回一個(gè) boolean值來(lái)判斷該過(guò)濾器是否要執(zhí)行, true表示執(zhí)行, false表示不執(zhí)行。

run:過(guò)濾器的具體邏輯;

zuul過(guò)濾器的禁用

Spring Cloud默認(rèn)為Zuul編寫(xiě)并啟用了一些過(guò)濾器,例如DebugFilter、FormBodyWrapperFilter等,這些過(guò)濾器都存放在spring-cloud-netflix-zuul這個(gè)jar包里,一些場(chǎng)景下,想要禁用掉部分過(guò)濾器,該怎么辦呢? 只需在application.properties里設(shè)置zuul...disable=true 例如,要禁用上面我們寫(xiě)的過(guò)濾器,這樣配置就行了:

  1. zuul.LogFilter.route.disable=true 

Zuul 的異常處理

Spring Cloud Zuul 對(duì)異常的處理是非常方便的,但是由于 Spring Cloud 處于迅速發(fā)展中,各個(gè)版本之間有所差異,本案例是以 Finchley.RELEASE 版本為例, 來(lái)說(shuō)明 Spring Cloud Zuul 中的異常處理問(wèn)題。

首先我們來(lái)看一張官方給出的 Zuul 請(qǐng)求的生命周期圖:

1.正常情況下所有的請(qǐng)求都是按照 pre、route、post 的順序來(lái)執(zhí)行,然后由 post 返回 response

2.在 pre 階段,如果有自定義的過(guò)濾器則執(zhí)行自定義的過(guò)濾器

3.pre、routing、post 的任意一個(gè)階段如果拋異常了,則執(zhí)行 error 過(guò)濾器

我們可以統(tǒng)一處理異常:

怎么實(shí)現(xiàn),步驟:

1、禁用 zuul 默認(rèn)的異常處理 SendErrorFilter 過(guò)濾器,然后自定義我們自己的Errorfilter 過(guò)濾器

  1. zuul.SendErrorFilter.error.disable=true 
  2.   
  3. @Component 
  4. public class ErrorFilter extends ZuulFilter { 
  5.     @Override 
  6.     public String filterType() { 
  7.         return "error"
  8.     } 
  9.     @Override 
  10.     public int filterOrder() { 
  11.         return 1; 
  12.     } 
  13.     @Override 
  14.     public boolean shouldFilter() { 
  15.         return true
  16.     } 
  17.     @Override 
  18.     public Object run() throws ZuulException { 
  19.         try { 
  20.             RequestContext context = RequestContext.getCurrentContext(); 
  21.             ZuulException exception = (ZuulException)context.getThrowable(); 
  22.             System.out.println("進(jìn)入系統(tǒng)異常攔截" + exception.getMessage()); 
  23.             HttpServletResponse response = context.getResponse(); 
  24.             response.setContentType("application/json; charset=utf8"); 
  25.             response.setStatus(exception.nStatusCode); 
  26.             PrintWriter writer = null
  27.             try { 
  28.                 writer = response.getWriter(); 
  29.                 writer.print("{code:"+ exception.nStatusCode +",message:\""
  30.                         exception.getMessage() +"\"}"); 
  31.             } catch (IOException e) { 
  32.                 e.printStackTrace(); 
  33.             } finally { 
  34.                 if(writer!=null){ 
  35.                     writer.close(); 
  36.                 } 
  37.             } 
  38.         } catch (Exception e) { 
  39.             ReflectionUtils.rethrowRuntimeException(e); 
  40.         } 
  41.         return null
  42.     } 

Zuul的熔斷降級(jí)

zuul是一個(gè)代理服務(wù),但如果被代理的服務(wù)突然斷了,這個(gè)時(shí)候zuul上面會(huì)有出錯(cuò)信息,例如,停止了被調(diào)用的微服務(wù);

一般服務(wù)方自己會(huì)進(jìn)行服務(wù)的熔斷降級(jí),但對(duì)于zuul本身,也應(yīng)該進(jìn)行zuul的降級(jí)處理;

我們需要有一個(gè)zuul的降級(jí),實(shí)現(xiàn)如下:

  1. @Component 
  2. public class ProviderFallback implements FallbackProvider { 
  3.     @Override 
  4.     public String getRoute() { 
  5.         return "*"
  6.     } 
  7.     @Override 
  8.     public ClientHttpResponse fallbackResponse(String route, Throwable cause) { 
  9.         return new ClientHttpResponse() { 
  10.             @Override 
  11.             public HttpHeaders getHeaders() { 
  12.                 HttpHeaders headers = new HttpHeaders(); 
  13.                 headers.set("Content-Type""text/html; charset=UTF-8"); 
  14.                 return headers; 
  15.             } 
  16.             @Override 
  17.             public InputStream getBody() throws IOException { 
  18.                 // 響應(yīng)體 
  19.                 return new ByteArrayInputStream("服務(wù)正在維護(hù),請(qǐng)稍后再試.".getBytes()); 
  20.             } 
  21.             @Override 
  22.             public HttpStatus getStatusCode() throws IOException { 
  23.                 return HttpStatus.BAD_REQUEST; 
  24.             } 
  25.             @Override 
  26.             public int getRawStatusCode() throws IOException { 
  27.                 return HttpStatus.BAD_REQUEST.value(); 
  28.             } 
  29.             @Override 
  30.             public String getStatusText() throws IOException { 
  31.                 return HttpStatus.BAD_REQUEST.getReasonPhrase(); 
  32.             } 
  33.             @Override 
  34.             public void close() { 
  35.             } 
  36.         }; 
  37.     } 
  38. }  
責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2021-06-30 07:34:21

SpringCloudHystrix 監(jiān)控

2022-05-13 09:05:49

Hystrix熔斷器

2017-04-03 21:52:30

隔離線程池分布式

2023-02-03 15:16:42

SpringHystrix

2021-08-26 11:52:32

FeignWeb服務(wù)

2010-01-13 13:27:07

CentOS vsft

2021-12-10 09:45:19

生成器配置代碼

2021-03-26 06:01:45

日志MongoDB存儲(chǔ)

2010-03-23 16:28:31

CentOS使用

2022-07-04 08:14:24

架構(gòu)演變Tomcat容器架構(gòu)

2022-09-15 15:25:47

spring-微服務(wù)

2010-07-07 09:48:05

UML

2009-11-06 16:48:03

WCF簡(jiǎn)介

2021-03-25 15:54:14

鴻蒙HarmonyOS應(yīng)用開(kāi)發(fā)

2011-04-19 17:06:24

bada控件bada

2009-06-11 17:13:44

J2EE設(shè)計(jì)模式Dao設(shè)計(jì)模式

2011-07-04 14:33:07

PHP

2011-07-08 16:47:07

SEAM

2011-03-25 09:18:59

Nagios

2016-09-20 15:47:46

JavascriptIndexedDB瀏覽器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)