前言 微服務的服務提供者和服務消費者解耦合之後,我們可以藉助restTemplate這樣的HTTP客戶端,向微服務的服務提供者發起遠程調用; 但是這樣的代碼有2大缺陷: 代碼可讀性差,編程體驗不統一 當URL參數複雜時難以維護 //使用RestTemplate發起遠程調用 @Autowired pr ...
前言
微服務的服務提供者和服務消費者解耦合之後,我們可以藉助restTemplate這樣的HTTP客戶端,向微服務的服務提供者發起遠程調用;
但是這樣的代碼有2大缺陷:
//使用RestTemplate發起遠程調用 @Autowired private RestTemplate restTemplate; public Order findById(Long orderId) { // 1.查詢訂單 Order order = orderMapper.selectById(orderId); //2.調用user-service服務查詢當前訂單的用戶信息 //String url = "http://127.0.0.1:8081/user/" + order.getUserId(); //使用RestTemplate發起遠程調用 String url = "http://user-service/user/" + order.getUserId(); User user = restTemplate.getForObject(url, User.class); //3.user封裝到order對象 order.setUser(user); // 4.返回 return order; }
其作用就是幫助我們優雅的實現HTTP請求的發送,解決上面提到的問題。
<!--feign的依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
@EnableFeignClients
@MapperScan("com.zhanggen.order.mapper") @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients //開啟Feign public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); }
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
com.zhanggen.order.mapper
//FeignClient必須和@EnableFeignClients標註的類在同一個包下 //該介面用於向user-service微服務發起遠程調用 //Feign底層預設使用HTTP協議發起遠程調用 //@FeignClient("user-service")+@GetMapping("/user/{id}")確定服務提供者的URL(http://user-service/user/{id}) @FeignClient("user-service") public interface UserClient { //根據userId查詢用戶信息 @GetMapping("/user/{id}") User findById(@PathVariable Long id); }
這樣,Feign就可以幫助我們發送http請求,無需自己使用RestTemplate來發送了。
//使用Feign發起遠程調用 @Autowired private UserClient userClient; public Order findById(Long orderId) { // 1.查詢訂單 Order order = orderMapper.selectById(orderId); //2.調用user-service服務查詢當前訂單的用戶信息 //String url = "http://127.0.0.1:8081/user/" + order.getUserId(); //使用RestTemplate發起遠程調用 //String url = "http://user-service/user/" + order.getUserId(); //User user = restTemplate.getForObject(url, User.class); User user = userClient.findById(order.getUserId()); //3.user封裝到order對象 order.setUser(user); // 4.返回 return order; }
三、
作用 | 說明 | |
---|---|---|
feign.Logger.Level | 修改日誌級別 | 包含四種不同的級別:NONE(預設)、BASIC、HEADERS、FULL NONE ,不記錄。預設選項 BASIC ,僅記錄請求方法和URL以及響應狀態代碼和執行時間。 HEADERS ,記錄基本信息以及請求和響應標頭。 FULL ,記錄請求和響應的標題,正文和元數據。 |
feign.codec.Decoder | 響應結果的解析器 | http遠程調用的結果做解析,例如解析json字元串為java對象 |
feign.codec.Encoder | 請求參數編碼 | 將請求參數編碼,便於通過http請求發送,例如POST請求,將請求參數編碼到請求體中 |
feign.Contract | 支持的註解格式 | 預設是SpringMVC的註解 |
feign.Retryer | 失敗重試機制 |
feign: client: config: user-service: # 針對某個微服務的配置,也可以針對所有服務,這個位置換成default loggerLevel: FULL # 日誌級別
package com.zhanggen.order.config; import feign.Logger; import org.springframework.context.annotation.Bean; public class FeignDefaultConfiguration { @Bean public Logger.Level feignLogLevel(){ return Logger.Level.FULL; // 日誌級別為FULL } }
2.1.配置局部
如果我想讓以上日誌配置在調用某1個服務提供者時生效,在FeigClien介面中修改如下;
@FeignClient(value = "user-service",configuration = FeignDefaultConfiguration.class) public interface UserClient { //根據userId查詢用戶信息 @GetMapping("/user/{id}") User findById(@PathVariable Long id); }
2.2.配置全局
@EnableFeignClients(defaultConfiguration = FeignDefaultConfiguration.class) public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); }
四、Feign連接池
-
URLConnection:預設實現,不支持連接池,每次請求都是新建連接
-
Apache HttpClient :支持連接池
-
OKHttp:支持連接池
因此提高Feign的性能主要手段就是使用連接池
<!--httpClient的依賴內置連接池 --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency>
max-connections-per-route:再調用某1個服務提供者時,最多從連接池中拿出50個連接發起遠程調用,避免服務雪崩;
feign:
httpclient:
enabled: true # 開啟feign對HttpClient的支持
max-connections: 200 # 設置最大的連接數
max-connections-per-route: 50 # 並行接收一個服務的請求數量
1.創建fein-api模塊
把之前在order-service中編寫的UserClient、User、FeignDefaultConfiguration剪切到feign-api項目中
2.pom依賴依賴
在fein-api模塊中添加以下依賴
<dependencies> <!--openfeign依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--mybatis-plus 實體類註解要用到--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-core</artifactId> <version>3.4.0</version> </dependency> <!--httpclient基於連接池的調用--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency> </dependencies>
3.服務消費者
服務消費者依賴fei-api公共模塊;
<dependency> <groupId>com.zhanggen</groupId> <artifactId>fein-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
服務消費者啟動類
@EnableFeignClients(defaultConfiguration = FeignDefaultConfiguration.class, basePackages = "com.zhanggen.feign") public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } //SpringBoot啟動是,在Spring容器中放入1個restTemplate對象 @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }