亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺談SpringCloud feign的http請(qǐng)求組件優(yōu)化方案

 更新時(shí)間:2021年02月25日 10:26:01   作者:小魚(yú)兒_karl  
這篇文章主要介紹了淺談SpringCloud feign的http請(qǐng)求組件優(yōu)化方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

1 描述

如果我們直接使用SpringCloud Feign進(jìn)行服務(wù)間調(diào)用的時(shí)候,http組件使用的是JDK的HttpURLConnection,每次請(qǐng)求都會(huì)新建一個(gè)連接,沒(méi)有使用線(xiàn)程池復(fù)用。具體的可以從源碼進(jìn)行分析

2 源碼分析

我們?cè)诜治鲈创a很難找到入口,不知道從何開(kāi)始入手,我們?cè)诜治鯯pringCloud feign的時(shí)候可用在配置文件下面我講一下個(gè)人的思路。

1 首先我點(diǎn)擊@EnableFeignClients 看一下這個(gè)注解在哪個(gè)資源路徑下

如下圖所示:

2 找到服務(wù)啟動(dòng)加載的配置文件

3 因?yàn)閒eign底層的負(fù)載均衡是基于Ribbon的所以很快就找到了FeignRibbonClientAutoConfiguration.java 這個(gè)類(lèi)

@ConditionalOnClass({ ILoadBalancer.class, Feign.class })
@Configuration
@AutoConfigureBefore(FeignAutoConfiguration.class)
@EnableConfigurationProperties({ FeignHttpClientProperties.class })
//Order is important here, last should be the default, first should be optional
// see https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653
@Import({ HttpClientFeignLoadBalancedConfiguration.class,
 OkHttpFeignLoadBalancedConfiguration.class,
 DefaultFeignLoadBalancedConfiguration.class })
public class FeignRibbonClientAutoConfiguration {

首先我們從這三個(gè)類(lèi)進(jìn)行分析,從名字上來(lái)看我為了驗(yàn)證沒(méi)有特殊配置,feign底層走的是不是默認(rèn)的DefaultFeignLoadBalancedConfiguration.class

OkHttpFeignLoadBalancedConfiguration.class

HttpClientFeignLoadBalancedConfiguration.class

DefaultFeignLoadBalancedConfiguration.class

DefaultFeignLoadBalancedConfiguration.class

@Configuration
class DefaultFeignLoadBalancedConfiguration {
	@Bean
	@ConditionalOnMissingBean
	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
							 SpringClientFactory clientFactory) {
		return new LoadBalancerFeignClient(new Client.Default(null, null),
				cachingFactory, clientFactory);
	}
}

從上面代碼可知每次請(qǐng)求過(guò)來(lái)都會(huì)創(chuàng)建一個(gè)新的client,具體的源碼演示有興趣的可以深入研究,在這里不是我們所研究的重點(diǎn)。

OkHttpFeignLoadBalancedConfiguration.class

@Configuration
@ConditionalOnClass(OkHttpClient.class)
@ConditionalOnProperty(value = "feign.okhttp.enabled")
class OkHttpFeignLoadBalancedConfiguration {
	@Configuration
	@ConditionalOnMissingBean(okhttp3.OkHttpClient.class)
	protected static class OkHttpFeignConfiguration {
		private okhttp3.OkHttpClient okHttpClient;
		@Bean
		@ConditionalOnMissingBean(ConnectionPool.class)
		public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties,
													 OkHttpClientConnectionPoolFactory connectionPoolFactory) {
			Integer maxTotalConnections = httpClientProperties.getMaxConnections();
			Long timeToLive = httpClientProperties.getTimeToLive();
			TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
			return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
		}
		@Bean
		public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory,
										 ConnectionPool connectionPool, FeignHttpClientProperties httpClientProperties) {
			Boolean followRedirects = httpClientProperties.isFollowRedirects();
			Integer connectTimeout = httpClientProperties.getConnectionTimeout();
			this.okHttpClient = httpClientFactory.createBuilder(httpClientProperties.isDisableSslValidation()).
					connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).
					followRedirects(followRedirects).
					connectionPool(connectionPool).build();
			return this.okHttpClient;
		}
		@PreDestroy
		public void destroy() {
			if(okHttpClient != null) {
				okHttpClient.dispatcher().executorService().shutdown();
				okHttpClient.connectionPool().evictAll();
			}
		}
	}
	@Bean
	@ConditionalOnMissingBean(Client.class)
	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
							 SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) {
		OkHttpClient delegate = new OkHttpClient(okHttpClient);
		return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
	}
}

從源碼可以看出

1 該類(lèi)是個(gè)配置類(lèi),當(dāng)引入OkHttpClient.Class會(huì)加載

client方法中可以看出會(huì)返回一個(gè)http連接池的client
HttpClientFeignLoadBalancedConfiguration
@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
class HttpClientFeignLoadBalancedConfiguration {

這個(gè)類(lèi)和OkHttpFeignLoadBalancedConfiguration原理類(lèi)型

使用OKHttp替代默認(rèn)的JDK的HttpURLConnection

使用appach httpclient使用教程類(lèi)似

使用方法

1 pom

 <dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-okhttp</artifactId>
 </dependency>

2 Yml文件

feign:
 okhttp:
 enabled: true

3 自定義連接池

可以通過(guò)代碼進(jìn)行配置,也可以通過(guò)yml配置

@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {
 @Bean
 public okhttp3.OkHttpClient okHttpClient(){
 return new okhttp3.OkHttpClient.Builder()
  .readTimeout(60,TimeUnit.SECONDS)
  .connectTimeout(60,TimeUnit.SECONDS)
  .connectionPool(new ConnectionPool())
  .build();
 }
}

驗(yàn)證

默認(rèn)的Feign處理會(huì)走到如下位置;

位置處于如下圖所示

 @Override
 public Response execute(Request request, Options options) throws IOException {
 HttpURLConnection connection = convertAndSend(request, options);
 return convertResponse(connection).toBuilder().request(request).build();
 }

走okhttp客戶(hù)端會(huì)走如下代碼

具體位置如下圖所示:

@Override public Response execute() throws IOException {
 synchronized (this) {
 if (executed) throw new IllegalStateException("Already Executed");
 executed = true;
 }
 captureCallStackTrace();
 try {
 client.dispatcher().executed(this);
 Response result = getResponseWithInterceptorChain();
 if (result == null) throw new IOException("Canceled");
 return result;
 } finally {
 client.dispatcher().finished(this);
 }
 }

驗(yàn)證結(jié)果

如下所示:

彩蛋

okhttp客戶(hù)端會(huì)走的代碼可以看出來(lái)okhttp有synchronized鎖線(xiàn)程安全的那默認(rèn)的是否是線(xiàn)程安全的呢 有待去驗(yàn)證。

追加

如果發(fā)現(xiàn)配置的超時(shí)時(shí)間無(wú)效,可以添加以下配置,因?yàn)樽x取超時(shí)配置的時(shí)候沒(méi)有讀取上面的okhttp的配置參數(shù),而是從Request中讀取。

具體配置如下所示:

 @Bean
 public Request.Options options(){
 return new Request.Options(60000,60000);
 }

補(bǔ)充:springCloud feign使用/優(yōu)化總結(jié)

基于springCloud Dalston.SR3版本

1.當(dāng)接口參數(shù)是多個(gè)的時(shí)候 需要指定@RequestParam 中的value來(lái)明確一下。

/**
 * 用戶(hù)互掃
 * @param uid 被掃人ID
 * @param userId 當(dāng)前用戶(hù)ID
 * @return
 */
@PostMapping(REQ_URL_PRE + "/qrCodeReturnUser")
UserQrCode qrCodeReturnUser(@RequestParam("uid") String uid,@RequestParam("userId") Integer userId);

2.接口參數(shù)為對(duì)象的時(shí)候 需要使用@RequestBody注解 并采用POST方式。

3.如果接口是簡(jiǎn)單的數(shù)組/列表參數(shù) 這里需要使用Get請(qǐng)求才行

@GetMapping(REQ_URL_PRE + "/getUserLevels")
Map<Integer, UserLevel> getUserLevels(@RequestParam("userIds") List<Integer> userIds);

4.直接可以在@FeignClient中配置降級(jí)處理方式 對(duì)于一些不重要的業(yè)務(wù) 自定義處理很有幫助

@FeignClient(value = "cloud-user", fallback = IUsers.UsersFallback.class)

5.feign默認(rèn)只有HystrixBadRequestException異常不會(huì)走熔斷,其它任何異常都會(huì)進(jìn)入熔斷,需要重新實(shí)現(xiàn)一下ErrorDecoder包裝業(yè)務(wù)異常

示例:https://github.com/peachyy/feign-support

6. feign HTTP請(qǐng)求方式選擇

feign默認(rèn)使用的是基于JDK提供的URLConnection調(diào)用HTTP接口,不具備連接池。所以資源開(kāi)銷(xiāo)上有點(diǎn)影響,經(jīng)測(cè)試JDK的URLConnection比Apache HttpClient快很多倍。但是Apache HttpClient和okhttp都支持配置連接池功能。具體選擇需要權(quán)衡

7.默認(rèn)不啟用hystrix 需要手動(dòng)指定feign.hystrix.enabled=true 開(kāi)啟熔斷

8.啟用壓縮也是一種有效的優(yōu)化方式

feign.compression.request.enabled=true
feign.compression.response.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json

9.參數(shù)相關(guān)調(diào)優(yōu)

hystrix線(xiàn)程數(shù)設(shè)置

設(shè)置參數(shù)hystrix.threadpool.default.coreSize 來(lái)指定熔斷隔離的線(xiàn)程數(shù) 這個(gè)數(shù)需要調(diào)優(yōu),經(jīng)測(cè)試 線(xiàn)程數(shù)我們?cè)O(shè)置為和提供方的容器線(xiàn)程差不多,吞吐量高許多。

第一次訪問(wèn)服務(wù)出錯(cuò)的問(wèn)題

啟用Hystrix后,很多服務(wù)當(dāng)?shù)谝淮卧L問(wèn)的時(shí)候都會(huì)失敗 是因?yàn)槌跏蓟?fù)載均衡一系列操作已經(jīng)超出了超時(shí)時(shí)間了 默認(rèn)的超時(shí)時(shí)間為1S,設(shè)置參數(shù)超時(shí)時(shí)間hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=30000 可解決這個(gè)問(wèn)題。

負(fù)載均衡參數(shù)設(shè)置

設(shè)置了Hystrix的超時(shí)參數(shù)會(huì) 還需設(shè)置一下ribbon的相關(guān)參數(shù) 這些參數(shù)和Hystrix的超時(shí)參數(shù)有一定的邏輯關(guān)系

請(qǐng)求處理的超時(shí)時(shí)間 ribbon.ReadTimeout=120000

請(qǐng)求連接的超時(shí)時(shí)間 ribbon.ConnectTimeout=30000

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • SpringBoot FailureAnalyzer實(shí)例使用教程

    SpringBoot FailureAnalyzer實(shí)例使用教程

    FailureAnalyzer是一種在啟動(dòng)時(shí)攔截exception并將其轉(zhuǎn)換為human-readable消息的好方法,包含在故障分析中。SpringBoot為application context相關(guān)的exceptions,JSR-303驗(yàn)證等提供了這樣的分析器,實(shí)際上很容易創(chuàng)建自己的
    2022-12-12
  • Java多線(xiàn)程編程之ThreadLocal線(xiàn)程范圍內(nèi)的共享變量

    Java多線(xiàn)程編程之ThreadLocal線(xiàn)程范圍內(nèi)的共享變量

    這篇文章主要介紹了Java多線(xiàn)程編程之ThreadLocal線(xiàn)程范圍內(nèi)的共享變量,本文講解了ThreadLocal的作用和目的、ThreadLocal的應(yīng)用場(chǎng)景、ThreadLocal的使用實(shí)例等,需要的朋友可以參考下
    2015-05-05
  • Hibernate中l(wèi)oad方法與get方法的區(qū)別

    Hibernate中l(wèi)oad方法與get方法的區(qū)別

    Hibernate中有兩個(gè)極為相似的方法get()與load(),他們都可以通過(guò)指定的實(shí)體類(lèi)與ID從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),并返回對(duì)應(yīng)的實(shí)例,但Hibernate不會(huì)搞兩個(gè)完全一樣的方法的
    2016-01-01
  • mybatis的動(dòng)態(tài)sql之if test的使用說(shuō)明

    mybatis的動(dòng)態(tài)sql之if test的使用說(shuō)明

    這篇文章主要介紹了mybatis的動(dòng)態(tài)sql之if test的使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Java程序中的延遲加載功能使用

    Java程序中的延遲加載功能使用

    這篇文章主要介紹了Java程序中的延遲加載功能使用,一定程度上有助于提升性能和降低內(nèi)存使用率,需要的朋友可以參考下
    2015-07-07
  • 深入理解Java中1是true0是false

    深入理解Java中1是true0是false

    Java中,1可以被看作是true,0可以被看作是false,本文就來(lái)進(jìn)行詳細(xì)的講解,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • MybatisPlus創(chuàng)建時(shí)間不想用默認(rèn)值的問(wèn)題

    MybatisPlus創(chuàng)建時(shí)間不想用默認(rèn)值的問(wèn)題

    MybatisPlus通過(guò)FieldFill注解和MpMetaObjectHandler類(lèi)支持自動(dòng)填充字段功能,特別地,可以設(shè)置字段在插入或更新時(shí)自動(dòng)填充創(chuàng)建時(shí)間和更新時(shí)間,但在特定場(chǎng)景下,如導(dǎo)入數(shù)據(jù)時(shí),可能需要自定義創(chuàng)建時(shí)間
    2024-09-09
  • Java處理時(shí)間格式CST和GMT轉(zhuǎn)換方法示例

    Java處理時(shí)間格式CST和GMT轉(zhuǎn)換方法示例

    這篇文章主要給大家介紹了關(guān)于Java處理時(shí)間格式CST和GMT轉(zhuǎn)換方法的相關(guān)資料,相信很多小伙伴在時(shí)間格式轉(zhuǎn)換的時(shí)候非常頭疼,文中通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 淺試仿?mapstruct實(shí)現(xiàn)微服務(wù)編排框架詳解

    淺試仿?mapstruct實(shí)現(xiàn)微服務(wù)編排框架詳解

    這篇文章主要為大家介紹了淺試仿?mapstruct實(shí)現(xiàn)微服務(wù)編排框架詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 使用SpringBoot簡(jiǎn)單實(shí)現(xiàn)無(wú)感知的刷新 Token功能

    使用SpringBoot簡(jiǎn)單實(shí)現(xiàn)無(wú)感知的刷新 Token功能

    實(shí)現(xiàn)無(wú)感知的刷新 Token 是一種提升用戶(hù)體驗(yàn)的常用技術(shù),可以在用戶(hù)使用應(yīng)用時(shí)自動(dòng)更新 Token,無(wú)需用戶(hù)手動(dòng)干預(yù),這種技術(shù)在需要長(zhǎng)時(shí)間保持用戶(hù)登錄狀態(tài)的應(yīng)用中非常有用,以下是使用Spring Boot實(shí)現(xiàn)無(wú)感知刷新Token的一個(gè)場(chǎng)景案例和相應(yīng)的示例代碼
    2024-09-09

最新評(píng)論