本文章僅作為個(gè)人筆記
-
eureka的集成(注冊(cè)中心)
-
新建springboot項(xiàng)目并在build.gradle文件添加相關(guān)依賴
ext { set('springCloudVersion', "Hoxton.SR4") } dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
-
在新建的eureka服務(wù)項(xiàng)目中配置相關(guān)文件(application.yml對(duì)應(yīng)配置可自行更改,下面給的是單機(jī)配置)
eureka: instance: hostname: localhost # 是否向注冊(cè)中心注冊(cè)服務(wù)(如果單eureka服務(wù)則false/避免自己對(duì)自己注冊(cè)服務(wù)) client: register-with-eureka: false # 是否去檢索其它服務(wù), fetch-registry: false # 指定服務(wù)注冊(cè)中心的位置 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
-
在新建的eureka服務(wù)項(xiàng)目Application主類添加注解 @EnableEurekaServer
@EnableEurekaServer public class EurekaServerApplication {
此時(shí)再啟動(dòng)新建的eureka服務(wù)項(xiàng)目便完成了單eureka服務(wù)注冊(cè)中心的搭建
-
eureka集群的配置
-
配置文件(在項(xiàng)目中復(fù)制配置文件类垦,并加后綴<application-eureka8761.yml>)
-
配置文件1
server: port: 8761 eureka: instance: hostname: eureka8761 # 是否向注冊(cè)中心注冊(cè)服務(wù)(如果單eureka服務(wù)則false/避免自己對(duì)自己注冊(cè)服務(wù)) client: register-with-eureka: false # 是否去檢索其它服務(wù), fetch-registry: false # 指定服務(wù)注冊(cè)中心的位置 service-url: defaultZone: http://eureka8762:eureka8762/eureka/
-
配置文件2
server: port: 8762 eureka: instance: hostname: eureka8762 # 是否向注冊(cè)中心注冊(cè)服務(wù)(如果單eureka服務(wù)則false/避免自己對(duì)自己注冊(cè)服務(wù)) client: register-with-eureka: false # 是否去檢索其它服務(wù)徘公, fetch-registry: false # 指定服務(wù)注冊(cè)中心的位置 service-url: defaultZone: http://eureka8761:eureka8761/eureka/
-
-
因?yàn)閔ostname改變了留特,但是本地并不能識(shí)別堂鲤,因此需要更改本地host文件咙咽,添加本地配置
127.0.0.1 eureka8761 127.0.0.1 eureka8762
-
-
運(yùn)行時(shí)命令
java -jar xxx.jar --spring.profiles.active=<服務(wù)名(eureka8761)>
-
eureka常用配置
// 服務(wù)心跳s eureka.instance.lease-renewal-interval-in-seconds=2 // 服務(wù)判定故障時(shí)間s eureka.instance.lease-expiration-duration-in-seconds=10
-
普通服務(wù)提供者/消費(fèi)者接入eureka注冊(cè)中心
提供者注冊(cè)服務(wù)
-
為服務(wù)提供者項(xiàng)目的build.gradle項(xiàng)目添加eureka相關(guān)依賴
ext { set('springCloudVersion', "Hoxton.SR4") } dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
-
為服務(wù)提供者項(xiàng)目的application.yml添加eureka相關(guān)配置(多配置時(shí)service-url以,分隔)
# 服務(wù)名稱 spring: application: name: cloud-provider # eureka注冊(cè)中心連接方式 eureka: client: service-url: defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka
-
在服務(wù)提供者項(xiàng)目的Application主類添加注解 @EnableEurekaClient/@EnableDiscoveryClient 以使配置文件生效并注冊(cè)服務(wù)/表明以可以使用eureka服務(wù)
@EnableDiscoveryClient public class CloudProviderApplication {
此時(shí)再啟動(dòng)服務(wù)提供者項(xiàng)目老玛,服務(wù)便注冊(cè)至eureka注冊(cè)中心了
-
服務(wù)者的調(diào)用
-
為消費(fèi)者項(xiàng)目的build.gradle項(xiàng)目添加eureka相關(guān)依賴
ext { set('springCloudVersion', "Hoxton.SR4") } dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
-
為服務(wù)消費(fèi)者項(xiàng)目的application.yml添加eureka相關(guān)配置(多配置時(shí)service-url以,分隔)
# 服務(wù)名稱 spring: application: name: cloud-consumer # eureka注冊(cè)中心連接方式 eureka: client: service-url: defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka
-
再在消費(fèi)者RestTemplate bean注入的地方加入 @LoadBalanced 注解加入負(fù)載均衡功能
@Bean @LoadBalanced public RestTemplate restTemplate() {
-
此時(shí)只需要將服務(wù)消費(fèi)者的restTemplate.getForEntity方法里的host改為服務(wù)提供者名稱即可(例:<restTemplate.getForEntity("http://cloud-provider/provider/hello"...>)
@RestController public class ConsumerController { @Autowired RestTemplate restTemplate; @RequestMapping("/consumer/hello") public String hello() { // eureka注冊(cè)服務(wù)調(diào)用方式 直接返回?cái)?shù)據(jù) return restTemplate.getForObject("http://cloud-provider/provider/hello" , String.class); } }
-
ribbon負(fù)載均衡的使用
啟動(dòng)多個(gè)服務(wù)提供者并注冊(cè)至注冊(cè)中心(eureka)
-
在消費(fèi)者RestTemplate bean注入的地方加入 @LoadBalanced 注解
@Bean @LoadBalanced public RestTemplate restTemplate() {
-
ribbon負(fù)載均衡策略與配置
- 策略
- RoundRobinRule 輪詢策略(默認(rèn))
- RandomRule 隨機(jī)策略
- RetryRule 重試策略,失敗重試,錯(cuò)誤過(guò)多訪問(wèn)其它服務(wù)
- AvailabilityFilteringRule 過(guò)濾故障/并發(fā)連接超閾值服務(wù)钧敞,對(duì)剩下的服務(wù)輪詢
- BestAvailableRule 過(guò)濾訪問(wèn)過(guò)多故障的服務(wù)蜡豹,返回并發(fā)量最小的服務(wù)
- ZoneAvoidanceRule 綜合判斷性能/可用性,返回更優(yōu)的服務(wù)
- 策略
-
配置
-
配置bean注入
@Bean public IRule iRule() { return new RandomRule();//根據(jù)自己的需求返回不同的rule實(shí)例 }
-
-
-
Hystrix 集成(熔斷器)
-
為項(xiàng)目的build.gradle項(xiàng)目添加hystrix相關(guān)配置
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix' }
-
在項(xiàng)目的Application主類添加注解 @EnableCircuitBreaker
@EnableCircuitBreaker public class CloudProviderApplication {
-
在項(xiàng)目的controller類中添加注解 @HystrixCommand 及方法錯(cuò)誤時(shí)調(diào)用方法
@HystrixCommand(fallbackMethod = "error") public String hystrix() { //業(yè)務(wù)處理 } public String error() { //錯(cuò)誤處理 return "error"; }
同時(shí) @SpringBootApplication/@EnableEurekaClient/@EnableCircuitBreaker 三個(gè)注解可用 @SpringCloudApplication 代替
@EnableDiscoveryClient 與 @EnableEurekaClient 相似
hystrix默認(rèn)超時(shí)時(shí)間為1000ms
-
hystrix 常用配置
// 設(shè)置超時(shí)時(shí)間 @HystrixCommand(fallbackMethod = "error", commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500") })
hystrix的服務(wù)降級(jí)(當(dāng)某個(gè)服務(wù)產(chǎn)生了熔斷溉苛,此服務(wù)將不再被調(diào)用)
-
hystrix的異常處理(當(dāng)調(diào)用者自己拋出了異常余素,此時(shí)也會(huì)觸發(fā)服務(wù)的降級(jí),當(dāng)我們自己發(fā)生異常時(shí)炊昆,只需要在服務(wù)降級(jí)方法中添加一個(gè)Throwable類型的參數(shù)就能夠獲取到拋出的異常類型)
public String error(Throwable throwable) { return "error:" + (throwable == null ? "null" : throwable.getMessage()); }
-
如果需要拋某些異常給用戶,則直接在 @HystrixCommand 注解中添加 ignoreExceptions = {<忽略的異常類>}
@HystrixCommand(fallbackMethod = "error", commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500") }, ignoreExceptions = { Exception.class })
-
hystrix自定義請(qǐng)求服務(wù)熔斷
自定義類并繼承 com.netflix.hystrix.HystrixCommand 類
覆寫(xiě) run 方法執(zhí)行業(yè)務(wù)邏輯并返回業(yè)務(wù)數(shù)據(jù)
覆寫(xiě) getFallback 方法處理熔斷邏輯
重載構(gòu)造方法傳入必要參數(shù)Setter及RestTemplate
-
下面給出示例:
public class MyHystrixCommand extends HystrixCommand<String> { private RestTemplate restTemplate; public MyHystrixCommand(Setter setter, RestTemplate restTemplate) { super(setter); this.restTemplate = restTemplate; } @Override protected String run() throws Exception { // int b = 10 / 0;//異常模擬 return restTemplate.getForObject("http://cloud-provider/provider/hello" , String.class); } @Override protected String getFallback() { Throwable throwable = getExecutionException(); return "error2:" + (throwable == null ? "null" : throwable.getMessage()); } }
-
調(diào)用時(shí)則不再需要寫(xiě)注解威根,而是直接 new 自定義類凤巨,然后調(diào)用 execute 方法返回結(jié)果。
@RequestMapping("/consumer/hystrix2") public String hystrix2() { //使用默認(rèn)的setter MyHystrixCommand myHystrixCommand = new MyHystrixCommand( com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")) , restTemplate); return myHystrixCommand.execute(); }
-
異步調(diào)用方法
MyHystrixCommand myHystrixCommand = new MyHystrixCommand( com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")) , restTemplate); Future<String> future = myHystrixCommand.queue(); //可以在這里做一些其它邏輯 //阻塞方法 String result = future.get(); return result;
-
-
hystrix dashboard (hystrix儀表盤(pán)監(jiān)控)接入
-
新建項(xiàng)目并為項(xiàng)目的build.gradle項(xiàng)目添加hystrix-dashboard相關(guān)配置
ext { set('springCloudVersion', "Hoxton.SR4") } dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix-dashboard' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
-
在項(xiàng)目的Application主類添加注解 @EnableHystrixDashboard
@EnableHystrixDashboard public class HystrixDashboardApplication {
啟動(dòng)項(xiàng)目并訪問(wèn) http://<host>:<port>/hystrix (http://localhost:3721/hystrix) 查看服務(wù)是否部署成功
-
為需要監(jiān)控的項(xiàng)目的build.gradle文件添加依賴
dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' }
-
為需要監(jiān)控的項(xiàng)目配置springboot監(jiān)控端口的權(quán)限(用來(lái)暴露endpoints洛搀,由于endpoints包含很多敏感信息敢茁,默認(rèn)只可訪問(wèn) health 和 info 兩個(gè)權(quán)限)
management: endpoints: web: exposure: include: hystrix.stream
訪問(wèn) http://<host>:<port>/actuator/hystrix.stream 查看是否部署成功 (例: http://localhost:8081/actuator/hystrix.stream ,記得先訪問(wèn)一個(gè)其它接口留美,否之返回的是ping...)
為消費(fèi)者添加完監(jiān)控依賴再訪問(wèn) http://<host>:<port>/hystrix 彰檬,在title輸入要監(jiān)控的項(xiàng)目名稱,點(diǎn)擊 Monitor Stream 即可查看項(xiàng)目hystrix運(yùn)行情況谎砾。
-
-
聲明式服務(wù)消費(fèi) openFeign (hystrix + ribbon 的整合項(xiàng)目) 集成
-
為消費(fèi)者項(xiàng)目的build.gradle文件添加依賴
dependencies { //本身須包含 spring-cloud-starter-netflix-eureka-client implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' }
-
在項(xiàng)目的Application主類添加注解 @EnableFeignClients
@EnableFeignClients public class FeignConsumerApplication {
-
在項(xiàng)目需要訪問(wèn)注冊(cè)中心的service添加注解 @FeignClient("<服務(wù)名稱,不區(qū)分大小寫(xiě)>")并為方法添加 @RequestMapping("<訪問(wèn)服務(wù)路徑>")注解
/訪問(wèn)的服務(wù)名稱 @FeignClient("cloud-provider") public interface ProviderService { //訪問(wèn)的服務(wù)路徑 @RequestMapping("/provider/hello") public String hello(); }
-
為服務(wù)消費(fèi)者項(xiàng)目的application.yml添加相關(guān)配置(多配置時(shí)service-url以,分隔)
# 服務(wù)名稱 spring: application: name: feign-consumer # eureka注冊(cè)中心連接方式 eureka: client: service-url: defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka
-
openFeign 開(kāi)啟熔斷機(jī)制
-
在 application.yml 配置文件添加配置
feign: hystrix: enabled: true
-
在Service的 @FeignClient 注解中添加 fallback 賦值
@FeignClient(name = "cloud-provider", fallback = ProviderFallBack.class) public interface ProviderService {
-
自定義的 ProviderFallBack 須實(shí)現(xiàn)對(duì)應(yīng)的Service接口逢倍,當(dāng)熔斷時(shí)調(diào)用實(shí)現(xiàn)的方法
@Component public class ProviderFallBack implements ProviderService { @Override public String hello() { System.out.println("服務(wù)不可用時(shí)調(diào)用"); return "fall back."; } }
-
-
openFeign獲取服務(wù)熔斷異常信息
-
在 @FeignClient 注解中賦值屬性 fallbackFactory
@FeignClient(name = "cloud-provider", fallbackFactory = ProviderFallBackFactory.class)
-
編寫(xiě) ProviderFallBackFactory 類,實(shí)現(xiàn) FallbackFactory 接口并重寫(xiě)相應(yīng)方法景图,其中create方法里邊的cause即報(bào)錯(cuò)信息较雕。
@Component public class ProviderFallBackFactory implements FallbackFactory<ProviderService> { @Override public ProviderService create(Throwable cause) { return new ProviderService() { @Override public String hello() { System.out.println("服務(wù)不可用時(shí)調(diào)用 factory."); return cause.getMessage(); } }; } }
-
-
-
zuul 集成(api網(wǎng)關(guān))
-
新建項(xiàng)目并為項(xiàng)目的build.gradle文件添加依賴
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-zuul' }
-
在項(xiàng)目的Application主類添加注解 @EnableZuulProxy 開(kāi)啟zuul功能
@EnableZuulProxy public class ZuulServerApplication {
-
為項(xiàng)目的application.yml添加相關(guān)配置(多配置時(shí)service-url以,分隔)
# 服務(wù)名稱 spring: application: name: zuul-server # eureka注冊(cè)中心連接方式 eureka: client: service-url: defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka # 經(jīng)典路由配置(與簡(jiǎn)化配置2選1) zuul: routes: <自定義名字>: path: /api-mys/** serviceId: cloud-provider # 簡(jiǎn)化路由配置(與經(jīng)典配置2選1) zuul: routes: cloud-provider: /api-mys/**
其中自定義名字必須對(duì)應(yīng)path和serviceId,意為serviceId指向path,其中serviceId為訪問(wèn)的服務(wù)名,path為項(xiàng)目中訪問(wèn)路徑亮蒋,當(dāng)前規(guī)則為匹配所有 /api-mys/** 的請(qǐng)求扣典,只要請(qǐng)求路徑包含 /api-mys/ 則會(huì)被轉(zhuǎn)發(fā)到cloud-provider上
-
如果什么配置都不寫(xiě),默認(rèn)也會(huì)幫我們做代理慎玖,默認(rèn)為
zuul: routes: <服務(wù)名>: /<服務(wù)名>/**
訪問(wèn)host://<host>:<port>/<配置服務(wù)名>/<配置路徑> 測(cè)試(例: http://localhost:8085/api-mys/provider/hello )
-
為zuul添加過(guò)濾器
創(chuàng)建 Filter 類并繼承ZuulFilter類重寫(xiě)相應(yīng)方法
-
filterType 方法表示當(dāng)前filter在哪個(gè)生命周期運(yùn)行 pre->routing->post error任意階段錯(cuò)誤執(zhí)行
- pre 表示在路由之前執(zhí)行
- post 表示請(qǐng)求完成后執(zhí)行
- error 表示錯(cuò)誤時(shí)執(zhí)行
- route 表示環(huán)繞請(qǐng)求前后執(zhí)行
- static 表示
- 最后還可以自定義
filterOrder 方法表示執(zhí)行順序贮尖,當(dāng)filter很多時(shí),根據(jù)這個(gè)值的大小進(jìn)行排序趁怔,
shouldFilter 方法判斷當(dāng)前過(guò)濾器是否需要執(zhí)行
run 方法則是具體過(guò)濾邏輯
-
示例代碼:
@Component public class AuthFilter extends ZuulFilter { @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 10; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); String token = request.getParameter("token"); if (token == null) { //是否轉(zhuǎn)發(fā) requestContext.setSendZuulResponse(false); requestContext.setResponseStatusCode(401); requestContext.addZuulResponseHeader("content-type", "text/html;charset=utf-8"); requestContext.setResponseBody("非法訪問(wèn)"); } //目前返回值無(wú)意義湿硝,可以返回null return null; } }
-
忽略路由規(guī)則
- 在 application.yml 文件添加配置
-
忽略所有服務(wù)
zuul: ignored-services: cloud-provider
-
忽略 某個(gè)/某些 路徑
zuul: ignored-patterns: /provider/hello
-
為路由添加前綴
zuul: prefix: /api-mys
-
- 在 application.yml 文件添加配置
zuul錯(cuò)誤處理
-
禁用默認(rèn)錯(cuò)誤處理器
zuul: SendErrorFilter: error: disable: true
-
創(chuàng)建 Filter 類并繼承ZuulFilter類重寫(xiě)相應(yīng)方法衰齐,與之前差異僅filterType返回"error"及run中的處理差異柏副,下面給出示例:
@Component public class ErrorFilter extends ZuulFilter { @Override public String filterType() { return "error"; } @Override public int filterOrder() { return 10; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { try { RequestContext requestContext = RequestContext.getCurrentContext(); ZuulException exception = (ZuulException) requestContext.getThrowable(); System.out.println("系統(tǒng)異常攔截:" + exception); HttpServletResponse response = requestContext.getResponse(); response.setContentType("application/json; charset=utf8"); response.setStatus(exception.nStatusCode); PrintWriter writer = null; try { writer = response.getWriter(); writer.println("{\"code\":" + exception.nStatusCode + ",\"message\":\"" + exception.getMessage() + "\"}"); } catch (IOException e) { e.printStackTrace(); } finally { if (writer != null) { writer.close(); } } } catch (Exception e) { ReflectionUtils.rethrowRuntimeException(e); } //目前返回值無(wú)意義,可以返回null return null; } }
-
自定義全局錯(cuò)誤頁(yè)面(與自定義錯(cuò)誤處理不兼容)
-
自定義controller并實(shí)現(xiàn) ErrorController 接口报破,實(shí)現(xiàn)相應(yīng)方法任连,下面給出示例:
@RestController public class AllErrorController implements ErrorController { @Override public String getErrorPath() { //訪問(wèn)哪個(gè)路徑 return "/error"; } @RequestMapping("/error") public Object error() { RequestContext context = RequestContext.getCurrentContext(); ZuulException exception = (ZuulException) context.getThrowable(); //具體處理看個(gè)人需求 return exception.nStatusCode + "--" + exception.getMessage(); } }
-
-
-
Spring Cloud Config (分布式配置管理系統(tǒng))
- Spring Cloud 默認(rèn)情況使用git存放配置文件蚤吹,也可使用svn/gitlab等
- SpringCloud Config 服務(wù)搭建
- Spring Cloud Config 服務(wù)端搭建(服務(wù)端作為中心)
-
新建項(xiàng)目并為項(xiàng)目 build.gradle 添加相應(yīng)依賴
ext { set('springCloudVersion', "Hoxton.SR4") } dependencies { implementation 'org.springframework.cloud:spring-cloud-config-server' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
-
在項(xiàng)目的Application主類添加注解 @EnableConfigServer 開(kāi)啟功能
@EnableConfigServer public class ConfigServerApplication {
-
在項(xiàng)目的 application.yml 中配置git倉(cāng)庫(kù)信息 (這里使用的自己搭建的本地gitlab)
spring: cloud: config: server: git: uri: http://git.woaizhuangbi.com/makai/springconfigdemo.git search-paths: config-center username: springconfigdemo password: admin1234
此時(shí)再啟動(dòng)項(xiàng)目便配置好了配置服務(wù)中心
-
為了測(cè)試可以在項(xiàng)目下創(chuàng)建文件以測(cè)試
在根目錄創(chuàng)建config-center文件夾
在config-center文件夾下創(chuàng)建application.properties/application-dev.properties/application-test.properties/application-online.yml 文件
-
在不同文件設(shè)置不同配置(支持.yml文件與.properties文件)
application.properties url=http://www.woaizhuangbi.com application-test.properties url=http://test.woaizhuangbi.com application-online.yml url: http://online.woaizhuangbi.com application-dev.properties url=http://dev.woaizhuangbi.com
-
配置文件大致取名規(guī)則
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
訪問(wèn)指定路徑獲取指定配置 http://<host>:<port>/<配置文件前綴>/<配置文件中綴>/<分支> 例: http://localhost:3721/application/online/master
-
- Spring Cloud Config 客戶端搭建(可以理解為所有需要獲取動(dòng)態(tài)配置的項(xiàng)目,可以是所有服務(wù))
-
為項(xiàng)目 build.gradle 添加相應(yīng)依賴
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-config' }
-
創(chuàng)建 bootstrap.yml 文件并配置 name對(duì)應(yīng)配置文件前綴随抠,profile對(duì)應(yīng)中綴裁着,label對(duì)應(yīng)分支,uri即根訪問(wèn)路徑
spring: application: name: config-client cloud: config: profile: dev label: master uri: http://localhost:3721/
-
創(chuàng)建controller進(jìn)行測(cè)試,可以直接使用 @Value("${配置名}") 的方式或者 @Environment 的方式進(jìn)行數(shù)據(jù)獲取拱她,例:
@RestController public class ConfigController { @Value("${url}") private String url; @Autowired private Environment environment; @RequestMapping("/cloud/url") public String url() { return environment.getProperty("url"); // return url; } }
這樣就簡(jiǎn)單的完成配置的使用
-
-
SpringCloud Config 動(dòng)態(tài)更新
-
客戶端處理
-
為config客戶端項(xiàng)目的 build.gradle 添加相應(yīng)依賴
dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' }
-
在服務(wù)端項(xiàng)目的 bootstrap.yml 文件中添加暴露監(jiān)控端點(diǎn)配置及服務(wù)注冊(cè)配置
management: endpoint: web: exposure: include: "*"
-
在controller上面添加 @RefreshScope 注解
@RefreshScope public class ConfigController {
-
最后發(fā)送一個(gè)post請(qǐng)求給每個(gè)客戶端二驰,以動(dòng)態(tài)刷新 curl -X POST "http://<host>:<port>/actuator/refresh" 例如:
curl -X POST "http://localhost:3721/actuator/refresh"
此時(shí)再請(qǐng)求發(fā)送過(guò)post請(qǐng)求的客戶端就能獲取最新的配置了
-
-
SpringCloud Config 安全保護(hù)
-
服務(wù)端處理
-
為config服務(wù)端項(xiàng)目的 build.gradle 添加相應(yīng)依賴
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-security' }
-
在服務(wù)端項(xiàng)目的 application.yml 文件中配置用戶名密碼
spring: security: user: name: springconfigadmin password: admin1234
此時(shí)再直接訪問(wèn)服務(wù)端的url便需要登錄了
-
-
客戶端處理
-
在客戶端項(xiàng)目的 bootstrap.yml 文件中配置用戶名密碼
spring: cloud: config: username: springconfigadmin password: admin1234
-
-
-
-
rabbitMQ 安裝(docker安裝)
-
拉取鏡像
docker pull rabbitmq docker pull rabbitmq:management
-
運(yùn)行鏡像(這里僅單機(jī),端口自定義指定,詳細(xì)集群等這里不深究)
docker run -p 4369:4369 -p 5672:5672 -p 15672:15672 -p 25672:25672 --name rabbitmq -d rabbitmq:management
-
默認(rèn)端口
- 4369 -- erlang發(fā)現(xiàn)口
- 5672 --client端通信口
- 15672 -- 管理界面ui端口
- 25672 -- server間內(nèi)部通信口
默認(rèn)訪問(wèn)地址 http://localhost:15672
-
默認(rèn)用戶名密碼:
guest guest
-
-
SpringCloud Bus 集成(消息總線/配合rabbitMQ或者kafka使用/這里使用rabbitMQ)
-
服務(wù)端處理
-
為config服務(wù)端項(xiàng)目的 build.gradle 添加相應(yīng)依賴
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' }
-
在服務(wù)端項(xiàng)目的 application.yml 文件中配置rabbitmq相關(guān)配置及暴露bus刷新配置的端點(diǎn)配置
spring: rabbitmq: host: 192.168.3.6 port: 5672 username: guest password: guest management: endpoints: web: exposure: include: 'bus-refresh'
-
-
客戶端處理
-
為config客戶端項(xiàng)目的 build.gradle 添加相應(yīng)依賴
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' }
-
在客戶端項(xiàng)目的 application.yml 文件中配置rabbitmq相關(guān)配置
spring: rabbitmq: host: 192.168.3.6 port: 5672 username: guest password: guest
-
-
最后發(fā)送一個(gè)post請(qǐng)求給服務(wù)端,以動(dòng)態(tài)刷新 curl -X POST "http://<host>:<port>/actuator/bus-refresh" 例如(這里如果開(kāi)啟了登錄則會(huì)沖突):
curl -X POST "http://localhost:3722/actuator/bus-refresh"
此時(shí)再請(qǐng)求所有的客戶端就都能獲取最新的配置了
動(dòng)態(tài)刷新定點(diǎn)通知(只通知部分客戶端)
-
指定某一個(gè)通知: http://<server_host>:<server_port>/actuator/bus-refresh/{destination} 例:
http://localhost:3721/actuator/bus-refresh/config-client:3722
-
-
zookeeper 的集成(注冊(cè)中心)
-
docker 常用命令
-
docker實(shí)例查看
docker ps -a
-
docker復(fù)制文件
docker cp <local path> <applicationID>:<docker path>
-
docker登錄
docker exec -i -t <applicationID> /bin/sh
-
zookeeper 在 docker 下運(yùn)行
-
拉取鏡像
docker pull zookeeper
-
運(yùn)行鏡像(這里僅單機(jī),端口自定義指定,詳細(xì)集群等這里不深究)
docker run -p 8080:8080 -p 2181:2181 --name zookeeper -d zookeeper
訪問(wèn) http://<host>:<port> 測(cè)試服務(wù)是否能正常訪問(wèn)
-
-
zookeeper 接入
- 注冊(cè)服務(wù)至zookeeper
-
服務(wù)提供者項(xiàng)目的 build.gradle 添加相應(yīng)依賴
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-zookeeper-discovery' }
-
服務(wù)提供者項(xiàng)目的 application.yml 文件中添加相應(yīng)配置
spring: cloud: zookeeper: connect-string: 192.168.3.6:2181
-
在服務(wù)提供者項(xiàng)目的Application主類添加注解 @EnableDiscoveryClient 以使配置文件生效并注冊(cè)服務(wù)
@EnableDiscoveryClient public class CloudProviderApplication {
此時(shí)服務(wù)提供者的服務(wù)便注冊(cè)至zookeeper了
-
- 服務(wù)消費(fèi)者的接入
-
服務(wù)消費(fèi)者項(xiàng)目的 build.gradle 添加相應(yīng)依賴
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-zookeeper-discovery' }
-
服務(wù)消費(fèi)者項(xiàng)目的 application.yml 文件中添加相應(yīng)配置
spring: cloud: zookeeper: connect-string: 192.168.3.6:2181
(后面的流程與eureka無(wú)異)
-
再在消費(fèi)者RestTemplate bean注入的地方加入 @LoadBalanced 注解加入負(fù)載均衡功能
@Bean @LoadBalanced public RestTemplate restTemplate() {
-
此時(shí)只需要將服務(wù)消費(fèi)者的restTemplate.getForEntity方法里的host改為服務(wù)提供者名稱即可(例:<restTemplate.getForEntity("http://cloud-provider/provider/hello"...>)
@RestController public class ConsumerController { @Autowired RestTemplate restTemplate; @RequestMapping("/consumer/hello") public String hello() { // eureka注冊(cè)服務(wù)調(diào)用方式 直接返回?cái)?shù)據(jù) return restTemplate.getForObject("http://cloud-provider/provider/hello" , String.class); } }
-
- 注冊(cè)服務(wù)至zookeeper
-
gateway 集成(api網(wǎng)關(guān))
基本概念 Predicate->Filter->Route
-
新建項(xiàng)目并為項(xiàng)目 build.gradle 添加相應(yīng)依賴
ext { set('springCloudVersion', "Hoxton.SR4") } dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-zookeeper-discovery' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
-
在項(xiàng)目的Application主類添加注解 @EnableDiscoveryClient 將服務(wù)注冊(cè)至注冊(cè)中心
@EnableDiscoveryClient public class GatewayServerApplication {
-
在項(xiàng)目的 application.yml 中配置相應(yīng)的路由/服務(wù)/斷言等(路由可多個(gè))
spring: cloud: gateway: discovery: locator: enabled: true # 開(kāi)啟從注冊(cè)中心動(dòng)態(tài)創(chuàng)建路由的功能秉沼,利用服務(wù)名進(jìn)行路由 routes: - id: cloud-provider # 路由的id桶雀,沒(méi)有固定規(guī)則但要求唯一,建議配合服務(wù)名 # uri: http://localhost:8080 # 匹配提供服務(wù)的服務(wù)根地址 uri: lb://cloud-provider # 匹配后提供服務(wù)的路由地址 predicates: - Path=/provider/** # 斷言唬复,路徑相匹配的進(jìn)行路由
- predicates這個(gè)配置除了Path還有其它參數(shù)
- After 之前 - After=2020-05-23T15:15:21.234+08:00[Asia/Shanghai] # 指定時(shí)間之后可訪問(wèn)
- Before 之前 - Before=2020-06-23T15:15:21.234+08:00[Asia/Shanghai] # 指定時(shí)間之前可以訪問(wèn)
- Between 之間 - Between=2020-06-23T15:15:21.234+08:00[Asia/Shanghai],2020-07-23T15:15:21.234+08:00[Asia/Shanghai] # 指定時(shí)間之間可以訪問(wèn)
- Cookie 帶Cookie - Cookie=username,aabb # 帶有Cookie且key為username矗积,value為aabb
- Header 帶Header - Header=X-Request-Id, \d+ # 含X-Request-Id的頭且為數(shù)字
- Method 指定請(qǐng)求方式 - Method=GET # get請(qǐng)求
- Path 路徑匹配 - Path=/provider/** # 請(qǐng)求路徑匹配 /provider 開(kāi)頭
- Query 參數(shù)匹配 - Query=username, \d+ # 帶username參數(shù)且參數(shù)值為數(shù)字
- filter 官方有詳細(xì)介紹
- 局部過(guò)濾器
- 全局過(guò)濾器
- 自定義過(guò)濾器
- GlobalFilter 全局過(guò)濾器
- Ordered 權(quán)重
- predicates這個(gè)配置除了Path還有其它參數(shù)
此時(shí)再啟動(dòng)項(xiàng)目便配置好了相關(guān)網(wǎng)關(guān)服務(wù)了
可以訪問(wèn) http://<host>:<port>/<具體路徑> 例: http://localhost:8087/provider/hello
-
SpringCloud Stream 綁定器(兼容所有MQ(目前僅支持RabbitMQ/Kafka))
-
常用注解
- @Input 注解標(biāo)識(shí)輸入通道,通過(guò)該通道接收到的消息進(jìn)入應(yīng)用程序
- @Output 注解標(biāo)識(shí)輸入通道敞咧,發(fā)布的消息將通過(guò)該通道離開(kāi)應(yīng)用程序
- @StreamListener 監(jiān)聽(tīng)隊(duì)列棘捣,用于消費(fèi)者隊(duì)列的消息接收
- @EnableBinding 指信道channel和exchange綁定在一起
消息提供者者相關(guān)
-
為消息提供者項(xiàng)目的build.gradle文件添加依賴(此處兼容rabbitMQ)
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-stream-rabbit' }
-
為消息提供者項(xiàng)目的 application.yml 文檔添加對(duì)應(yīng)的配置
spring: cloud: stream: binders: defaultRabbit: type: rabbit environment: spring: rabbitmq: host: 192.168.3.6 port: 5672 username: guest password: guest bindings: output: destination: studyExchange content-type: application/json binder: defaultRabbit
-
創(chuàng)建service接口并實(shí)現(xiàn),再在service實(shí)現(xiàn)類添加 @EnableBinding 注解并定義消息的推送管道休建,再注入消息發(fā)送管道 MessageChannel乍恐,使用時(shí)調(diào)用 output.send(MessageBuilder.withPayload(<message>).build()) 例:
@EnableBinding(Source.class) //定義消息的推送管道 public class MessageProviderImpl implements IMessageProvider { @Resource private MessageChannel output;//消息發(fā)送管道 @Override public String send() { String serial = UUID.randomUUID().toString(); output.send(MessageBuilder.withPayload(serial).build()); System.out.println("send:" + serial); return serial; } }
使用時(shí)直接注入IMessageProvider進(jìn)行消息操作即可
-
-
消息消費(fèi)者相關(guān)
-
為消息消費(fèi)者項(xiàng)目的build.gradle文件添加依賴(此處兼容rabbitMQ)
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-stream-rabbit' }
-
為消息消費(fèi)者項(xiàng)目的 application.yml 文檔添加對(duì)應(yīng)的配置
spring: cloud: stream: binders: defaultRabbit: type: rabbit environment: spring: rabbitmq: host: 192.168.3.6 port: 5672 username: guest password: guest bindings: input: destination: studyExchange content-type: application/json binder: defaultRabbit
-
創(chuàng)建Controller并添加 @EnableBinding 注解定義管道類 Sink.class,創(chuàng)建消息方法添加 @StreamListener 注解定義類型测砂,例:
@Component @EnableBinding(Sink.class) public class ReceiveMessageListenerController { @Value("${server.port}") private String serverPort; @StreamListener(Sink.INPUT) public void input(Message<String> message) { System.out.println(serverPort + " receive message = " + message); } }
使用時(shí) 若收到消息即會(huì)調(diào)用 input(Message<String> message) 方法
-
mq重復(fù)消費(fèi)問(wèn)題
默認(rèn)消息生產(chǎn)者會(huì)發(fā)送給消息給每個(gè)用戶茵烈,即多次消費(fèi)。當(dāng)我們的消息只需要被一個(gè)用戶消費(fèi)時(shí)砌些,需要對(duì)多個(gè)消息消費(fèi)者進(jìn)行共同分組
-
在多個(gè)消費(fèi)者項(xiàng)目配置文件里添加配置即可瞧毙,例:
spring: cloud: stream: bindings: input: group: config-client
mq持久化
自定義分組的消息消費(fèi)者掉線后再上線不會(huì)丟失錯(cuò)過(guò)的消息
-
本人創(chuàng)建一github demo,有需求可自行查看借鑒。