1. 程式人生 > 實用技巧 >Feign HttpClient連線池

Feign HttpClient連線池

原文連結:https://zhuanlan.zhihu.com/p/81107006

1.概念部分

http 的背景原理
a. 兩臺伺服器建立 http 連線的過程是很複雜的一個過程,涉及到多個數據包的交換,並
且也很耗時間。
b. Http 連線需要的 3 次握手 4 次分手開銷很大,這一開銷對於大量的比較小的 http 消
息來說更大。
2優化解決方案
a. 如果我們直接採用 http 連線池,節約了大量的 3 次握手 4 次分手;這樣能大大提升吞
吐率。
b. feign 的 http 客戶端支援 3 種框架;HttpURLConnection、httpclient、okhttp;預設是
HttpURLConnection。
c. 傳統的 HttpURLConnection 是 JDK 自帶的,並不支援連線池,如果要實現連線池的
機制,還需要自己來管理連線物件。對於網路請求這種底層相對複雜的操作,如果有可用的
其他方案,也沒有必要自己去管理連線物件。
d. HttpClient 相比傳統 JDK 自帶的 HttpURLConnection,它封裝了訪問 http 的請求頭,
引數,內容體,響應等等;它不僅使客戶端傳送 HTTP 請求變得容易,而且也方便了開發人
員測試介面(基於 Http 協議的),即提高了開發的效率,也方便提高程式碼的健壯性;另外
高併發大量的請求網路的時候,還是用“連線池”提升吞吐量。

2.在consumer端新增httpClient相關座標

注意:httpClien與feign版本之間的適配

Dalston.SR5版本

<!-- 新增 Feign 座標 -->
<dependency>
   <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- 使用Apache HttpClient替換Feign原生httpURLConnection -->
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
</dependency>
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-httpclient</artifactId>
  <version>8.17.0</version>
</dependency>\

Greenwich.SR2版本

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 使用Apache HttpClient替換Feign原生httpURLConnection -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
    <version>10.1.0</version>
</dependency>

3.修改application.properties

#啟用 httpclient
feign.httpclient.enabled=true

4.案例

server端

注意:
    1.在傳遞物件時在server端@RequestBody註解可寫可不寫
    2.與預設的相比支援get和post方式傳遞物件
    3.1.x版本需在@RequestMapping註解中指定consumes屬性,而2.x版本不需要

Dalston.SR5版本

//新增商品傳遞多個引數 方式二 :POST 方式
@RequestMapping(value="/add2",method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
public Product addProduct2(@RequestBody Product product);
//使用 HttpClient 工具 新增商品傳遞多個引數 :基於 GET 方式
@RequestMapping(value="/add3",method=RequestMethod.GET,consumes=MediaType.APPLICATION_JSON_VALUE)
    public Product addProduct3(Product product);
}

Greenwich.SR2版本

//傳遞物件  post方式
@PostMapping(value = "/add2")
String addItem2( Item item);
//傳遞物件  get方式
@GetMapping(value = "/add3")
String addItem3( Item item);

provier端

注意: 1.傳遞物件時必須在引數前使用@RequestBody註解

2.普通引數需使用@requestParam註解

//post方式傳遞物件
@Override
public String addItem2(@RequestBody Item item) {
    System.out.println(item);
    return "新增商品Ok";
}
//get方式傳遞物件
@Override
public String addItem3(@RequestBody Item item) {
    System.out.println(item);
    return "新增商品Ok";
}

consumer端

service層

@FeignClient(name = "feign-provider")
public interface ItemConsumerService  extends ItemService {
}

controller層

//post方式傳遞物件
@GetMapping("/add2")
public String addItem2(Item item){
    return itemConsumerService.addItem2(item);
}
//post方式傳遞物件
@GetMapping("/add3")
public String addItem3(Item item){
    return itemConsumerService.addItem3(item);
}

啟動器

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApplication.class, args);
    }

}

applicaton.properties

spring.application.name=feign-consumer
server.port=6001
eureka.client.service-url.defaultZone=http://root:root@eureka1:8761/eureka/,http://root:root@eureka2:8761/eureka/
#-----------------------------feign gzip
#配置請求 GZIP 壓縮
feign.compression.request.enabled=true
#配置響應 GZIP 壓縮
feign.compression.response.enabled=true
#配置壓縮支援的 MIME TYPE
feign.compression.request.mime-types=text/xml,application/xml,application/json
#配置壓縮資料大小的最小閥值,預設 2048
feign.compression.request.min-request-size=512

#-----------------------------spring boot gzip
#是否啟用壓縮
server.compression.enabled=true
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain

#啟用 httpclient
feign.httpclient.enabled=true