javascript
SpringCloud学习一
文章目錄
- SpringCLoud
- 總覽
- 服務(wù)注冊(cè)/發(fā)現(xiàn)&注冊(cè)中心
- 1、Eureka
- 2、Consul
- 3、Zookeeper
- 服務(wù)接口調(diào)用
- OpenFeign
- 負(fù)載均衡
- Ribbon(蝴蝶結(jié))
- 服務(wù)熔斷降級(jí)
- Hystrix(豪豬獸)
- 1、服務(wù)降級(jí)
- 2、服務(wù)熔斷
- 3、服務(wù)監(jiān)控
- 服務(wù)網(wǎng)關(guān)
- 1、Gateway
- 路由轉(zhuǎn)發(fā)
- Filter
- 服務(wù)配置中心
- 實(shí)現(xiàn):
- 動(dòng)態(tài)刷新
- 消息總線
- Bus
- 廣播
- 定點(diǎn)通知
- 消息驅(qū)動(dòng)
- Stream
SpringCLoud
總覽
參考鏈接
服務(wù)注冊(cè)/發(fā)現(xiàn)&注冊(cè)中心
1、Eureka
服務(wù)注冊(cè)(服務(wù)提供者)/發(fā)現(xiàn)(服務(wù)調(diào)用者)&注冊(cè)中心(服務(wù)中介)
-
服務(wù)注冊(cè):
當(dāng) Eureka 客戶端向 Eureka Server 注冊(cè)時(shí),它提供自身的元數(shù)據(jù),比如IP地址、端口,運(yùn)行狀況指示符URL,主頁(yè)等。
-
服務(wù)續(xù)約:
Eureka 客戶會(huì)每隔30秒(默認(rèn)情況下)發(fā)送一次心跳來(lái)續(xù)約。通過(guò)續(xù)約來(lái)告知 Eureka Server 該 Eureka 客戶仍然存在,沒(méi)有出現(xiàn)問(wèn)題。正常情況下,如果 Eureka Server 在90秒沒(méi)有收到 Eureka 客戶的續(xù)約,它會(huì)將實(shí)例從其注冊(cè)表中刪除。
-
服務(wù)下線
Eureka客戶端在程序關(guān)閉時(shí)向Eureka服務(wù)器發(fā)送取消請(qǐng)求。發(fā)送請(qǐng)求后,該客戶端實(shí)例信息將從服務(wù)器的實(shí)例注冊(cè)表中刪除。該下線請(qǐng)求不會(huì)自動(dòng)完成,它需要調(diào)用以下內(nèi)容:DiscoveryManager.getInstance().shutdownComponent();
-
服務(wù)剔除
在默認(rèn)的情況下,當(dāng)Eureka客戶端連續(xù)90秒(3個(gè)續(xù)約周期)沒(méi)有向Eureka服務(wù)器發(fā)送服務(wù)續(xù)約,即心跳,Eureka服務(wù)器會(huì)將該服務(wù)實(shí)例從服務(wù)注冊(cè)列表刪除,即服務(wù)剔除。
-
獲取注冊(cè)列表信息 Fetch Registries
Eureka 客戶端從服務(wù)器獲取注冊(cè)表信息,并將其緩存在本地 。 該注冊(cè)列表信息定期(每30秒鐘)更新一次。 在默認(rèn)的情況下 Eureka 客戶端使用壓縮 JSON 格式來(lái)獲取注冊(cè)列表的信息。
-
架構(gòu)圖
-
步驟
-
注冊(cè)中心
-
pom(版本隨父項(xiàng)目)
父項(xiàng)目
<!--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>注冊(cè)中心
<!--eureka-server--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> -
yml
fetch-registry為true表示獲取注冊(cè)信息列表,如果該項(xiàng)目就是注冊(cè)中心,則為false表示不用去獲取。
eureka:instance:hostname: eureka7001.com #eureka服務(wù)端的實(shí)例名稱client:register-with-eureka: false #false表示不向注冊(cè)中心注冊(cè)自己。fetch-registry: false #false表示自己端就是注冊(cè)中心,我的職責(zé)就是維護(hù)服務(wù)實(shí)例,并不需要去檢索服務(wù)service-url:#集群指向其它eureka# defaultZone: http://eureka7002.com:7002/eureka/#單機(jī)就是7001自己defaultZone: http://eureka7001.com:7001/eureka/#server:#關(guān)閉自我保護(hù)機(jī)制,保證不可用服務(wù)被及時(shí)踢除#enable-self-preservation: false#eviction-interval-timer-in-ms: 2000此路徑下找到hosts文件C:\Windows\System32\drivers\etc,并增加一下信息,方便直接通過(guò)域名訪問(wèn)
# springcloud-eureka 127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com -
主啟動(dòng)類
@EnableEurekaServer注解開啟Eureka
@SpringBootApplication @EnableEurekaServer public class EurekaServerMain7001 {public static void main(String[] args) {SpringApplication.run(EurekaServerMain7001.class,args);} }
-
-
客戶端
-
pom
<!-- eureka-client --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency> -
yml
eureka:client:register-with-eureka: true #將自身注冊(cè)到eurekafetch-registry: trueservice-url:defaultZone: http://localhost:7001/eureka # http://eureka7001.com:7001/eureka/ 也可以# defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版 -
啟動(dòng)類
@EnableEurekaClient
@SpringBootApplication @EnableEurekaClient public class PaymentMain8001 {public static void main(String[] args) {SpringApplication.run(PaymentMain8001.class, args);} }
2、Consul
3、Zookeeper
服務(wù)接口調(diào)用
OpenFeign
OpenFeign 直接內(nèi)置了 Ribbon。
RestTemplate是Spring提供的一個(gè)訪問(wèn)Http服務(wù)的客戶端類 。例如以下例子,我們就能通過(guò)/judge路徑訪問(wèn)到http://localhost:8081//service1
@Autowired private RestTemplate restTemplate; // 這里是提供者A的ip地址,但是如果使用了 Eureka 那么就應(yīng)該是提供者A的名稱 privatestaticfinal String SERVICE_PROVIDER_A = "http://localhost:8081";@PostMapping("/judge") public boolean judge(@RequestBody Request request) {String url = SERVICE_PROVIDER_A + "/service1";return restTemplate.postForObject(url, request, Boolean.class); }使用有些麻煩。OpenFeign能做到向 域名和IP地址的映射一樣進(jìn)行服務(wù)間的調(diào)用
-
實(shí)現(xiàn)
- 消費(fèi)端
-
pom
<!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency> -
yml
將默認(rèn)等待時(shí)間延長(zhǎng),默認(rèn)為一秒,因?yàn)檫B接遠(yuǎn)程服務(wù)器已經(jīng)多個(gè)項(xiàng)目直接的調(diào)用容易造成超時(shí)。
#設(shè)置feign客戶端超時(shí)時(shí)間(OpenFeign默認(rèn)支持ribbon) ribbon: #指的是建立連接所用的時(shí)間,適用于網(wǎng)絡(luò)狀況正常的情況下,兩端連接所用的時(shí)間ReadTimeout: 5000 #指的是建立連接后從服務(wù)器讀取到可用資源所用的時(shí)間ConnectTimeout: 5000 -
主啟動(dòng)類
@SpringBootApplication @EnableFeignClients public class OrderFeignMain80 {public static void main(String[] args) {SpringApplication.run(OrderFeignMain80.class, args);} } -
service
@Component @FeignClient(value = "CLOUD-PAYMENT-SERVICE") public interface PaymentFeignService {@GetMapping(value = "/payment/get/{id}")public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);@GetMapping(value = "/payment/feign/timeout")public String paymentFeignTimeout(); } -
Controller
Controller 就可以像原來(lái)調(diào)用 Service 層代碼一樣調(diào)用它了。
@RestController @Slf4j public class OrderFeignController {@Resourceprivate PaymentFeignService paymentFeignService;@GetMapping(value = "/consumer/payment/get/{id}")public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){return paymentFeignService.getPaymentById(id);}@GetMapping(value = "/consumer/payment/feign/timeout")public String paymentFeignTimeout(){// OpenFeign客戶端一般默認(rèn)等待1秒鐘return paymentFeignService.paymentFeignTimeout();} } -
提供端
實(shí)現(xiàn)@FeignClient注解標(biāo)注類的路徑映射即可
負(fù)載均衡
Ribbon(蝴蝶結(jié))
它是在消費(fèi)者端進(jìn)行的負(fù)載均衡 。
- RoundRobinRule:輪詢策略。Ribbon默認(rèn)采用的策略。若經(jīng)過(guò)一輪輪詢沒(méi)有找到可用的provider,其最多輪詢 10 輪。若最終還沒(méi)有找到,則返回 null。(默認(rèn))
- RandomRule: 隨機(jī)策略,從所有可用的 provider 中隨機(jī)選擇一個(gè)。
- RetryRule: 重試策略。先按照 RoundRobinRule 策略獲取 provider,若獲取失敗,則在指定的時(shí)限內(nèi)重試。默認(rèn)的時(shí)限為 500 毫秒。
實(shí)現(xiàn):
配置類
@Configuration public class ApplicationContextConfig {@Bean@LoadBalancedpublic RestTemplate getRestTemplate(){return new RestTemplate();} }注意:先啟動(dòng)Eureka,再啟動(dòng)提供端,再啟動(dòng)消費(fèi)端
自定義負(fù)載均衡算法
實(shí)現(xiàn) IRule 接口
修改配置文件或者自定義 Java Config 類。
不能與啟動(dòng)類在同級(jí)包,也不能在啟動(dòng)類同級(jí)包的子包下。
以下啟動(dòng)類在com.lx下
自定義負(fù)載均衡在com.myrule下
@Configuration public class MySelfRule {@Beanpublic IRule myRule(){return new RandomRule();//定義為隨機(jī)} }服務(wù)熔斷降級(jí)
Hystrix(豪豬獸)
Hystrix是一個(gè)庫(kù),可通過(guò)添加等待時(shí)間容限和容錯(cuò)邏輯來(lái)幫助您控制這些分布式服務(wù)之間的交互。Hystrix通過(guò)隔離服務(wù)之間的訪問(wèn)點(diǎn),停止服務(wù)之間的級(jí)聯(lián)故障并提供后備選項(xiàng)來(lái)實(shí)現(xiàn)此目的,所有這些都可以提高系統(tǒng)的整體彈性。
在微服務(wù)場(chǎng)景中,通常會(huì)有很多層的服務(wù)調(diào)用。如果一個(gè)底層服務(wù)出現(xiàn)問(wèn)題,故障會(huì)被向上傳播給用戶。我們需要一種機(jī)制,當(dāng)?shù)讓臃?wù)不可用時(shí),可以阻斷故障的傳播。這就是斷路器的作用。他是系統(tǒng)服務(wù)穩(wěn)定性的最后一重保障。
在springcloud中斷路器組件就是Hystrix。Hystrix也是Netflix套件的一部分。他的功能是,當(dāng)對(duì)某個(gè)服務(wù)的調(diào)用在一定的時(shí)間內(nèi)(默認(rèn)10000ms),有超過(guò)一定次數(shù)(默認(rèn)20次)并且失敗率超過(guò)一定值(默認(rèn)50%),(更多詳情見HystrixCommandProperties類),該服務(wù)的斷路器會(huì)打開。返回一個(gè)由開發(fā)者設(shè)定的fallback。
fallback可以是另一個(gè)由Hystrix保護(hù)的服務(wù)調(diào)用,也可以是固定的值。fallback也可以設(shè)計(jì)成鏈?zhǔn)秸{(diào)用,先執(zhí)行某些邏輯,再返回fallback。
Hystrix的作用
1、服務(wù)降級(jí)
情景:
實(shí)現(xiàn):
pom
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>主啟動(dòng)
@SpringBootApplication @EnableEurekaClient @EnableCircuitBreaker public class PaymentHystrixMain8001 {public static void main(String[] args) {SpringApplication.run(PaymentHystrixMain8001.class,args);}/***此配置是為了服務(wù)監(jiān)控而配置,與服務(wù)容錯(cuò)本身無(wú)關(guān),springcloud升級(jí)后的坑*ServletRegistrationBean因?yàn)閟pringboot的默認(rèn)路徑不是"/hystrix.stream",*只要在自己的項(xiàng)目里配置上下面的servlet就可以了*/@Beanpublic ServletRegistrationBean getServlet() {HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);registrationBean.setLoadOnStartup(1);registrationBean.addUrlMappings("/hystrix.stream");registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean;} }service
/*** @Description: 正常訪問(wèn)* @Param0: id**/ public String paymentInfo_OK(Integer id) {return "線程池: "+Thread.currentThread().getName()+" paymentInfo_OK,id: "+id+"\t"+"O(∩_∩)O哈哈~"; }/*** @Description: 超時(shí)訪問(wèn)/訪問(wèn)異常,2s* @Param0: id**/ @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="2000")}) public String paymentInfo_TimeOut(Integer id) {int timeSleep=3000;try { TimeUnit.MILLISECONDS.sleep(timeSleep); } catch (InterruptedException e) { e.printStackTrace(); }return "線程池: "+Thread.currentThread().getName()+" id: "+id+"\t"+"O(∩_∩)O哈哈~"+" 耗時(shí)(毫秒): "+timeSleep; } /*** @Description: 超時(shí)處理**/ public String paymentInfo_TimeOutHandler(Integer id) {return "線程池: "+Thread.currentThread().getName()+" 8001系統(tǒng)繁忙,請(qǐng)稍后再試,id: "+id+"\t"+"o(╥﹏╥)o"; } /*** @Description: 訪問(wèn)異常* @Param0: id**/ @HystrixCommand(fallbackMethod = "paymentInfo_ExceptionHandler") public String paymentInfo_Exception(Integer id) {int i=10/0;return "線程池: "+Thread.currentThread().getName()+" id: "+id+"\t"+"O(∩_∩)O哈哈~"+" 結(jié)果 "+i; } /*** @Description: 異常處理**/ public String paymentInfo_ExceptionHandler(Integer id) {return "線程池: "+Thread.currentThread().getName()+" 8001運(yùn)行報(bào)錯(cuò),請(qǐng)稍后再試,id: "+id+"\t"+"o(╥﹏╥)o"; }問(wèn)題:
改善
在調(diào)用端controller類上加上@DefaultProperties注解,指定整個(gè)類的全局降級(jí)處理方法
@RestController @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod") public class OrderOpenFeignController {@ResourcePaymentService paymentService;@ResourcePaymentHystrixService paymentHystrixService;@GetMapping("/consumer/payment/get/{id}")public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {return paymentService.getPaymentByid(id);}@GetMapping("/consumer/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_OK(id);System.out.println("*****result: "+result);return result;}@GetMapping("/consumer/payment/hystrix/timeout/{id}")/* @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")})*///使用全局處理之后寫下面的注解,不加屬性代表使用默認(rèn)的全局處理方法@HystrixCommandpublic String paymentInfo_TimeOut(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_TimeOut(id);System.out.println("*****result: "+result);return result;}public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){return "timeout";}// 下面是全局fallback方法public String payment_Global_FallbackMethod(){return "Global異常處理信息,請(qǐng)稍后再試,/(ㄒoㄒ)/~~";}}2、服務(wù)熔斷
類比保險(xiǎn)絲達(dá)到最大服務(wù)訪問(wèn)后,直接拒絕訪問(wèn),拉閘限電,然后調(diào)用服務(wù)降級(jí)的方法并返回友好提示 。
服務(wù)的降級(jí)->進(jìn)而熔斷->恢復(fù)調(diào)用鏈路
實(shí)現(xiàn):
? service
//=====服務(wù)熔斷 @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否開啟斷路器@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 請(qǐng)求次數(shù)@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 時(shí)間窗口期@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失敗率達(dá)到多少后跳閘 }) public String paymentCircuitBreaker(@PathVariable("id") Integer id) {if(id < 0){throw new RuntimeException("******id 不能負(fù)數(shù)");}String serialNumber = IdUtil.simpleUUID();return Thread.currentThread().getName()+"\t"+"調(diào)用成功,流水號(hào): " + serialNumber; } public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {return "id 不能負(fù)數(shù),請(qǐng)稍后再試,/(ㄒoㄒ)/~~ id: " +id; }測(cè)試
通過(guò)改變參數(shù)訪問(wèn),當(dāng)使用負(fù)數(shù)訪問(wèn)是會(huì)觸發(fā)服務(wù)降級(jí),多次降級(jí)后服務(wù)會(huì)自動(dòng)打開熔斷(表現(xiàn)為即使使用正數(shù)訪問(wèn)仍然是降級(jí)處理),之后逐漸恢復(fù)正常處理。
3、服務(wù)監(jiān)控
實(shí)現(xiàn):
pom
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency>yml
9001端口
主啟動(dòng)類
@EnableHystrixDashboard
要求,所有提供服務(wù)端都添加actuator
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>此版本需要配置路徑,才能用一下圖片路徑訪問(wèn)
@Beanpublic ServletRegistrationBean getServlet() {HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);registrationBean.setLoadOnStartup(1);registrationBean.addUrlMappings("/hystrix.stream");registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean;}注意:每個(gè)顏色的數(shù)字對(duì)應(yīng)右上方每個(gè)屬性,例如,綠色代表成功次數(shù)。
服務(wù)網(wǎng)關(guān)
-
網(wǎng)關(guān)職責(zé):
<img src="https://gitee.com/jklixin/images/raw/master/cloud/aHR0cDovL2Nvcy5yYWluMTAyNC5jb20vbWFya2Rvd24vaW1hZ2UtMjAxOTEwMDgxNjAzMjUwMjEucG5n.jpg" alt="img" style="zoom: 50%;" />
-
網(wǎng)關(guān)分類與功能:
1、Gateway
為微服務(wù)架構(gòu)提供一種簡(jiǎn)單而有效的統(tǒng)一的API路由管理方式
-
實(shí)現(xiàn)
-
pom
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency> -
yml
server:port: 9527 spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #開啟從注冊(cè)中心動(dòng)態(tài)創(chuàng)建路由的功能,利用微服務(wù)名進(jìn)行路由routes:- id: payment_routh #路由的ID,沒(méi)有固定規(guī)則但要求唯一,建議配合服務(wù)名# uri: http://localhost:8001 #匹配后提供服務(wù)的路由地址uri: lb://cloud-payment-service #匹配后提供服務(wù)的路由地址predicates:- Path=/payment/** # 斷言,路徑相匹配的進(jìn)行路由 eureka:instance:hostname: cloud-gateway-serviceclient: #服務(wù)提供者provider注冊(cè)進(jìn)eureka服務(wù)列表內(nèi)service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka -
主啟動(dòng)
@SpringBootApplication @EnableEurekaClient public class GatewayMain9527 {public static void main(String[] args) {SpringApplication.run(GatewayMain9527.class,args);} } -
測(cè)試:
通過(guò)端口9527訪問(wèn)服務(wù)名為cloud-payment-service的服務(wù),路徑匹配時(shí)訪問(wèn)成功
路由轉(zhuǎn)發(fā)
時(shí)間匹配
Predicate 支持設(shè)置一個(gè)時(shí)間,在請(qǐng)求進(jìn)行轉(zhuǎn)發(fā)的時(shí)候,可以通過(guò)判斷在這個(gè)時(shí)間之前或者之后進(jìn)行轉(zhuǎn)發(fā)。
predicates:- After=2020-01-20T06:06:06+08:00[Asia/Shanghai]2020/01/20之后訪問(wèn)才會(huì)進(jìn)行轉(zhuǎn)發(fā)到對(duì)應(yīng)的服務(wù), Before 同理
Cookie匹配
Cookie Route Predicate 可以接收兩個(gè)參數(shù),一個(gè)是 Cookie name , 一個(gè)是正則表達(dá)式,
predicates:- Cookie=ityouknow, kee.e測(cè)試:curl http://localhost:9527 --cookie “ityouknow=kee.e”,匹配成功
請(qǐng)求頭匹配
Header Route Predicate 和 Cookie Route Predicate 一樣,也是接收 2 個(gè)參數(shù),一個(gè) header 中屬性名稱和一個(gè)正則表達(dá)式,這個(gè)屬性值和正則表達(dá)式匹配則執(zhí)行。
predicates:- Header=X-Request-Id, \d+測(cè)試1 curl http://localhost:9527 -H “X-Request-Id:1234” 匹配成功
測(cè)試2 curl http://localhost:9527 -H “X-Request-Id:sfsg” 匹配失敗
Host匹配
Host Route Predicate 接收一組參數(shù),一組匹配的域名列表,這個(gè)模板是一個(gè) ant 分隔的模板,用.號(hào)作為分隔符。它通過(guò)參數(shù)中的主機(jī)地址作為匹配規(guī)則。
predicates:- Host=**.ityouknow.com測(cè)試 curl http://localhost:9527 -H “Host: www.ityouknow.com” 匹配成功
請(qǐng)求方式匹配
predicates:- Method=GETcurl 默認(rèn)是以 GET 的方式去請(qǐng)求
測(cè)試 curl -X POST http://localhost:9527 匹配失敗
請(qǐng)求參數(shù)匹配
- Query Route Predicate 支持傳入兩個(gè)參數(shù),一個(gè)是屬性名一個(gè)為屬性值,屬性值可以是正則表達(dá)式。
只要求情中包含該屬性即可匹配
測(cè)試 curl localhost:9527?smile=x&id=2 匹配成功。
- 將 Query 的值以鍵值對(duì)的方式進(jìn)行配置,這樣在請(qǐng)求過(guò)來(lái)時(shí)會(huì)對(duì)屬性值和正則進(jìn)行匹配
當(dāng)請(qǐng)求中包含 keep 屬性并且參數(shù)值是以 pu 開頭的長(zhǎng)度為三位的字符串才會(huì)進(jìn)行匹配和路由。
測(cè)試1 curl localhost:9527?keep=pub 匹配成功
測(cè)試2 curl localhost:9527?keep=pubx 匹配失敗
請(qǐng)求ip匹配
Predicate 也支持通過(guò)設(shè)置某個(gè) ip 區(qū)間號(hào)段的請(qǐng)求才會(huì)路由,RemoteAddr Route Predicate 接受 cidr 符號(hào) (IPv4 或 IPv6) 字符串的列表(最小大小為 1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子網(wǎng)掩碼)。
predicates:- RemoteAddr=192.168.1.1/24請(qǐng)求的遠(yuǎn)程地址是 192.168.1.10,則此路由將匹配
組合匹配
- 需要滿足所有斷言條件才會(huì)被轉(zhuǎn)發(fā)
- 當(dāng)滿足多個(gè)路由時(shí)。先匹配先轉(zhuǎn)發(fā)原則
Filter
下例中表示當(dāng)含有uname屬性是允許訪問(wèn)。
@Component public class FilterConfig implements GlobalFilter,Ordered{@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("進(jìn)入過(guò)濾器");String uname=exchange.getRequest().getQueryParams().getFirst("uname");if(uname==null){//請(qǐng)求路徑中沒(méi)有該屬性值System.out.println("拒絕訪問(wèn)");exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}//存在,放行return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;} }測(cè)試: http://localhost:9527/payment/lb?uname=z3 訪問(wèn)成功
服務(wù)配置中心
為分布式系統(tǒng)中的外部配置提供服務(wù)器和客戶端支持。方便部署與運(yùn)維。有客戶端、服務(wù)端。
服務(wù)端也稱分布式配置中心,是一個(gè)獨(dú)立的微服務(wù)應(yīng)用,用來(lái)連接配置服務(wù)器并為客戶端提供獲取配置信息,加密/解密信息等訪問(wèn)接口。
客戶端則是通過(guò)指定配置中心來(lái)管理應(yīng)用資源,以及與業(yè)務(wù)相關(guān)的配置內(nèi)容,并在啟動(dòng)的時(shí)候從配置中心獲取和加載配置信息。默認(rèn)采用 git,并且可以通過(guò) git 客戶端工具來(lái)方便管理和訪問(wèn)配置內(nèi)容。
優(yōu)點(diǎn):
- 集中管理配置文件
- 不同環(huán)境不同配置,動(dòng)態(tài)化的配置更新
- 運(yùn)行期間,不需要去服務(wù)器修改配置文件,服務(wù)會(huì)想配置中心拉取自己的信息
- 配置信息改變時(shí),不需要重啟即可更新配置信息到服務(wù)
- 配置信息以 rest 接口暴露
實(shí)現(xiàn):
服務(wù)端
pom
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId></dependency>yml
spring:application:name: cloud-config-server #注冊(cè)進(jìn)Eureka服務(wù)器的微服務(wù)名cloud:config:server:git:# uri: git@github.com:zzyybs/springcloud-config.git #GitHub上面的git倉(cāng)庫(kù)名字uri: https://gitee.com/jklixin/springcloud-config.git #Gitee上面的git倉(cāng)庫(kù)名字####搜索目錄search-paths:- springcloud-config####讀取分支label: master啟動(dòng)類
@EnableConfigServer
@SpringBootApplication @EnableConfigServer public class ConfigMain3344 {public static void main(String[] args) {SpringApplication.run(ConfigMain3344.class,args);} }客戶端
pom
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency>bootstrap.yml
spring:application:name: cloud-config-clientcloud:config:lable: master name: config #需要從github上讀取的資源名稱,注意沒(méi)有yml后綴名profile: dev #本次訪問(wèn)的配置項(xiàng)uri: http://localhost:3344 #配置服務(wù)端,本微服務(wù)啟動(dòng)后先去找3344號(hào)服務(wù),通過(guò)SpringCloudConfig獲取GitHub的服務(wù)地址controller
@RestController //@RefreshScope public class ConfigController {@Value("${config.info}")String info;@GetMapping("/configInfo")public String getConfigInfo(){return info;} }訪問(wèn)方式:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
問(wèn)題: 更改gitee上的內(nèi)容,服務(wù)端更新成功,但是客戶端并未更新成功
動(dòng)態(tài)刷新
解決:
客戶端引入actuator依賴
暴露監(jiān)控端點(diǎn)
# 暴露監(jiān)控端點(diǎn) management:endpoints:web:exposure:include: "*"@refreshScope業(yè)務(wù)類Controller修改
需要運(yùn)維發(fā)送Post請(qǐng)求刷新3355
curl -X POST "http://localhost:3355/actuator/refresh"問(wèn)題: 多個(gè)客戶端如何實(shí)現(xiàn)動(dòng)態(tài)刷新
消息總線
Bus
Bus支持兩種消息代理:RabbitMQ和Kafka
廣播
實(shí)現(xiàn)
-
服務(wù)端
-
添加bus-amqp依賴
<!--添加消息總線RabbitMQ支持--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency> -
配置rabbitmq相關(guān)屬性
#rabbitmq相關(guān)配置rabbitmq:host: 123.56.16.54port: 5672username: guestpassword: guest -
暴露刷新端口
# 暴露bus刷新的端點(diǎn) management:endpoints:web:exposure:include: 'bus-refresh' -
客戶端
- 添加bus-amqp依賴
- 配置rabbitmq相關(guān)屬性
測(cè)試:
更改配置文件
刷新
http://localhost:3344/config-dev.yml 一致
http://localhost:3355/configInfo 不一致
發(fā)送請(qǐng)求刷新 curl -X POST “http://localhost:3344/actuator/bus-refresh”
刷新
http://localhost:3355/configInfo 一致
http://localhost:3366/configInfo 一致
定點(diǎn)通知
實(shí)現(xiàn): 公式:http://localhost:3344/actutor/bus-refresh/{destination}
測(cè)試: curl -X POST “http://localhost:3344/actuator/bus-refresh/config-client:3355”
? http://localhost:3355/configInfo 一致
? http://localhost:3366/configInfo 不一致
消息驅(qū)動(dòng)
Stream
屏蔽底層消息中間件的差異,降低切換成本,統(tǒng)一消息的編程模型
總結(jié)
以上是生活随笔為你收集整理的SpringCloud学习一的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 算法.动态规划 导航/数塔取数字问题
- 下一篇: javascript顺序点击文字验证