使用篇 第一章 Feign在项目中如何使用

前言
1、http调用
2、整合ribbon
3、整合hystrix
4、interceptor
5、使用线程池对http调用
6、http装换https
Feign可以在同一个注册中心实现服务与服务之间的调用,当然也可以在不同的注册中心实现接口调用,整合Ribbon做负载均衡,整合hystrix做容错处理,通过Interceptor支持,可以传递信息
谈谈feign在项目中如何使用
第一步: 添加依赖

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

第二步: 开启注解扫描

@EnableFeignClients({
    "com.xx.cloud.feign"
})

第三步:写代码

@FeignClient(name = "${xx.xx.serviceId}")
public interface FeignDeviceClinet {
    @RequestMapping(value = "${xx.xx.register}", method = RequestMethod.POST)
    public ObjectRestResponse<Boolean> postRegister(ClifeDeviceRegisterBean entiry);

分析: 上述可以实现http调用但是当服务出现问题,导致调用失败,我们应该对他实现容错处理(hystrix)

Hystrix
第一步: 引入依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

第二步:写application.yml

feign:
  eureka:
    enabled: true
  hystrix:
    enabled: true

第三步:写代码

@FeignClient(name = "${xx.xx.serviceId}", fallbackFactory = FeignDeviceClinetFailBackFactory.class)
public interface FeignDeviceClinet {
    @RequestMapping(value = "${xx.xx.register}", method = RequestMethod.POST)
    public ObjectRestResponse<Boolean> postRegister(ClifeDeviceRegisterBean entiry);

配置服务容错 官方提供了几种容错的现实,下面我们重点介绍下面这种实现,他可以捕获到异常、还可以接口做处理。

public class FeignDeviceClinetFailBackFactory implements  FallbackFactory<FeignDeviceClinet>{
	private final static Logger logger = LoggerFactory.getLogger(FeignDeviceClinetFailBackFactory.class);
	@Override
	public FeignDeviceClinet create(Throwable e) {
		if(e!=null && e.getStackTrace()!=null && e.getMessage()!=null)
		{
			logger.error(String.format("错误信息: %s",e.getMessage()));
		}
		return new FeignDeviceClinetFailBack() {
			
			@Override
			public ObjectRestResponse<Boolean> postRegister(ClifeDeviceRegisterBean entiry) {
				ObjectRestResponse<Boolean> result = new ObjectRestResponse<>().data(false);
				result.setStatus(404);
				return result; 
			}
		}
	}
}			

如果服务注册到注册中心上,客户端如何做负载均衡,因此ribbon从此诞生。注册中心可以eureka、nacos etc.
Ribbon
第一步:整合依赖

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

第二步:application.yml

ribbon:
  eureka:
    enabled: true
  ReadTimeout: 60000
  ConnectTimeout: 60000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 1
  OkToRetryOnAllOperations: false
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

Interceptor
在分布式环境下面,服务于服务之间传递参数、或者在请求头添加参数。下面介绍feign拦截器。
第一步:添加配置configuration

@FeignClient(name = "${xx.xx.serviceId}", fallbackFactory = FeignDeviceClinetFailBackFactory.class,
 configuration = FeignDeviceInterceptor.class)
public interface FeignDeviceClinet {
    @RequestMapping(value = "${xx.xx.register}", method = RequestMethod.POST)
    public ObjectRestResponse<Boolean> postRegister(ClifeDeviceRegisterBean entiry);

第二步:写代码

@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class FeignDeviceInterceptor implements RequestInterceptor {

  private final BeanFactory beanFactory;

  public Date getUtTC() {
    Calendar calendars = Calendar.getInstance();
    int offset = calendars.get(Calendar.ZONE_OFFSET);
    calendars.add(Calendar.MILLISECOND, -offset);
    Date time = calendars.getTime();
    return time;
  }

  private Map<String, Object> commonHeaders() {
    Map<String, Object> params = new ConcurrentHashMap<String, Object>();
    params.put("appId", ParamContant.systemId);
    params.put("appVersion", ParamContant.appVersion);
    params.put("clientId", UUID.randomUUID().toString().replace("-", ""));
    params.put("sequenceId", UUID.randomUUID().toString().replace("-", ""));
    long time = getUtTC().getTime();
    params.put("timestamp", time);
    params.put("Content-Type", ParamContant.contentType);
    params.put("timezone", 8);
    params.put("language", ParamContant.language);
    HaierService bean = beanFactory.getBean(HaierService.class);
    params.put("accessToken", bean.getToken());
    return params;
  }

   public Map<String, Object> requestHeaders() {
    // 第一步: 封装公共头
    Map<String, Object> commonHeaders = commonHeaders();
    // 第二步: 封装key
    log.info("appId = {}, appKey = {}, timestamp = {}, code = {}, httpUrl = {}", ParamContant.appId,
        ParamContant.systemKey,
        commonHeaders.get("timestamp"),
        DataMap.getValue("code"),
        ParamContant.httpUrl
    );
    JSONObject vo = new JSONObject();
    vo.put("code", DataMap.getValue("code").trim());
    String sign = CommonUtils.getSign(ParamContant.systemId,
        ParamContant.appKey,
        String.valueOf(commonHeaders.get("timestamp")),
        vo.toJSONString(),
        ParamContant.httpUrl);
    // 第三步: 存入sign
    commonHeaders.put("sign", sign);
    // 第四步: 发送Http请求
    return commonHeaders;
  }

  @Override
  public void apply(RequestTemplate requestTemplate) {
    Map<String, Object> objectMap = requestHeaders();
    log.info("interceptor send Haier Cloud params = {}", JSONObject.toJSONString(objectMap));
    objectMap.forEach((key, value) -> {
      if (value instanceof Integer || value instanceof Long) {
        requestTemplate.header(key, String.valueOf(value));
      } else {
        requestTemplate.header(key, (String) value);
      }

    });
  }

线程池
feign底层实现没有使用线程池,那么接下来我们引入线程池 (httpclient, okHttp etc)。

第一步:添加依赖

 <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.7</version>
 </dependency>

第二步:写配置文件

feign:
  eureka:
    enabled: true
  httpclient:
    enabled: true
  hystrix:
    enabled: true
  okhttp:
    enabled: true
  compression:
    request:
      enabled: true
      mime-types: text/xml,application/xml,application/json
      min-request-size: 2048
    response:
      enabled: true

Https
在实际项目中可能需要服务支持https调用,下面介绍对https的支持

@Configuration
public class FeignConfig {

  /**
   * 将feign http 转换为https调用
   * @param cachingFactory
   * @param clientFactory
   * @return
   * @throws NoSuchAlgorithmException
   * @throws KeyManagementException
   */
  @Bean
  @ConditionalOnMissingBean
  public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
                            SpringClientFactory clientFactory) throws NoSuchAlgorithmException, KeyManagementException {
    //添加https支持
    SSLContext ctx = SSLContext.getInstance("SSL");
    X509TrustManager tm = new X509TrustManager() {
      @Override
      public void checkClientTrusted(X509Certificate[] chain,
                                     String authType) throws CertificateException {
      }
      @Override
      public void checkServerTrusted(X509Certificate[] chain,
                                     String authType) throws CertificateException {
      }
      @Override
      public X509Certificate[] getAcceptedIssuers() {
        return null;
      }
    };
    ctx.init(null, new TrustManager[]{tm}, null);
    return new LoadBalancerFeignClient(new Client.Default(ctx.getSocketFactory(),
        new HostnameVerifier() {
          @Override
          public boolean verify(String hostname, SSLSession session) {
            // TODO Auto-generated method stub
            return true;
          }
        }) ,
        cachingFactory, clientFactory);
  }
}

推荐配置

feign:
  eureka:
    enabled: true
  httpclient:
    enabled: true
  hystrix:
    enabled: true
  okhttp:
    enabled: true
  compression:
    request:
      enabled: true
      mime-types: text/xml,application/xml,application/json
      min-request-size: 2048
    response:
      enabled: true
ribbon:
  eureka:
    enabled: true
  ReadTimeout: 60000
  ConnectTimeout: 60000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 1
  OkToRetryOnAllOperations: false
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
hystrix:
  threadpool:
    default:
      coreSize: 2 ##并发执行的最大线程数,默认10
      maxQueueSize: 10 ##BlockingQueue的最大队列数
      queueSizeRejectionThreshold: 5 ##即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 15000
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值