# feign Feignæ¯ä¸ä¸ªå£°æå¼çWebæå¡å®¢æ·ç«¯ãè¿ä½¿å¾Webæå¡å®¢æ·ç«¯çåå ¥æ´å æ¹ä¾¿ è¦ä½¿ç¨Feignå建ä¸ä¸ªçé¢å¹¶å¯¹å ¶è¿è¡æ³¨éãå®å ·æå¯æææ³¨éæ¯æï¼å æ¬Feign注éåJAX-RS注éãFeignè¿æ¯æå¯ææç¼ç å¨åè§£ç å¨ã Spring Cloudæ·»å äºå¯¹Spring MVC注éçæ¯æï¼å¹¶å¨Spring Webä¸ä½¿ç¨é»è®¤ä½¿ç¨çHttpMessageConvertersãSpring CloudéæRibbonåEureka以å¨ä½¿ç¨Feignæ¶æä¾è´è½½åè¡¡çhttp客æ·ç«¯ã ### feignæ ¸å¿ç±»ä»ç» * feign.Feign.Builder 设置åéhttp请æ±çç¸å ³åæ°ï¼æ¯å¦http客æ·ç«¯ï¼éè¯çç¥ï¼ç¼è§£ç ï¼è¶ æ¶æ¶é´çç * feign.Contract.Default è§£ææ¥å£æ¹æ³çå æ°æ®ï¼æå»ºhttpè¯·æ±æ¨¡æ¿ * feign.Client åéhttp请æ±å®¢æ·ç«¯ï¼é»è®¤å®ç°feign.Client.Defaultï¼ä½¿ç¨çæ¯java.netå å®ç°ç * Retryer éè¯ï¼é»è®¤å®ç°feign.Retryer.Defaultï¼è¶ æ¶å»¶è¿100mså¼å§éè¯ï¼æ¯é1séè¯ä¸æ¬¡ï¼éè¯4次 * Options è¶ æ¶æ¶é´ï¼é»è®¤è¿æ¥è¶ æ¶10sï¼è¯»è¶ æ¶60s * feign.codec.Encoder ç¼ç å¨ * feign.codec.Decoder è§£ç å¨ * RequestInterceptor è¯·æ±æ¦æªå¨ï¼å¯ä»¥å¨åéhttp请æ±ä¹åæ§è¡æ¤æ¦æªå¨ * feign.Contract æ¥å£ä»¥åæ¹æ³å æ°æ®è§£æå¨ 以ä¸åæ°é½å¯ä»¥èªå·±æ©å± * HardCodedTarget å®äºç®æ æ¥å£åurl * ReflectiveFeign çæå¨æä»£çç±»ï¼åºäºjdkç卿代çå®ç° * feign.InvocationHandlerFactory.Default æ¥å£æ¹æ³ç»ä¸æ¦æªå¨å建工å * FeignInvocationHandler æ¥å£ç»ä¸æ¹æ³æ¦æªå¨ * ParseHandlersByName è§£ææ¥å£æ¹æ³å æ°æ® * SynchronousMethodHandler.Factory æ¥å£æ¹æ³çæ¦æªå¨å建工å * SynchronousMethodHandler æ¥å£æ¹æ³çæ¦æªå¨ï¼çæ£æ¦æªçæ ¸å¿ï¼è¿éçæ£åèµ·http请æ±ï¼å¤çè¿åç»æ ## 1. éè¿feign.Feign.Builder为æä»¬è®¾ç½®http请æ±çç¸å ³åæ°ï¼æ¯å¦http客æ·ç«¯ï¼éè¯çç¥ï¼ç¼è§£ç ï¼è¶ æ¶æ¶é´ï¼è¿é齿¯é¢åæ¥å£ç¼ç¨å®ç°çï¼æä»¬å¾å®¹æçè¿è¡æ©å±ï¼æ¯å¦http客æ·ç«¯ï¼å¯ä»¥ä½¿ç¨javaåççå®ç°ï¼ä¹å¯ä»¥ä½¿ç¨apache httpclientï¼äº¦å¯ä»¥ä½¿ç¨okHttpClientï¼èªå·±å欢就好ï¼å ¶ä»å±æ§äº¦æ¯å¦æ¤ï¼ç±æ¤çåºfeignçè®¾è®¡å ·æé常好ç坿©å±æ§ã 2. ReflectiveFeignå é¨ä½¿ç¨äºjdkç卿代çä¸ºç®æ æ¥å£çæäºä¸ä¸ªå¨æä»£çç±»ï¼è¿éä¼çæä¸ä¸ªInvocationHandler(jdk卿代çåç)ç»ä¸çæ¹æ³æ¦æªå¨ï¼åæ¶ä¸ºæ¥å£çæ¯ä¸ªæ¹æ³çæä¸ä¸ªSynchronousMethodHandleræ¦æªå¨ï¼å¹¶è§£ææ¹æ³ä¸ç å æ°æ®ï¼çæä¸ä¸ªhttpè¯·æ±æ¨¡æ¿ã 3. å½åèµ·æ¹æ³è°ç¨çæ¶åï¼è¢«ç»ä¸çæ¹æ³æ¦æªå¨FeignInvocationHandleræ¦æªï¼åæ ¹æ®ä¸åçæ¹æ³å§æç»ä¸åçSynchronousMethodHandleræ¦æªå¨å¤çã 4. æ ¹æ®æ¯æ¬¡æ¹æ³è°ç¨çå ¥åçæhttpè¯·æ±æ¨¡æ¿ï¼å¦æè®¾ç½®äºhttpè¯·æ±æ¦æªå¨ï¼åå ç»åæ¦æªå¨çå¤çï¼ååèµ·çæ£çhttp请æ±ï¼å¾å°ç»æå伿 ¹æ®æ¹æ³æ¾å ¥è¿åå¼è¿è¡ååºååï¼æåè¿åç»è°ç¨æ¹ã 5. 妿åçäºå¼å¸¸ï¼ä¼æ ¹æ®éè¯çç¥è¿è¡éè¯ã feign乿´åäºHystrixï¼å®ç°çæé级çåè½ï¼å ¶å®ä¹å¾ç®åï¼ä¸é¢ç忿们ç¥éäºfeign卿¹æ³è°ç¨çæ¶åä¼ç»è¿ç»ä¸æ¹æ³æ¦æªå¨FeignInvocationHandlerçå¤çï¼èHystrixFeignåæ¯ä½¿ç¨äºHystrixInvocationHandler代æ¿ï¼å¨æ¹æ³è°ç¨çæ¶åè¿è¡Hystrixçå°è£ ï¼è¿ééè¦ç¹å«è¯´æä¸ï¼ * Hystrixæè¶ æ¶æ¶é´ï¼feignæ¬èº«ä¹æè¶ æ¶æ¶é´ï¼æ£å¸¸æ¥è¯´Hystrixçè¶ æ¶é´è¦å¤§äºfeignçè¶ æ¶æ¶é´ï¼å¦ææ¯å°äºçè¯ï¼Hytrixå·²ç»è¶ æ¶äºï¼feignåçå¾ å°±å·²ç»æ²¡ææä¹äºã * ååå°±æ¯feignè¶ æ¶çè¯ä¼è§¦åéè¯æä½ï¼æ¤æ¶è¦æ¯Hytrixåçè¶ æ¶å¼å¸¸è¿åäºï¼ä½è¿å¹¶ä¸ä¼åæfeignçç»§ç»æä½ï¼ä»ä¹ææå¢ï¼å设Hytrixçè¶ æ¶æ¶é´ä¸º1sï¼feign设置çè¶ æ¶æ¶é´ä¸º2sï¼èçæ£ä¸å¡æä½éè¦èæ¶3sï¼è¿æ¶Hytrixè¶ æ¶å¼å¸¸è¿åï¼èåfeignä¹ä¼åçè¶ æ¶å¼å¸¸ï¼ä½æ¯feign伿 ¹æ®è¶ æ¶çç¥ç»§ç»è¿è¡éè¯æä½ï¼å¹¶ä¸ä¼å 为Hytrixç䏿èä¸æã æä»¥Hytrixçè¶ æ¶æ¶é´ä¸è¬è¦å¤§äºfeignçæ»è¶ æ¶æ¶é´ï¼å¦è¿ä¸ªä¾åä¸è¦è®¾ç½®2 * 5(é»è®¤éè¯æ¬¡æ°4 + 1)=10sï¼å ¬å¼å°±æ¯Hytrixçè¶ æ¶é´=feignçè¶ æ¶æ¶é´ ä¹ä»¥ (feignçéè¯æ¬¡æ° + 1) ## spring-cloud-feign #### å¼å¯@EnableFeignClients注解å°åºç»æä»¬åäºä»ä¹äºæ å¢ï¼ 1. æ«æEnableFeignClients注解ä¸çé 置信æ¯ï¼æ³¨åé»è®¤çé 置类ï¼è¿ä¸ªé 置类æ¯å¯¹ææfeignclientç齿¯çæçï¼å³ä¸ºå ¨å±çé ç½®ã 2. æ«æå¸¦æ@FeignClientæ³¨è§£çæ¥å£ï¼å¹¶æ³¨åé ç½®ç±»ï¼æ¤æ¶çé 置类é对å½åfeignclientçæï¼åFeignClientFactoryBeanï¼æ¤beanå®ç°äºFactoryBeanæ¥å£ï¼æä»¬ç¥éspringæä¸¤ç§ç±»åçbean对象ï¼ä¸ç§æ¯æ®éçbeanï¼å¦ä¸ç§åæ¯å·¥åbeanï¼FactoryBeanï¼ï¼å®è¿åçå ¶å®æ¯getObjectæ¹æ³è¿åçå¯¹è±¡ï¼æ´å¤å ³äºFactoryBeançç¸å ³ä¿¡æ¯è¯·æ¥çspring宿¹ææ¡£ï¼ãgetObjectæ¹æ³å°±æ¯éæåçfeignçæ ¸å¿æ¹æ³ï¼å½springæ³¨å ¥feignclientæ¥å£æ¶ï¼getObjectæ¹æ³ä¼è¢«è°ç¨ï¼å¾å°æ¥å£ç代çç±»ã > 夿³¨ï¼å¨FeignClientæå®é 置类æ¶ï¼åè®°ä¸è¦è¢«spring容卿«æå°ï¼ä¸ç¶ä¼å¯¹å ¨å±çæã #### èªå¨å è½½é 置类 èªå¨å è½½é 置类FeignAutoConfigurationï¼FeignClientsConfigurationï¼FeignRibbonClientAutoConfigurationï¼ è¿ä¸ä¸ªç±»ä¸ºfeignæä¾äºææçé 置类ï¼é»è®¤æ åµä¸æå è½½çç±»æ åµï¼ * feign.Feign.Builder å½å¼å ¥äºHytrixå¹¶å¼å¯åæ°feign.hystrix.enabled=trueåï¼åä¼å è½½feign.hystrix.HystrixFeign.Builderï¼æ¤æ¶feignå°±å ·å¤é级çæçåè½äºã * feign.Client æ¤å®ç°ç±»çå è½½åä¸¤ç§æ åµï¼ * 使ç¨urlæ¹å¼ï¼feign.Client.Defaultï¼ä½¿ç¨javaåççæ¹å¼ï¼java.netå ï¼åèµ·http请æ±ï¼ä¹å¯ä»¥èªå·±æ©å±ã * 使ç¨nameæ¹å¼ï¼LoadBalancerFeignClientï¼éæäºribbonï¼å®ç°æå¡åç°ä¸è´è½½åè¡¡ï¼ä½æ¯çæ£åèµ·http请æ±è¿æ¯javaåççæ¹å¼ * æ¤å¤æ¯ä¸æ©å±ç¹ï¼å½æä»¬å¼å ¥ApacheHttpClientæ¶ï¼http客æ·ç«¯å°±ä¼ä½¿ç¨apacheçhttpClientï¼å½æä»¬å¼å ¥OkHttpClientæ¶ï¼http客æ·ç«¯å°±ä¼ä½¿ç¨okhttp3.OkHttpClientã * feign.Retryer é»è®¤Retryer.NEVER_RETRYï¼ä¸è¿è¡éè¯ï¼è¿éä¹å¯ä»¥èªå·±å®ç°Retryeræ¥å£å®ç°èªå·±çéè¯çç¥ï¼ä½æ¯feignå¨éæäºribbonçæ åµä¸ï¼æå¥½ä¿æé»è®¤ä¸è¿è¡éè¯ï¼å 为ribbonä¹ä¼æéè¯çç¥ï¼å¦æfeignä¹å¼å¯éè¯ï¼å®¹æäº§çæ··ä¹±ï¼å ¶å®å¨ä½çæ¬ä¸spring-cloud-feingéè¯é»è®¤å¹¶ä¸æ¯NEVER_RETRYï¼å¯è½spring-cloud-feing乿è¯å°è¿æ ·åçé®é¢ï¼æä»¥å¨Dç䏿¹æNEVER_RETRYäºã * feign.Request.Options é»è®¤è®¾ç½®è¿æ¥è¶ æ¶æ¶é´æ¯10ï¼è¯»è¶ æ¶æ¶é´æ¯60sãè¿éä¹å¯ä»¥æ´æ¹ï¼åä¸¤ç§æ åµï¼ * 使ç¨urlæ¹å¼ï¼å¿ é¡»éè¿è¿ä¸ªåæ°æ¥è®¾ç½®ï¼æçæ ``` @Configuration public class MyConfig { @Bean public Request.Options options(){ Request.Options o = new Options(1000, 1000); return o; } } ``` ç¶å卿³¨è§£ä¸@FeignClientæå®ï¼ ``` @FeignClient(name="",url="",configuration= {MyConfig.class}) ``` æ³¨ææ¤ç±»ä¸è½è¢«spring容卿«æå°ï¼å¦åä¼å¯¹å ¨å±çæãä½ ä¹å¯ä»¥éè¿æ³¨è§£@EnableFeignClientsæ¥å ¨å±æå® ``` @EnableFeignClients(defaultConfiguration=MyConfig.class) ``` * 使ç¨nameæ¹å¼ï¼æ¤æ¶å·²ç»éæäºribbonï¼å¯ä»¥ä½¿ç¨ä»¥ä¸é ç½®æ¥è®¾ç½®ï¼å¦æä½ æ¤æ¶ä¹é ç½®äºOptionsï¼ä»¥ä¸é ç½®ä¼è¢«è¦ç ``` # 对ææçfeignclientçæ ribbon.ReadTimeout=10000 ribbon.ConnectTimeout=2000 # 对æå®çfeigncliençæ [feignclientName].ribbon.ReadTimeout=10000 [feignclientName].ribbon.ConnectTimeout=2000 ``` 妿å¼å¯Hytrixï¼hytrixä¹æè¶ æ¶æ¶é´è®¾ç½®ï¼ä½æ¯hytrixæ¯å°è£ å¨feignåºç¡ä¹ä¸çï¼ä¸æå·²æåæã ``` hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000 ``` ä½ ä¹å¯ä»¥å ³éhytrixçè¶ æ¶æ¶é´ ``` hystrix.command.default.execution.timeout.enabled=false ``` * feign.codec.Decoder è§£ç å¨ï¼é»è®¤ä½¿ç¨äºHttpMessageConvertersæ¥å®ç° * feign.codec.Encoder ç¼ç å¨ï¼é»è®¤ä½¿ç¨äºHttpMessageConvertersæ¥å®ç° * feign.Contract é»è®¤æä¾springmvcçæ³¨è§£è§£æï¼æ¯æ@RequestMappingï¼@RequestBodyï¼@RequestParamï¼@PathVariable æåä¸ç§ä¹æ¯spring-cloud-feignæ¿æ¢åçfeignçé»è®¤å®ç°ï¼å¯¹springMVCçç¸å ³æ¯æ Options对象ç»è¿getClientConfig(options, clientName) æ¹æ³ï¼å°±ä»10sçè¿æ¥æ¶é´åæäº1s,60sçè¯»åæ¶é´ä¹åæäº1s,ä¸é¢æºç åæå¯ä»¥ç¥éï¼ å¦ææä»¬é ç½®äºfeignçè¶ æ¶æ¶é´ï¼é£ä¹å°±ä¼ä»¥æä»¬é ç½®çæ¶é´ä¸ºåï¼å¦ææ²¡æé ç½®ï¼é£ä¹å°±åribbonçè¶ æ¶æ¶é´ï¼2è åªè½æä¸ä¸ªçæï¼èribboné»è®¤è¶ æ¶æ¶é´æ¯1ç§ feignæè ribbonæé ç½®çè¶ æ¶æ¶é´ï¼æç»é½æ¯å¨HttpUrlConnectionä¸çæ é£ä¹ï¼æä»¬å¦ä½ä¿®æ¹feignçé ç½®æ¶é´å¢ï¼ ``` @Configuration public class Config { @Bean public Request.Options feignRequestOptions() { Request.Options options = new Request.Options(2000, TimeUnit.MILLISECONDS, 2000, TimeUnit.MILLISECONDS, true); return options; } } ``` Hystrixççææ¶é´è¦å¤§äºFeignæRibbonçconnectTimeout+readTimeout feignçè¶ æ¶æ¶é´å¦æè¦å¨application.ymlä¸é ç½®ï¼æ¹å¦ä½é ç½®å¢ï¼ ``` feign: hystrix: enabled: true client: config: default: #è¿æ¥å°ç®æ çæ¶é´ï¼æ¤å¤ä¼æ¶å°æ³¨åä¸å¿å¯å¨ä¸çå½±åã设置为3ç§éï¼å¦ææ³¨åä¸å¿æææ¾çä¸å¨çº¿ï¼åºæ¬æ¯æ¯«ç§çº§çææç» connectTimeout: 3000 #è·åç®æ è¿æ¥åæ§è¡çæé¿æ¶é´ï¼è®¾ç½®ä¸º32ç§ï¼å³æå¡æé¿æ¶ readTimeout: 32000 ``` é£ä¹æäººè¦é®äºï¼å¦æfeignåribbonåæ¶é ç½®ï¼é£ä¹ä»¥è°çä¸ºå æåæ»ç»ï¼ hystrixççææ¶é´é ç½®éè¿ymlé 置没æ³çæï¼å¯ä»¥éè¿é ç½®ç±»çæ¹æ³æ¥ä¿®æ¹ï¼feignçè¶ æ¶æ¶é´å¯ä»¥éè¿ä»£ç æè ymlé ç½®ï¼ribbonçè¶ æ¶æ¶é´å¯ä»¥éè¿ymlæ¥é ç½® feignåribbonçè¶ æ¶æ¶é´åªè½äºéä¸ï¼åªè¦feignçè¶ æ¶æ¶é´é ç½®äºï¼å°±ä»¥feignç为åï¼hystrixçè¶ æ¶æ¶é´è¦å¤§äºfeign/riboonçconnectTimeout+readTimeoutçå æåä¸å¼ 徿¥æ»ç»ï¼  ç®åçå¦ä¹ åæµè¯ç»ææ¥çï¼ å纯ç Ribbon + Hystrix æé ä½¿ç¨æ¶ï¼é ç½®æ¯æçµæ´»çï¼ä¸¤è 没æç¸äºå¹²æ¶ï¼å¯ä»¥èªç±å®ä¹ commandKey æ¥å®ç°è¶ æ¶æ¶é´çé ç½® Feign + Hystrix æé æ¶ï¼ç±äº Feign å°è£ äº Hystrix æéç commandKeyï¼æä»¬ä¸è½èªå®ä¹ï¼æä»¥åä¸ä¸ª FeignClient ä¸çæå¡æ¥å£ä¸è½æ¹ä¾¿çç»ä¸é ç½®ï¼å¦ææç¸åºçä¸å¡éæ±ï¼æè®¸åªè½å¯¹æ¯ä¸ªç¹æ®çæ¥å£æ¹æ³åç¬ç«çè¶ æ¶é ç½®ï¼æ¾å°æ°æ¹æ³çè¯ååæ¥æ´æ°ï¼ Zuul + Hystrix æé æ¶ï¼åä¸è¿°çæ åµç¸åï¼è½å¯¹ä¸åæå¡å®ä¾åä¸åçè¶ æ¶é ç½®ï¼ä½ä¸è½åç»åå°æå¡ä¸çå ·ä½æ¥å£æ¹æ³