SpringCloud詳細筆記2
SpringCloud
- 案例代碼
https://github.com/ZengjxRsingstar/springcloud2/blob/master/README.md
1 SpringCloudFeign
1.2 Feign簡介
Feign [fe?n] 譯文 偽裝。Feign是一個聲明式WebService客戶端。使用Feign能讓編寫WebService客戶端更加簡單,它的使用方法是定義一個接口,然后在上面添加注解。不再需要拼接URL,參數等操作。
項目主頁:https://github.com/OpenFeign/feign
? 集成Ribbon的負載均衡功能
? 集成了Hystrix的熔斷器功能
? 支持請求壓縮
? 大大簡化了遠程調用的代碼,同時功能還增強啦
? Feign以更加優雅的方式編寫遠程調用代碼,并簡化重復代碼
1.3 實現步驟
使用Feign替代RestTemplate發送Rest請求。
實現步驟:
- 導入feign依賴
- 編寫Feign客戶端接口
- 消費者啟動引導類開啟Feign功能注解
- 訪問接口測試
1.3.1
1.3.2 導入依賴
在user-consumer中添加spring-cloud-starter-openfeign依賴
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
1.3.3 創建Feign客戶端
在user-consumer中創建com.zengjx.feign.UserClient接口,代碼如下:
@FeignClient(value = "user-provider") //聲明Feign的客戶端,value:填寫生產者的名稱
public interface UserClient {
//注意:此處的請求地址一定要和生產者請求的地址一樣
@RequestMapping("{id}")
public User findById(@PathVariable("id")Integer id);
}
解釋:
Feign會通過動態代理,幫我們生成實現類。
注解@FeignClient聲明Feign的客戶端,注解value指明服務名稱
接口定義的方法,采用SpringMVC的注解。Feign會根據注解幫我們生成URL地址
注解@RequestMapping中的/user,不要忘記同時建議不要放在類的頭部。因為Feign需要拼接可訪問地址
1.3.4 編寫控制層
在user-consumer中創建com.zengjx.controller.ConsumerFeignController,在Controller中使用@Autowired注入FeignClient,代碼如下
@RestController
@RequestMapping(“feign”)
public class ConsumerFeignController {
@Autowired
private UserClient userClient;
@RequestMapping("{id}")
public User findById(@PathVariable(value = "id")Integer id){
return userClient.findByUserId(id);
}
}
1.3.5 開啟Feign
修改user-consumer的啟動類,在啟動類上添加@EnableFeignClients注解,開啟Feign,代碼如下:
**@SpringBootApplication
@EnableDiscoveryClient //開啟eureka發現功能
@EnableCircuitBreaker //開啟熔斷器
@EnableFeignClients //開啟Feign客戶端**
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class,args);
}
/***
* 將RestTemplate的實例放到Spring容器中
* @return
*/
@Bean
@LoadBalanced //開啟負載均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
1.3.6 測試
啟動相關工程,請求http://localhost:18082/feign/2 效果如下:
端口可以調整:
1.4 負載均衡
Feign自身已經集成了Ribbon,因此使用Feign的時候,不需要額外引入依賴。
Feign內置的ribbon默認設置了請求超時時長,默認是1000,可以修改
ribbon內部有重試機制,一旦超時,會自動重新發起請求。如果不希望重試可以關閉配置:
修改服務地址輪詢策略,默認是輪詢,配置之后變隨機
user-provider:
ribbon:
#輪詢
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
#隨機算法
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ConnectTimeout: 10000 # 連接超時時間
ReadTimeout: 2000 # 數據讀取超時時間
MaxAutoRetries: 1 # 最大重試次數(第一個服務)
MaxAutoRetriesNextServer: 0 # 最大重試下一個服務次數(集群的情況才會用到)
OkToRetryOnAllOperations: false # 無論是請求超時或者socket read timeout都進行重試,一般設置為false
1.5 熔斷器支持
Feign默認也有對Hystrix的集成
實現步驟:
- 在配置文件application.yml中開啟feign熔斷器支持
- 編寫FallBack處理類,實現FeignClient客戶端
- 在@FeignClient注解中,指定FallBack處理類。
- 測試
1.5.1 開啟Hystrix
在配置文件application.yml中開啟feign熔斷器支持:默認關閉
feign:
hystrix:
enabled: true # 開啟Feign的熔斷功能
1.5.2 熔斷降級類創建
在user-consumer,創建類com.zengjx.feign.fallback.UserClientFallback,實現剛才編寫的UserClient,作為FallBack的處理類,代碼如下:
@Component
public class UserClientFallback implements UserClient {
/**
* 服務降級實現
* @param id
* @return
*/
@Override
public User findById(Integer id) {
User user = new User();
user.setUsername("Fallback,Feign服務降級。。。");
return user;
}
}
1.5.3 指定Fallback處理類
在@FeignClient注解中,指定FallBack處理類
@FeignClient(value = "user-provider",fallback = UserClientFallback.class) //聲明Feign的客戶端,value:填寫生產者的名稱
public interface UserClient {
//注意:此處的請求地址一定要和生產者請求的地址一樣
@RequestMapping("/user/{id}")
public User findById(@PathVariable("id")Integer id);
}
1.5.3.1 遇到的錯誤
Eureka 重啟
接口跟controller 方法一致。
錯誤記錄:
錯誤位置:@RequestMapping("user")
public interface UserClient
正確的是寫在方法上:
public interface UserClient {
//@RequestMapping("/user/{id}")
/**
* @ClassName HelloController
* @Description TODO
* @Author zengjx
* @Company zengjx
* @Date 2019/11/4 15:32
* @Version V1.0
*/
@FeignClient(value = "user-provider",
fallback = UserClientFallBack.class
// configuration = FeignConfig.class //配置feign配置信息
)
@RequestMapping("user")
public interface UserClient {
@RequestMapping("/{id}")
//@RequestMapping("/user/{id}")
User findUserById(@PathVariable(value ="id") Integer id);
}
報錯信息:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘requestMappingHandlerMapping’ defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map ‘zengjx.feign.UserClient’ method
public abstract zengjx.domain.User zengjx.feign.UserClient.findUserById(java.lang.Integer)
to { /user/{id}}: There is already ‘userClientFallBack’ bean method
1.5.4 測試
關閉服務生產者,請求http://localhost:18082/feign/1 ,效果如下:
1.6 請求壓縮
壓縮前:
壓縮后: 節省空間
SpringCloudFeign支持對請求和響應進行GZIP壓縮,以減少通信過程中的性能損耗。
通過配置開啟請求與響應的壓縮功能:
feign:
hystrix:
enabled: true # 開啟Feign的熔斷功能
compression:
request:
enabled: true # 開啟請求壓縮
response:
enabled: true # 開啟響應壓縮
也可以對請求的數據類型,以及觸發壓縮的大小下限進行設置
feign:
hystrix:
enabled: true # 開啟Feign的熔斷功能
compression:
request:
enabled: true # 開啟請求壓縮
mime-types: text/html,application/xml,application/json # 設置壓縮的數據類型
min-request-size: 2048 # 設置觸發壓縮的大小下限
#以上數據類型,壓縮大小下限均為默認值
response:
enabled: true # 開啟響應壓縮
1.7 Feign的日志級別配置
通過loggin.level.xx=debug來設置日志級別。然而這個對Feign客戶端不會產生效果。因為@FeignClient注解修飾的客戶端在被代理時,都會創建一個新的Feign.Logger實例。我們需要額外通過配置類的方式指定這個日志的級別才可以。
實現步驟:
- 在application.yml配置文件中開啟日志級別配置
- 編寫配置類,定義日志級別bean。
- 在接口的@FeignClient中指定配置類
- 重啟項目,測試訪問
1.7.1 普通日志等級配置
在user-consumer的配置文件中設置com.zengjx包下的日志級別都為debug
#配置普通日志級別
logging:
level:
com.zengjx: debug
1.7.2 Feign日志等級配置
在user-consumer中創建com.itheima.feign.conf.FeignConfig,定義日志級別
@Configuration
public class FeignConfig {
/***
* 日志級別
*/
@Bean
public Logger.Level feignLoggerLevel(){
/**
* NONE:不記錄任何日志,默認值
* BASIC:僅記錄請求的方法,URL以及響應狀態碼和執行時間
* HEADERS:在BASIC基礎上,額外記錄了請求和響應的頭信息
* FULL:記錄所有請求和響應的明細,包括頭信息、請求體、元數據
*/
return Logger.Level.FULL;
}
}
1.7.3 指定配置類
修改user-consumer的com.zengjx.feign.UserClient指定上面的配置類,代碼如下:
//聲明Feign的客戶端,value:填寫生產者的名稱
@FeignClient(value = “user-provider”,
fallback = UserClientFallback.class, //配置熔斷器
configuration = FeignConfig.class //配置日志級別
)
public interface UserClient {
//注意:此處的請求地址一定要和生產者請求的地址一樣
@RequestMapping("/user/{id}")
public User findById(@PathVariable("id")Integer id);
}
1.7.4 重啟項目,即可看到每次訪問的日志
1.8 小結
? Feign的作用:不再使用拼接URL的方式實現遠程調用,以接口調用的方式實現遠程調用,簡化了遠程調用的實現方式,增強了遠程調用的功能,例如:增加了負載均衡、熔斷、壓縮、日志啟用。
? 掌握Feign的使用過程
properties
1.引入Feign依賴包
2.創建Feign接口,feign接口中需要指定調用的服務名字
3.使用@EnabledFeignClients啟用Feign功能
? 掌握Feign的負載均衡配置
properties
在配置文件中配置
{spring.application.name}負載均衡屬性配置
? 掌握Feign的熔斷配置
properties
1.在application.yml中開啟Hystrix
2.給Feign接口創建一個實現類
3.給Feign指定fallback類
? 掌握Feign的壓縮配置
properties
在application.yml中指定壓縮屬性即可
? 掌握Feign的日志配置
properties
1.在application.yml中開啟普通日志等級
2.創建一個類,定義Feign日志等級
3.在Feign接口中指定定義日志的配置
2 網關 Spring Cloud Gateway
2.1 目標
? 網關的作用
? 會配置動態路由
? 會配置過濾器
? 能自定義全局過濾器
2.2 Gateway 簡介
Spring Cloud Gateway 是Spring Cloud團隊的一個全新項目,基于Spring 5.0、SpringBoot2.0、Project Reactor 等技術開發的網關。旨在為微服務架構提供一種簡單有效統一的API路由管理方式。
Spring Cloud Gateway 作為SpringCloud生態系統中的網關,目標是替代Netflix Zuul。Gateway不僅提供統一路由方式,并且基于Filter鏈的方式提供網關的基本功能。例如:安全,監控/指標,和限流。
本身也是一個微服務,需要注冊到Eureka。
網關的核心功能:過濾、路由
? 路由(route)
? 斷言Predicate函數:路由轉發規則
? 過濾器(Filter)
2.3
實現步驟:
- 創建gateway-service普通Maven工程
- 編寫基礎配置
- 編寫路由規則,配置靜態路由策略
- 啟動網關服務進行測試
2.3.1 創建一個子工程gateway_service
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_parent</artifactId>
<groupId>com.zengjx</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway_service</artifactId>
<dependencies>
<!-- 網關 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Eureka客戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
2.3.2 創建啟動引導類
創建啟動類com.zengjx.GatewayApplication,代碼如下:
@SpringBootApplication
@EnableDiscoveryClient// 開啟Eureka客戶端發現功能
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
2.3.3 application.yml配置
# 注釋版本
server:
port: 18084
spring:
application:
name: api-gateway # 應用名
# Eureka服務中心配置
eureka:
client:
service-url:
# 注冊Eureka Server集群
defaultZone: http://127.0.0.1:7001/eureka
2.3.4 啟動引導類,查看Eureka控制臺
2.4 路由配置
通過網關配置一個路由功能,用戶訪問網關的時候,如果用戶請求的路徑是以/user開始,則路由到user-provider服務去,修改application.yml配置即可實現,配置如下:
# 注釋版本
server:
port: 18084
spring:
application:
name: api-gateway # 應用名
cloud:
gateway:
routes:
#id唯一標識,可自定義
- id: user-service-route
#路由的服務地址
uri: http://localhost:18081
# 路由斷言:路由攔截規則
predicates:
- Path=/user/**
# Eureka服務中心配置
eureka:
client:
service-url:
# 注冊Eureka Server集群
defaultZone: http://127.0.0.1:7001/eureka
測試:
啟動GatewayApplication測試 18084 是gateway 的配置文件配置的端口。
訪問http://localhost:18084/user/2 會訪問user-provider服務,效果如下
2.5 動態路由
根據服務名稱**,去Eureka注冊中心查找服務對應的所有實例列表,然后進行動態路由!
修改映射配置:通過服務名稱獲取,修改application.yml
spring:
application:
name: api-gateway # 應用名
cloud:
gateway:
routes:
#id唯一標識,可自定義
- id: user-service-route
#路由的服務地址
#lb協議表示從Eureka注冊中心獲取服務請求地址
#user-provider訪問的服務名稱。
#路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
uri: lb://user-provider
# 路由斷言:路由攔截規則
predicates:
- Path=/user/**
路由配置中uri所用的協議為lb時,gateway將把user-provider解析為實際的主機和端口,并通過Ribbon進行負載均衡。
2.6 過濾器
過濾器作為Gateway的重要功能。常用于請求鑒權、服務調用時長統計、修改請求或響應header、限流、去除路徑.
2.6.1 過濾器的分類
默認過濾器:出廠自帶,實現好了拿來就用,不需要實現
全局默認過濾器
局部默認過濾器
自定義過濾器:根據需求自己實現,實現后需配置,然后才能用哦。
全局過濾器:作用在所有路由上。
局部過濾器:配置在具體路由下,只作用在當前路由上。
默認過濾器幾十個,常見如下:
過濾器名稱 說明
AddRequestHeader 對匹配上的請求加上Header
AddRequestParameters 對匹配上的請求路由
AddResponseHeader 對從網關返回的響應添加Header
StripPrefix 對匹配上的請求路徑去除前綴
詳細說明官方說明鏈接
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/single/spring-cloud-gateway.html#_gatewayfilter_factories
2.6.2 默認過濾器配置
默認過濾器有兩個:全局默認過濾器和局部默認過濾器。
2.6.2.1 全局過濾器
全局過濾器:對輸出響應頭設置屬性
對輸出的響應設置其頭部屬性名稱為X-Response-Default-MyName,值為zengjx
修改配置文件
spring:
application:
name: api-gateway # 應用名
cloud:
gateway:
routes:
#id唯一標識,可自定義
- id: user-service-route
#路由的服務地址
#lb協議表示從Eureka注冊中心獲取服務請求地址
#user-provider訪問的服務名稱。
#路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
uri: lb://user-provider
# 路由斷言:路由攔截規則
predicates:
- Path=/user/**
#默認過濾器配置
default-filters:
# 往響應過濾器中加入響應頭信息
- AddResponseHeader=X-Response-Default-MyName,zengjx
查看瀏覽器響應頭信息!
2.6.2.2 局部過濾器
通過局部默認過濾器,修改請求路徑。局部過濾器在這里介紹兩種:添加路徑前綴、去除路徑前綴。
2.6.2.2.1 添加路徑前綴
在gateway中可以通過配置路由的過濾器PrefixPath 實現映射路徑中的前綴
配置請求地址添加路徑前綴過濾器
spring:
application:
name: api-gateway # 應用名
cloud:
gateway:
routes:
#id唯一標識,可自定義
- id: user-service-route
#路由的服務地址
#lb協議表示從Eureka注冊中心獲取服務請求地址
#user-provider訪問的服務名稱。
#路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
uri: lb://user-provider
# 路由斷言:路由攔截規則
predicates:
#- Path=/user/**
#注意:要想接下來的前綴過濾器生效,此處攔截規則為所有url:/**
- Path=/**
filters:
- PrefixPath=/user # 給當前路由所有請求,添加"/user"前綴
#默認過濾器配置
default-filters:
# 往響應過濾器中加入響應頭信息
- AddResponseHeader=X-Response-Default-MyName,zengjx
注意: 需要修改#- Path=/user/** 為- Path=/**
路由地址信息:
配置 訪問地址 路由地址
PrefixPath=/user http://localhost:18084/2 http://localhost:18084/ user/2
測試:瀏覽器訪問:http://localhost:18084/2 發現也可以查到用戶信息
2.6.2.2.2 去除路徑前綴
在gateway中通過配置路由過濾器StripPrefix,實現映射路徑中地址的去除。通過StripPrefix=1來指定路由要去掉的前綴個數。如:路徑/api/user/1將會被路由到/user/1。
配置去除路徑前綴過濾器
spring:
application:
name: api-gateway # 應用名
cloud:
gateway:
routes:
#id唯一標識,可自定義
- id: user-service-route
#路由的服務地址
#lb協議表示從Eureka注冊中心獲取服務請求地址
#user-provider訪問的服務名稱。
#路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
uri: lb://user-provider
# 路由斷言:路由攔截規則
predicates:
#- Path=/user/**
#注意:要想接下來的前綴過濾器生效,此處攔截規則為所有url:/**
- Path=/**
filters: #注意:PrefixPath與StripPrefix過濾器不要一起使用,一起使用等于沒配置過濾器
#- PrefixPath=/user # 給當前路由所有請求,添加"/user"前綴
- StripPrefix=1 # 去除路徑前綴過濾器,一個"/"識別為一個路徑
#默認過濾器配置
default-filters:
# 往響應過濾器中加入響應頭信息
- AddResponseHeader=X-Response-Default-MyName,zengjx
測試:
瀏覽器訪問:http://localhost:18084/api/2 發現也可以查到用戶信息
http://localhost:18085/add/user/1/
路由地址信息:
配置 訪問地址 路由地址
StripPrefix=1 http://localhost:18084/api/user/2 http://localhost:18081/user/2
StripPrefix=2 http://localhost:18084/api/r/user/2 http://localhost:18081/user/2
2.6.3 自定義過濾器案例
自定義過濾器也有兩個:全局自定義全局過濾器和自定義局部過濾器。
自定義全局過濾器的案例:模擬登陸校驗。
基本邏輯:如果請求中有token參數,則認為請求有效放行,如果沒有則攔截提示授權無效
2.6.3.1 自定義全局過濾器
實現步驟:
1.在gateway-service工程編寫全局過濾器類實現GlobalFilter,Ordered
2.編寫業務邏輯代碼
3.訪問接口測試,加token和不加token。
在gateway-service中創建com.zengjx.filter.LoginGlobalFilter全局過濾器類,代碼如下:
@Component
public class LoginGlobalFilter implements GlobalFilter, Ordered {
/***
* 過濾攔截
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//獲取請求參數token
String token = exchange.getRequest().getQueryParams().getFirst("token");
//如果沒有傳入token
if(StringUtils.isEmpty(token)){
//設置返回狀態碼-400參數異常
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
//結束請求
return exchange.getResponse().setComplete();
}
//傳入了token,放行
return chain.filter(exchange);
}
/***
* 定義過濾器執行順序
* 返回值越小,越靠前執行
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
測試:不攜帶token http://localhost:18084/api/user/find/2效果如下:
測試:攜帶token http://localhost:18084/api/user/2?token=abc 此時可以正常訪問。
2.6.3.2 自定義局部過濾器(了解)
自定義局部過濾器,該過濾器在控制臺輸出配置文件中指定名稱的請求參數及參數的值
實現步驟:
- 在gateway-service中編寫MyParamGatewayFilterFactory類
- 實現業務代碼:循環請求參數中是否包含name,如果包含則輸出參數值
- 修改配置文件
- 訪問請求測試,帶name參數
在gateway_service中編寫MyParamGatewayFilterFactory類,此類不需要大家掌握,可以直接復制項目使用
/**
- 自定義局部過濾器
- 注意的點:{
-
類名必須是:前綴+GatewayFilterFactory
-
必須有構造函數
-
必須要有個內部類:Config
-
處理當前排序方法:shortcutFieldOrder
-
處理過濾器邏輯:apply
- }
*/
@Component
public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
/**
* 定義需要處理的參數
*/
public static final String PARAM_NAME = "name";
/****
* 處理過程
* @return
*/
@Override
public GatewayFilter apply(MyParamGatewayFilterFactory.Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String name = exchange.getRequest().getQueryParams().getFirst("name");
if(!StringUtils.isEmpty(name)){
System.out.println("名字參數:"+name);
}
return chain.filter(exchange);
}
};
}
/***
* 構造函數
*/
public MyParamGatewayFilterFactory() {
super(MyParamGatewayFilterFactory.Config.class);
}
/***
* 處理字段的排序
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(PARAM_NAME);
}
/****
* 需要處理的參數
* name:和處理的參數名字保持一致
*/
public static class Config {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
修改application.yml配置文件 - MyParam=name
spring:
application:
name: api-gateway # 應用名
cloud:
gateway:
routes:
#id唯一標識,可自定義
- id: user-service-route
#路由的服務地址
#lb協議表示從Eureka注冊中心獲取服務請求地址
#user-provider訪問的服務名稱。
#路由地址如果通過lb協議加服務名稱時,會自動使用負載均衡訪問對應服務
uri: lb://user-provider
# 路由斷言:路由攔截規則
predicates:
#- Path=/user/**
#注意:要想接下來的前綴過濾器生效,此處攔截規則為所有url:/**
- Path=/**
filters: #注意:PrefixPath與StripPrefix過濾器不要一起使用,一起使用等于沒配置過濾器
#- PrefixPath=/user # 給當前路由所有請求,添加"/user"前綴
- StripPrefix=1 # 去除路徑前綴過濾器,一個"/"識別為一個路徑
#配置自定義局部過濾器,此處的名字與過濾器聲明時的前綴一致
- MyParam=name
#默認過濾器配置
default-filters:
# 往響應過濾器中加入響應頭信息
- AddResponseHeader=X-Response-Default-MyName,zengjx
測試訪問,檢查后臺是否輸出name和itcast;訪問http://localhost:18084/api/user/find/2?name=itheima&token=aaa 會輸出。
2.6.4 微服務架構加入Gateway后
不管是來自客戶端的請求,還是服務內部調用。一切對服務的請求都可經過網關。
網關實現鑒權、動態路由等等操作。
Gateway就是我們服務的統一入口
2.7 小結
? 網關的作用
properties
1.為微服務架構提供一種簡單有效統一的API路由管理方式
2.可以在網關中實現微服務鑒權、安全控制、請求監控、限流
? 會配置動態路由
properties
使用lb配置,能根據服務名字動態請求。
? 會配置過濾器
properties
默認過濾器:default-filters:
? 能自定義全局過濾器
properties
編寫過濾器類,實現GlobalFilter和Ordered,在filter方法中實現過濾。
3 配置中心 Spring Cloud Config
3.1 目標
? 了解配置中心的作用
? 能配置Git倉庫
? 能搭建配置中心
? 修改微服務,從配置中心獲取修改的配置
3.2 Config簡介
分布式系統中,由于服務數量非常多,配置文件分散在不同微服務項目中,管理極其不方便。為了方便配置文件集中管理,需要分布式配置中心組件。在Spring Cloud中,提供了Spring Cloud Config,它支持配置文件放在配置服務的本地,也支持配置文件放在遠程倉庫Git(GitHub、碼云)。配置中心本質上是一個微服務,同樣需要注冊到Eureka服務中心!
3.3 Git配置管理
3.3.1 遠程Git倉庫
知名的Git遠程倉庫有國外的GitHub和國內的碼云(gitee);
GitHub主服務在外網,訪問經常不穩定,如果希望服務穩定,可以使用碼云;
碼云訪問地址:http://gitee.com 測試地址:https://gitee.com/zengjx/config.git
3.3.2 創建遠程倉庫
首先使用碼云上的git倉庫需要先注冊賬戶。
賬戶注冊完成,然后使用賬戶登錄碼云控制臺并創建公開倉庫
配置倉庫 名稱和路徑
3.3.3 創建配置文件
在新建的倉庫中創建需要被統一配置管理的配置文件
3.3.3.4文件命名有規則:
配置文件的命名方式:{application}-{profile}.yml或{application}-{profile}.properties
application為應用名稱
profile用于區分開發環境dev,測試環境test,生產環境pro等
開發環境 user-dev.yml
測試環境 user-test.yml
生產環境 user-pro.yml
創建一個user-provider-dev.yml文件
將user-provider工程里的配置文件application.yml內容復制進去。
server:
port: 18081
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
application:
name: user-provider #服務的名字,不同的應用,名字不同,如果是集群,名字需要相同
#指定eureka服務地址
eureka:
client:
service-url:
# EurekaServer的地址
defaultZone: http://localhost:7001/eureka
# 每隔30獲取服務列表(只讀備份)
registry-fetch-interval-seconds: 30
instance:
#指定IP地址
ip-address: 127.0.0.1
#訪問服務的時候,推薦使用IP
prefer-ip-address: true
#租約到期,服務時效時間,默認值90秒
lease-expiration-duration-in-seconds: 150
#租約續約間隔時間,默認30秒
lease-renewal-interval-in-seconds: 30
創建完user-provider-dev.yml配置文件之后,gitee中的倉庫如下:
3.3.3.5 遇到訪問碼云沒有權限
問題:
沒有權限:
設置為公開:
rg.eclipse.jgit.api.errors.TransportException: https://gitee.com/zengjx/config.git: Authentication is required but no CredentialsProvider has been registered
4 【異常】org.eclipse.jgit.api.errors.TransportException: [email protected]/base-config-center.git: channel is not opened.
一、異常原因
連不上git倉庫,可能原因有:
1.)git倉庫不存在
2)連接git倉庫超時
原因是;上面碼云倉庫設置為公開后沒有點擊保存:
rg.eclipse.jgit.api.errors.TransportException: https://gitee.com/zengjx/config.git: Authentication is required but no CredentialsProvider has been registered
4 【異常】org.eclipse.jgit.api.errors.TransportException: [email protected]/base-config-center.git: channel is not opened.
4.1 搭建配置中心微服務
實現步驟:
- 創建配置中心SpringBoot項目config_server
- 配置坐標依賴
- 啟動類添加開啟配置中心服務注解
- 配置服務中心application.yml文件
- 啟動測試
4.1.1 創建工程 conf_server
```java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_parent</artifactId>
<groupId>com.zengjx</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>conf_server</artifactId>
<dependencies>
<!-- Eureka客戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--配置中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
</project>
4.1.3 application.yml配置文件
```java
# 注釋版本
server:
port: 18085 # 端口號
spring:
application:
name: config-server # 應用名
cloud:
config:
server:
git:
# 配置gitee的倉庫地址
uri: https://gitee.com/StevenBlake/conf.git
# Eureka服務中心配置
eureka:
client:
service-url:
# 注冊Eureka Server集群
defaultZone: http://127.0.0.1:7001/eureka
# com.itheima 包下的日志級別都為Debug
logging:
level:
com: debug
4.1.4 測試
啟動config-server,訪問http://localhost:18085/user-provider-dev.yml ,效果如下

可以查看到碼云上的文件數據,并且可以在gitee上修改user-dev.yml,然后刷新上述測試地址也能及時更新數據。
## 4.2 服務去獲取配置中心配置
目標:改造user-provider工程,配置文件不再由微服務項目提供,而是從配置中心獲取。
目標:改造user-provider工程,配置文件不再由微服務項目提供,而是從配置中心獲取。
實現步驟:
1. 添加配置中心客戶端啟動依賴
2. 修改服務提供者的配置文件
3. 啟動服務
4. 測試效果
4.2.1.1 添加依賴
```java
<!--spring cloud 配置中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
4.2.1.2 修改配置
刪除user-provider工程的application.yml文件
創建user-provider工程bootstrap.yml配置文件,配置內容如下
# 注釋版本
spring:
cloud:
config:
name: user-provider # 與遠程倉庫中的配置文件的application保持一致,{application}-{profile}.yml
profile: dev # 遠程倉庫中的配置文件的profile保持一致
label: master # 遠程倉庫中的版本保持一致
discovery:
enabled: true # 使用配置中心
service-id: config-server # 配置中心服務id
#向Eureka服務中心集群注冊服務
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka
關于application.yml和bootstrap.yml文件的說明:
- bootstrap.yml文件是SpringBoot的默認配置文件,而且其加載時間相比于application.yml更早。
- bootstrap.yml和application.yml都是默認配置文件,但定位不同
- bootstrap.yml可以理解成系統級別的一些參數配置,一般不會變動
- application.yml用來定義應用級別的參數
- 搭配spring-cloud-config使用application.yml的配置可以動態替換。
- bootstrap.yml相當于項目啟動的引導文件,內容相對固定
- application.yml文件是微服務的常規配置參數,變化比較頻繁
4.2.1.3 啟動測試
啟動eurake服務中心、conf配置中心、user_provider如果啟動沒報錯,其實已經使用上配置中心內容了
可以在服務中心查看也可以檢驗user_service的服務
4.3.1 修改碼云配置文件
修改在碼云上的user-provider-dev.yml文件,添加一個屬性test.message,如下操作:
4.3.2 讀取配置文件數據
在user-provider工程中創建一個com.zengjx.controller.LoadConfigController讀取配置文件信息,代碼如下:
@RestController
@RequestMapping(value = "config")
public class LoadConfigController {
@Value("${test.message}")
private String msg;
/***
* 讀取配置文件中的數據
* @return
*/
@RequestMapping(value = "load")
public String load(){
return msg;
}
}
啟動運行user-provider,訪問http://localhost:18081/config/load
修改碼云上的配置后,發現項目中的數據仍然沒有變化,只有項目重啟后才會變化。
4.4 小結
? 配置中心的作用:將各個微服務的配置文件集中到一起進行統一管理。
? 能搭建配置中心
需要在application.yml配置文件中指定需要遠程更新的倉庫地址。
? 修改微服務,從配置中心獲取修改的配置
properties:
創建bootstrap.yml,并在bootstrap.yml中配置
# 注釋版本
spring:
cloud:
config:
name: user-provider # 與遠程倉庫中的配置文件的application保持一致,{application}-{profile}.yml
profile: dev # 遠程倉庫中的配置文件的profile保持一致
label: master # 遠程倉庫中的版本保持一致
discovery:
enabled: true # 使用配置中心
service-id: config-server # 配置中心服務id
#向Eureka服務中心集群注冊服務
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka
5 消息總線 Spring Cloud Bus
SpringCloud Bus,解決上述問題,實現配置自動更新。
注意:SpringCloudBus基于RabbitMQ實現,默認使用本地的消息隊列服務,所以需要提前安裝并啟動RabbitMQ。安裝參考./04資料/安裝Windows RabbitMQ.pdf
5.1 Bus簡介
Bus是用輕量的消息代理將分布式的節點連接起來,可以用于廣播配置文件的更改或者服務的監控管理。
Bus可以為微服務做監控,也可以實現應用程序之間互相通信。Bus可選的消息代理RabbitMQ和Kafka。
廣播出去的配置文件服務會進行本地緩存。
5.2 整合案例
目標:消息總線整合入微服務系統,實現配置中心的配置自動更新。不需要重啟微服務。
5.2.1 改造配置中心
改造步驟:
? 在config-server項目中加入Bus相關依賴
? 修改application.yml,加入RabbitMQ的配置信息,和暴露觸發消息總線地址
5.2.1.1 引入依賴
修改config-server的pom.xml引入依賴:
<!--消息總線依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<!--RabbitMQ依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
5.2.1.2 修改application.yml配置文件
修改config-server的application.yml,如下配置的rabbit都是默認值,其實可以完全不配置,代碼如下:
# 注釋版本
server:
port: 18085 # 端口號
spring:
application:
name: config-server # 應用名
cloud:
config:
server:
git:
# 配置gitee的倉庫地址
uri: https://gitee.com/StevenBlake/conf.git
# rabbitmq的配置信息;如下配置的rabbit都是默認值,其實可以完全不配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
# 暴露觸發消息總線的地址
management:
endpoints:
web:
exposure:
# 暴露觸發消息總線的地址
include: bus-refresh
# Eureka服務中心配置
eureka:
client:
service-url:
# 注冊Eureka Server集群
defaultZone: http://127.0.0.1:7001/eureka
# com.itheima 包下的日志級別都為Debug
logging:
level:
com: debug
5.2.2 改造用戶服務
改造步驟:
- 在用戶微服務user_provider項目中加入Bus相關依賴
- 修改user_provider項目的bootstrap.yml,加入RabbitMQ的配置信息
- UserController類上加入@RefreshScope刷新配置注解
- 測試
5.2.2.1 引入依賴
修改user-provider引入如下依賴:
<!--消息總線依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<!--RabbitMQ依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<!--健康監控依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
5.2.2.2 添加bootstrap.yml文件
在user-provider的resources目錄下添加bootstrap.yml,添加rabbitmq配置,代碼如下:
# 注釋版本
spring:
cloud:
config:
name: user-provider # 與遠程倉庫中的配置文件的application保持一致,{application}-{profile}.yml
profile: dev # 遠程倉庫中的配置文件的profile保持一致
label: master # 遠程倉庫中的版本保持一致
discovery:
enabled: true # 使用配置中心
service-id: config-server # 配置中心服務id
# rabbitmq的配置信息;如下配置的rabbit都是默認值,其實可以完全不配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
#向Eureka服務中心集群注冊服務
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka
5.2.2.3 添加刷新配置
修改user-provider的com.itheima.controller.LoadConfigController,添加一個@RefreshScope注解刷新配置信息,代碼如下:
@RestController
@RequestMapping(value = "config")
@RefreshScope //用于啟用刷新配置文件的信息
public class LoadConfigController {
@Value("${test.message}")
private String msg;
/***
* 讀取配置文件中的數據
* @return
*/
@RequestMapping(value = "load")
public String load(){
return msg;
}
}
5.2.3 測試
目標:當我們修改Git倉庫的配置文件,用戶微服務是否能夠在不重啟的情況下自動更新配置文件信息。
測試步驟:
(1)啟動eureka-server
(2)啟動config-server
(3)啟動user-provider
(4)訪問測試
訪問http://localhost:18081/config/load ,效果如下:
(5)修改碼云配置
修改碼云的配置,修改后并提交,修改如下:
(6)刷新配置
使用Postman以POST方式請求http://localhost:18085/actuator/bus-refresh
http://localhost:18086/actuator/bus-refresh
也可以用idea 自帶的:
請求地址中actuator是固定的,bus-refresh對應的是配置中心的config-server中的application.yml文件的配置項include的內容
(7)刷新測試
訪問http://localhost:18081/config/load ,效果如下:
(7)刷新測試
訪問http://localhost:18081/config/load
消息總線實現消息分發過程:
? 請求地址訪問配置中心的消息總線
? 消息總線接收到請求
? 消息總線向消息隊列發送消息
? user-service微服務會監聽消息隊列
? user-service微服務接到消息隊列中消息后
? user-service微服務會重新從配置中心獲取最新配置信息
什么時候使用了MQ?
https://blog.csdn.net/u010255818/article/details/77855873/
智能推薦
springCloud搭建詳細教程
springCloud搭建詳細教程 別的都不說了,直接動手: SpringCloud分布式開發五大組件詳解 服務發現——Netflix Eureka 客服端負載均衡——Netflix Ribbon 斷路器——Netflix Hystrix 服務網關——Netflix Zuul 分布式配置—&...
springcloud筆記
SpringCloud 微服務概述 [馬丁福勒微服務論文] : https://martinfowler.com/articles/microservices.html 什么是微服務 目前的微服務并沒有一個統一的標準,一般是以業務來劃分 將傳統的一站式應用,拆分成一個個的服務,徹底去耦合,一個微服務就是單功能業務,只做一件事。 與微服務相對的叫巨石 微服務與微服務架構 微服務是一種架構模式或者一種...
SpringCloud 筆記
文章目錄 一、SpringCloud介紹 1.1 微服務架構 1.2 SpringCloud介紹 二、服務的注冊與發現-Eureka【`重點`】 2.1 引言 2.2 Eureka的快速入門 2.2.1 創建EurekaServer 2.2.2 創建EurekaClient 2.2.3 測試Eureka 2.3 Eureka的安全性 2.4 Eureka的高可用 2.5 Eureka的細節 三、服...
SpringCloud筆記
SpringCloud 框架 一、分布式概念 1、分布式的優點 處理高并發問題: ? 面對越來越大的業務量,一臺機器的性能已經無法滿足。我們需要多臺機器才能滿足高并發的需求。因此我 們需要垂直或水平拆分業務系統,讓它變成一個分布式的架構。 加強系統可用性: ? 為了我們的系統不會因為一臺機器出故障二導致整個系統不可用。所以需要利用分布式來消除單點故障,提 高系統可用性。 把模塊拆分,使用接口通信,...
猜你喜歡
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...