1. 配置中心
1.1 配置中心的設置
SpringCloud配置中心也可以使用nacos來完成
nacos配置中心的配置通過 [服務名]-[類型].[后綴名] 來定位到需要讀取這個配置文件的服務
1.2 配置中心的讀取
- 給需要使用配置中心的服務 添加依賴
<!--nacos配置管理依賴-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 給需要使用配置中心的服務 添加 bootstrap.yml 配置文件並輸入配置
# 通過 [服務名稱]-[開發環境].[文件類型] 可以定位到 Nacos 的配置中心的具體配置
spring:
application:
name: userservice # 服務名稱
profiles:
active: dev #開發環境,這里是dev
cloud:
nacos:
server-addr: localhost:8848 # Nacos地址
config:
file-extension: yaml # 文件后綴名
- 部署熱更新
每次修改配置中心的文件,服務不需要再重啟就能讀取到最新配置
方法1. 想要熱更新的Field所在class上添加 @RefreshScope 注解,這樣配置中心的xx.yyy屬性更新后,str的屬性也會更新
@Component
@RefreshScope
class Test{
@Value("xx.yyy")
private String str;
}
方法2. 使用 @ConfigurationProperties 注解獲取配置中心的配置,然后添加到IOC容器中。這樣配置中心的xx.yyy屬性更新后,yyy的屬性也會更新
@Component
@ConfigurationProperties(prefix = "xx")
class Test{
private String yyy;
}
@Component
class Org{
@Autowired
private Test test;
}
1.3 配置中心的共享
直接使用 [服務名稱].[文件類型] 為Data ID來創建配置
這樣該服務的所有類型的開發環境下都能讀取到該配置
配置的優先級:[服務名稱]-[開發環境].[文件類型] > [服務名稱].[文件類型] > 本地配置文件(applicaiton.yml)
2. Feign遠程調用
Feign提供了一種優雅的方式調用遠程接口,不需要再使用 RestTemplate 了
2.1 使用步驟
- 給需要使用遠程調用功能的服務 添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--servlet API-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
- 給需要使用遠程調用功能的服務的啟動類添加 @EnableFeignClients 注解
- 編寫Feign客戶端(接口)
@FeignClient("userservice") //服務名
public interface UserFeign {
// 請求方式、請求路徑、方法參數、返回值要和 被請求的服務 的接口相同
@GetMapping("/user/{id}")
User findByID(@PathVariable("id")Long id);
}
- 使用
@Component
class Test{
@Autowired
private UserFeign userFeign;
public void test(){
User user = userFeign.findByID(1L);
}
}
2.2 自定義配置
- 主要屬性
- 配置文件方式
基於配置文件修改feign的日志級別可以針對單個服務:
feign:
client:
config:
userservice: # 針對某個微服務的配置
loggerLevel: FULL # 日志級別
也可以針對所有服務:
feign:
client:
config:
default: # 這里用default就是全局配置,如果是寫服務名稱,則是針對某個微服務的配置
loggerLevel: FULL # 日志級別
- 代碼方式
public class DefaultFeignConfiguration {
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.BASIC; // 日志級別為BASIC
}
//設置feign發送請求的攔截器,解決feign遠程調用請求頭丟失的問題
@Bean
public RequestInterceptor requestInterceptor(){
//設置以后,Feign在遠程調用之前,會先執行apply方法
return requestTemplate -> {
//1.使用RequestContextHolder獲取在Controller層進入的請求的所有屬性,底層是使用ThreadLocal的機制
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(attributes == null)
return;
HttpServletRequest request = attributes.getRequest();
//2.同步請求頭數據 (Cookie)
String cookie = request.getHeader("Cookie");
requestTemplate.header("Cookie",cookie);
};
}
}
2.3 Feign的性能優化
使用連接池代替默認的URLConnection
- 引入依賴
<!--httpClient的依賴 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
- 添加配置
feign:
httpclient:
enabled: true # 開啟feign對HttpClient的支持
max-connections: 200 # 最大的連接數
max-connections-per-route: 50 # 每個路徑的最大連接數
2.4 最佳實踐
把Feign抽取成模塊,然后需要用到的服務再引入即可
- 創建模塊 feign
- 引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 抽取公共類(pojo類,Feign類,FeignConfig類等等)
- 給需要用到的服務 引入依賴
<dependency>
<groupId>com.cc</groupId>
<artifactId>feign</artifactId>
<version>1.0</version>
</dependency>
- 解決包掃描問題(服務的啟動類上)
3. Gateway網關
3.1 Gateway入門
- 創建 Gateway 模塊並引入依賴
<!--網關-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服務發現依賴-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 編寫配置信息(application.yml)
server:
port: 10010 # 網關端口
spring:
application:
name: gateway # 服務名稱
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 網關路由配置
- id: user-service # 路由id,自定義,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目標地址 http就是固定地址
uri: lb://userservice # 路由的目標地址 lb就是負載均衡,后面跟服務名稱
predicates: # 路由斷言,也就是判斷請求是否符合路由規則的條件
- Path=/user/** # 這個是按照路徑匹配,只要以/user/開頭就符合要求
- 運行流程
- 斷言工廠(predicates屬性)
- 過濾器工廠
5.1 過濾器種類
5.1.1 例子:請求頭過濾器
給所有進入userservice的請求添加一個請求頭:Truth=itcast is freaking awesome! 修改application.yml文件就好
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
filters: # 過濾器
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加請求頭
5.2 默認過濾器
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
default-filters: # 默認過濾項
- AddRequestHeader=Truth, Itcast is freaking awesome!
5.3 全局過濾器,用來添加自己的邏輯
實現 GlobalFilter 接口
@Order(-1) // order指定的越小,同等級Filter就先執行
@Component
public class AuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// 如果滿足條件就放行(執行下一個過濾器)
if(request.getQueryParams().get("auth") != null){
return chain.filter(exchange);
}
// 如果不滿足條件就重定向到 "https://www.baidu.com/"
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.SEE_OTHER);
response.getHeaders().set("Location", "https://www.baidu.com/");
return exchange.getResponse().setComplete();
}
}
- 跨域問題
在application.yml中添加如下配置
spring:
cloud:
gateway:
globalcors: # 全局的跨域處理
add-to-simple-url-handler-mapping: true # 解決options請求被攔截問題
corsConfigurations:
'[/**]':
allowedOrigins: # 允許哪些網站的跨域請求
- "http://localhost:8090"
allowedMethods: # 允許的跨域ajax的請求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允許在請求中攜帶的頭信息
allowCredentials: true # 是否允許攜帶cookie
maxAge: 360000 # 這次跨域檢測的有效期
- 如果GateWay無法使用Feign
將以下類加入IOC容器
@Configuration
public class GateWayConfig {
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
}
}