SpringCloud : 多個 @FeignClient 註解 value 設置爲同一個應用的解決方案

Feign 版本10.1.0java

Spring 版本 5.1.5.RELEASEspring

SpringBoot 版本 2.1.5.RELEASEjson

SpringCloud 版本 2.1.1.RELEASE架構

 

在微服務架構中,當咱們須要進行服務間調用時能夠選擇feign組件,app

如今遇到的問題是: 當同一個服務,聲明多個feign實例時,啓動時直接報錯。微服務

 

解決辦法,經過 Feign.builder() 手動生成代理類。ui

1.定義接口:this

 

public interface AbcClient{ @ResponseBody @PostMapping("/abc") JSONObject doSomething(@RequestBody Req request); } public interface DefClient{ @ResponseBody @PostMapping("/def") JSONObject doSomething(@RequestBody Req request); }

 

 

2.配置接口代理編碼

import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClient; import com.yunplus.bpg.cloud.file.proxy.client.QcloudClient; import com.yunplus.bpg.cloud.file.proxy.client.TaskClient; import feign.Contract; import feign.Feign; import feign.codec.Decoder; import feign.codec.Encoder; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.cloud.openfeign.FeignContext; import org.springframework.cloud.openfeign.support.SpringDecoder; import org.springframework.cloud.openfeign.support.SpringEncoder; import org.springframework.http.MediaType;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; /** * Feign配置類,負責實例化所須要的僞客戶端 */ @Component public class RemoteXxxClient { public final static String SERVICE_ID = "XXX-SERVICE-ID"; /** * FeignClientFactoryBean 該工廠類中 設置builder屬性時就是經過該對象,源碼中可看到 */protected FeignContext feignContext; /** * 經過注入Eureka實例對象,就不用手動指定url,只須要指定服務名便可 */protected EurekaClient eurekaClient; private static final Map<String, Object> FEIGN_CLIENTS = new ConcurrentHashMap<>(); @Autowired public void init(final EurekaClient eurekaClient, final FeignContext feignContext) { this.eurekaClient = eurekaClient; this.feignContext = feignContext; }
@Bean
public AbcClient getQcloudService() { return create(AbcClient.class, SERVICE_ID); }
@Bean
public DefClient getTaskService() { return create(DefClient.class, SERVICE_ID); } /** * 設置編碼解碼器爲FastJson * * @param clazz * @param serverId * @param <T> * @return */ protected <T> T create(Class<T> clazz, String serverId) { InstanceInfo nextServerFromEureka = eurekaClient.getNextServerFromEureka(serverId, false); Object object = FEIGN_CLIENTS.get(nextServerFromEureka.getIPAddr()); if (Objects.isNull(object)) { object = Feign.builder() //encoder指定對象編碼方式 .encoder(this.feignEncoder()) //decoder指定對象解碼方式 .decoder(this.feignDecoder()) .client(feignClient) //options方法指定鏈接超時時長及響應超時時長 .options(new Request.Options(5000, 5000)) //retryer方法指定重試策略 //.retryer(new Retryer.Default(5000, 5000, 3)) .contract(feignContext.getInstance(serverId, Contract.class)) //target方法綁定接口與服務端地址。返回類型爲綁定的接口類型。 .target(clazz, nextServerFromEureka.getHomePageUrl()); FEIGN_CLIENTS.put(nextServerFromEureka.getIPAddr(), object); } return (T) object; } protected Encoder feignEncoder() { return new SpringEncoder(feignHttpMessageConverter()); } protected Decoder feignDecoder() { return new SpringDecoder(feignHttpMessageConverter()); } /** * 設置解碼器爲fastjson * * @return */ private ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() { final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter()); return () -> httpMessageConverters; } private FastJsonHttpMessageConverter getFastJsonConverter() { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); List<MediaType> supportedMediaTypes = new ArrayList<>(); MediaType mediaTypeJson = MediaType.valueOf(MediaType.APPLICATION_JSON_UTF8_VALUE); supportedMediaTypes.add(mediaTypeJson); converter.setSupportedMediaTypes(supportedMediaTypes); FastJsonConfig config = new FastJsonConfig(); config.getSerializeConfig().put(JSON.class, new SwaggerJsonSerializer()); config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect); converter.setFastJsonConfig(config); return converter; } }

 

3.調用url

@Slf4j @Service public class MyLogic { @Autowired private AbcClient abcClient; public void callDownstreamService() { Req req = new Req(); JSONObject rsp = abcClient.doSomething(req); } }

 

PS:

feign 同一個服務編寫多個遠程調用實例 解決辦法

@FeignClient同一個name使用多個配置類的解決方案

相關文章
相關標籤/搜索