SpringCloud OpenFeign

OpenFeign

一、OpenFeign是什么

Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。

Feign是Spring Cloud组件中一个轻量级RESTful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。

OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类

二、Spring Cloud 整合OpenFeign

  1. 添加openFeign依赖
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 启动类添加Feign客户端注解
@EnableFeignClients
public class  OpsApplication {
    public static void main(String[] args) {
        SpringApplication.run(OpsApplication.class, args);
    }
}
  1. 编写Feign调用
@FeignClient(name = "zm-teachers", path = "/teacherInfo")
public interface TeacherClient {
    
    
    
}

三、OpenFeign特性

1. 超时时间配置

通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms);第二个是请求处理的超时时间(ms)。

  • 配置类配置,全局配置
@Configuration
public class FeignConfig {
    
    
    @Bean
    public Request.Options options(){
    
    
        return new Request.Options(5000,10000);
    }
}
  • 配置类配置,局部配置
@FeignClient(name = "zm-teachers",configuration = FeignConfig.class)
public interface TeacherClient {
    
    
}

public class FeignConfig {
    
    
    @Bean
    public Request.Options options(){
    
    
        return new Request.Options(5000,10000);
    }
}
  • 配置文件配置,全局配置
#连接超时时间 单位:ms
feign.client.config.default.connectTimeout:5000
#请求处理超时时间 单位:ms
feign.client.config.default.connectTimeout:3000
  • 配置文件配置,局部配置
#连接超时时间 单位:ms
feign.client.config.zm-teachers.connectTimeout:5000
#请求处理超时时间 单位:ms
feign.client.config.zm-teachers.connectTimeout:3000

2. 日志配置

日志级别

日志等级 适用场景 内容
NONE(默认) 性能最佳,适合于生产 不产生任何日志
BASIC 适用于生产环境测试问题 记录请求方法、URL响应状态码和执行时间
HEADERS 在BASIC的基础上,记录请求和响应的header
FULL 适合开发和测试环境定位问题 记录请求和响应的header、bogy和元数据
  • 配置类配置,全局配置

    @Configuration
    public class FeignConfig {
          
          
        //日志级别
        @Bean
        public Logger.Level feignLoggerLevel(){
          
          
            return Logger.Level.FULL;
        }
    }
    
  • 配置类配置,局部配置

    @FeignClient(name = "zm-teachers",configuration = FeignConfig.class)
    public interface TeacherClient {
          
          
    }
    
    public class FeignConfig {
          
          
       //日志级别
        @Bean
        public Logger.Level feignLoggerLevel(){
          
          
            return Logger.Level.FULL;
        }
    }
    
  • 配置文件配置,全局配置

    feign.client.config.default.loggerLevel:FULL
    
  • 配置文件配置,局部配置

    feign.client.config.zm-teachers.loggerLevel:FULL
    

3. 通信组件

  • OkHttp

    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-okhttp</artifactId>
    </dependency>
    
    feign.okhttp.enabled:true
    
  • HttpClient

    <dependency>
       <groupId>io.github.openfeign</groupId>
       <artifactId>feign-httpclient</artifactId>
    </dependency>
    
    feign.httpclient.enabled:true
    

4. Gzip压缩

GET请求与POST请求的数据长度限制

理论上,GET请求和POST请求的数据长度是没有限制的,但是服务器以及浏览器会对其进行限制

  • 浏览器限制:为了兼容各个浏览器的长度请求,URL长度限制为【2083】个字符。(IE:2083、Firefox:65536、Chrome:8182)
  • 服务器限制:
    • tomecat:maxHttpHeaderSize参数
    • nginx:large_client_header_buffers参数

feign数据压缩配置

#开启feign请求压缩,默认不开始
feign.compression.reqest.enabled:true
#配置支持压缩的MIME TYPE,默认为:text/xml,application/xml,application/json
feign.compression.reqest.mime-types:text/xml,application/xml,application/json
#触发请求数据压缩的最小Size,默认2048KB
feign.compression.reqest.min-request-size: 2048

#开启Feign响应压缩,默认不开启
feign.compression.response.enabled:true
#使用GZip解码器,默认不使用
feign.compression.response.useGzipDecoder:true

数据压缩会给CPU带来负担

注,如果通信组件使用的是okhttp3,Gzip不生效

/*
 * Copyright 2013-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.cloud.openfeign.encoding;

import feign.Client;
import feign.Feign;

import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Configures the Feign response compression.
 *
 * @author Jakub Narloch
 * @see FeignAcceptGzipEncodingInterceptor
 */
@Configuration
@EnableConfigurationProperties(FeignClientEncodingProperties.class)
@ConditionalOnClass(Feign.class)
@ConditionalOnBean(Client.class)
@ConditionalOnProperty(value = "feign.compression.response.enabled", matchIfMissing = false)
//The OK HTTP client uses "transparent" compression.
//If the accept-encoding header is present it disable transparent compression
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
@AutoConfigureAfter(FeignAutoConfiguration.class)
public class FeignAcceptGzipEncodingAutoConfiguration {
    
    

	@Bean
	public FeignAcceptGzipEncodingInterceptor feignAcceptGzipEncodingInterceptor(FeignClientEncodingProperties properties) {
    
    
		return new FeignAcceptGzipEncodingInterceptor(properties);
	}
}

5. 负载均衡

负载均衡配置

zm-teachers.ribbon.NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RandomRule
zm-teachers.ribbon.ConnectTimeout: 250                 # 连接超时时间
zm-teachers.ribbon. ReadTimeout: 1000                   # ribbon 读取超时时间
zm-teachers.ribbon. OkToRetryOnAllOperations: true      # 是否对所有操作都进行重试
zm-teachers.ribbon.MaxAutoRetriesNextServer: 1         # 切换实例的重试次数
zm-teachers.ribbon.MaxAutoRetries: 1                   # 对当前实例的重试次数
负载均衡策略 说明
权重策略/WeightedResponseTimeRule 根据每个服务提供者的响应时间分配一个权重,响应时间越长、权重越小、被选中的可能性也就越低。实现原理:刚开始使用轮询策略并开启一个计时器,每隔一段时间收集一次所有服务提供的平均响应时间,然后再给每个服务提供者附上权重,权重越高,被选中的概率越大。
最小连接数策略/BestAvailableRule 也叫最小并发策略,他是遍历服务提供者列表,选取连接数最小的一个服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取。
区域敏感策略/ZoneAvoidanceRule 根据服务所在的区域的性能和服务的可用性来选择服务实例,在没有区域的环境下,改策略和轮询策略类似。
可用敏感性策略/AvailabilityFilteringRule 先过滤到非健康的服务实例,然后再选择连接数较小的服务实例
随机策略/RandomRule 从服务提供者列表中随机选择一个服务实例
重试策略/RetryRule 按照轮询策略来获取服务,如果获取的服务为null或已失效,则在指定时间内进行重试来获取服务,如果超过指定时间依然没有获取到服务实例,返回null

6. Hystrix

复杂分布式服务面临的问题:服务雪崩

解决服务雪崩的方法:降级、隔离、熔断、请求缓存、请求合并。

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

Hystrix 回调的两种方式:

  1. fallback
@FeignClient(name = "zm-biz-import-service"fallback = ImportClientHystrix.class)
public interface ImportClient {
    
    
    @RequestMapping(method = RequestMethod.POST, path = "/upload/single/file" ,produces = {
    
    MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    Result<TeacherUploadDto> uploadSingleFile(MultipartFile  param);
}

@Component
public class ImportClientHystrix implements ImportClient {
    
    

    @Override
    public Result<TeacherUploadDto> uploadSingleFile(MultipartFile param) {
    
    
        log.warn("ImportClientHystrix uploadSingleFile error ");
        return Result.error();
    }
}
  1. fallbackFactory
@FeignClient(name = "zmbiz-asset-query", fallbackFactory = AssetQueryFeignClientFallbackFactory.class)
public interface AssetQueryFeignClient {
    
    

    /**
     * @return 根据学生ID查询student_money
     * @param
     * @return
     */
    @GetMapping(value = "/api/studentMoney/queryByStuId")
    HaloResult<List<StudentMoneyDTO>> queryStudentMoneyByStuId(@RequestParam(value = "stuId") Integer stuId);
}

@Component
@Slf4j
public class AssetQueryFeignClientFallbackFactory implements FallbackFactory<AssetQueryFeignClient> {
    
    
    @Override
    public AssetQueryFeignClient create(Throwable cause) {
    
    
        return new AssetQueryFeignClient() {
    
    
            @Override
            public Result<User> addPerson(User user) {
    
    
                log.warn("调用zmbiz-user-business服务调用异常,uri = /tBsPerson/add/person, para = {}, e = {}", JSONObject.toJSONString(user), ExceptionUtils.getFullStackTrace(e));
                return Result.errorMessage("亲,服务器升级中,请稍后再试!");
            }
        };
    }
}

推荐使用fallbackFactory,可以通过打印降级的异常,查询出问题原因。

hystrix配置

feign.hystrix.enabled:true

#方案一:配置核心线程数量,以及最大线程数量

hystrix.threadpool.default.coreSize = 50
hystrix.threadpool.default.maximumSize = 100
hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize = true

#方案二:配置队列长度以及拒绝长度

hystrix.threadpool.default.maxQueueSize: 1000 #BlockingQueue的最大队列数,默认值-1
hystrix.threadpool.default.queueSizeRejectionThreshold: 800 #即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝,默认值5

OpenFeign

一、OpenFeign是什么

Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。

Feign是Spring Cloud组件中一个轻量级RESTful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。

OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类

二、Spring Cloud 整合OpenFeign

  1. 添加openFeign依赖
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 启动类添加Feign客户端注解
@EnableFeignClients
public class  OpsApplication {
    public static void main(String[] args) {
        SpringApplication.run(OpsApplication.class, args);
    }
}
  1. 编写Feign调用
@FeignClient(name = "zm-teachers", path = "/teacherInfo")
public interface TeacherClient {
    
    
    
}

三、OpenFeign特性

1. 超时时间配置

通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms);第二个是请求处理的超时时间(ms)。

  • 配置类配置,全局配置
@Configuration
public class FeignConfig {
    
    
    @Bean
    public Request.Options options(){
    
    
        return new Request.Options(5000,10000);
    }
}
  • 配置类配置,局部配置
@FeignClient(name = "zm-teachers",configuration = FeignConfig.class)
public interface TeacherClient {
    
    
}

public class FeignConfig {
    
    
    @Bean
    public Request.Options options(){
    
    
        return new Request.Options(5000,10000);
    }
}
  • 配置文件配置,全局配置
#连接超时时间 单位:ms
feign.client.config.default.connectTimeout:5000
#请求处理超时时间 单位:ms
feign.client.config.default.connectTimeout:3000
  • 配置文件配置,局部配置
#连接超时时间 单位:ms
feign.client.config.zm-teachers.connectTimeout:5000
#请求处理超时时间 单位:ms
feign.client.config.zm-teachers.connectTimeout:3000

2. 日志配置

日志级别

日志等级 适用场景 内容
NONE(默认) 性能最佳,适合于生产 不产生任何日志
BASIC 适用于生产环境测试问题 记录请求方法、URL响应状态码和执行时间
HEADERS 在BASIC的基础上,记录请求和响应的header
FULL 适合开发和测试环境定位问题 记录请求和响应的header、bogy和元数据
  • 配置类配置,全局配置

    @Configuration
    public class FeignConfig {
          
          
        //日志级别
        @Bean
        public Logger.Level feignLoggerLevel(){
          
          
            return Logger.Level.FULL;
        }
    }
    
  • 配置类配置,局部配置

    @FeignClient(name = "zm-teachers",configuration = FeignConfig.class)
    public interface TeacherClient {
          
          
    }
    
    public class FeignConfig {
          
          
       //日志级别
        @Bean
        public Logger.Level feignLoggerLevel(){
          
          
            return Logger.Level.FULL;
        }
    }
    
  • 配置文件配置,全局配置

    feign.client.config.default.loggerLevel:FULL
    
  • 配置文件配置,局部配置

    feign.client.config.zm-teachers.loggerLevel:FULL
    

3. 通信组件

  • OkHttp

    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-okhttp</artifactId>
    </dependency>
    
    feign.okhttp.enabled:true
    
  • HttpClient

    <dependency>
       <groupId>io.github.openfeign</groupId>
       <artifactId>feign-httpclient</artifactId>
    </dependency>
    
    feign.httpclient.enabled:true
    

4. Gzip压缩

GET请求与POST请求的数据长度限制

理论上,GET请求和POST请求的数据长度是没有限制的,但是服务器以及浏览器会对其进行限制

  • 浏览器限制:为了兼容各个浏览器的长度请求,URL长度限制为【2083】个字符。(IE:2083、Firefox:65536、Chrome:8182)
  • 服务器限制:
    • tomecat:maxHttpHeaderSize参数
    • nginx:large_client_header_buffers参数

feign数据压缩配置

#开启feign请求压缩,默认不开始
feign.compression.reqest.enabled:true
#配置支持压缩的MIME TYPE,默认为:text/xml,application/xml,application/json
feign.compression.reqest.mime-types:text/xml,application/xml,application/json
#触发请求数据压缩的最小Size,默认2048KB
feign.compression.reqest.min-request-size: 2048

#开启Feign响应压缩,默认不开启
feign.compression.response.enabled:true
#使用GZip解码器,默认不使用
feign.compression.response.useGzipDecoder:true

数据压缩会给CPU带来负担

注,如果通信组件使用的是okhttp3,Gzip不生效

/*
 * Copyright 2013-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.cloud.openfeign.encoding;

import feign.Client;
import feign.Feign;

import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Configures the Feign response compression.
 *
 * @author Jakub Narloch
 * @see FeignAcceptGzipEncodingInterceptor
 */
@Configuration
@EnableConfigurationProperties(FeignClientEncodingProperties.class)
@ConditionalOnClass(Feign.class)
@ConditionalOnBean(Client.class)
@ConditionalOnProperty(value = "feign.compression.response.enabled", matchIfMissing = false)
//The OK HTTP client uses "transparent" compression.
//If the accept-encoding header is present it disable transparent compression
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
@AutoConfigureAfter(FeignAutoConfiguration.class)
public class FeignAcceptGzipEncodingAutoConfiguration {
    
    

	@Bean
	public FeignAcceptGzipEncodingInterceptor feignAcceptGzipEncodingInterceptor(FeignClientEncodingProperties properties) {
    
    
		return new FeignAcceptGzipEncodingInterceptor(properties);
	}
}

5. 负载均衡

负载均衡配置

zm-teachers.ribbon.NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RandomRule
zm-teachers.ribbon.ConnectTimeout: 250                 # 连接超时时间
zm-teachers.ribbon. ReadTimeout: 1000                   # ribbon 读取超时时间
zm-teachers.ribbon. OkToRetryOnAllOperations: true      # 是否对所有操作都进行重试
zm-teachers.ribbon.MaxAutoRetriesNextServer: 1         # 切换实例的重试次数
zm-teachers.ribbon.MaxAutoRetries: 1                   # 对当前实例的重试次数
负载均衡策略 说明
权重策略/WeightedResponseTimeRule 根据每个服务提供者的响应时间分配一个权重,响应时间越长、权重越小、被选中的可能性也就越低。实现原理:刚开始使用轮询策略并开启一个计时器,每隔一段时间收集一次所有服务提供的平均响应时间,然后再给每个服务提供者附上权重,权重越高,被选中的概率越大。
最小连接数策略/BestAvailableRule 也叫最小并发策略,他是遍历服务提供者列表,选取连接数最小的一个服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取。
区域敏感策略/ZoneAvoidanceRule 根据服务所在的区域的性能和服务的可用性来选择服务实例,在没有区域的环境下,改策略和轮询策略类似。
可用敏感性策略/AvailabilityFilteringRule 先过滤到非健康的服务实例,然后再选择连接数较小的服务实例
随机策略/RandomRule 从服务提供者列表中随机选择一个服务实例
重试策略/RetryRule 按照轮询策略来获取服务,如果获取的服务为null或已失效,则在指定时间内进行重试来获取服务,如果超过指定时间依然没有获取到服务实例,返回null

6. Hystrix

复杂分布式服务面临的问题:服务雪崩

解决服务雪崩的方法:降级、隔离、熔断、请求缓存、请求合并。

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

Hystrix 回调的两种方式:

  1. fallback
@FeignClient(name = "zm-biz-import-service"fallback = ImportClientHystrix.class)
public interface ImportClient {
    
    
    @RequestMapping(method = RequestMethod.POST, path = "/upload/single/file" ,produces = {
    
    MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    Result<TeacherUploadDto> uploadSingleFile(MultipartFile  param);
}

@Component
public class ImportClientHystrix implements ImportClient {
    
    

    @Override
    public Result<TeacherUploadDto> uploadSingleFile(MultipartFile param) {
    
    
        log.warn("ImportClientHystrix uploadSingleFile error ");
        return Result.error();
    }
}
  1. fallbackFactory
@FeignClient(name = "zmbiz-asset-query", fallbackFactory = AssetQueryFeignClientFallbackFactory.class)
public interface AssetQueryFeignClient {
    
    

    /**
     * @return 根据学生ID查询student_money
     * @param
     * @return
     */
    @GetMapping(value = "/api/studentMoney/queryByStuId")
    HaloResult<List<StudentMoneyDTO>> queryStudentMoneyByStuId(@RequestParam(value = "stuId") Integer stuId);
}

@Component
@Slf4j
public class AssetQueryFeignClientFallbackFactory implements FallbackFactory<AssetQueryFeignClient> {
    
    
    @Override
    public AssetQueryFeignClient create(Throwable cause) {
    
    
        return new AssetQueryFeignClient() {
    
    
            @Override
            public Result<User> addPerson(User user) {
    
    
                log.warn("调用zmbiz-user-business服务调用异常,uri = /tBsPerson/add/person, para = {}, e = {}", JSONObject.toJSONString(user), ExceptionUtils.getFullStackTrace(e));
                return Result.errorMessage("亲,服务器升级中,请稍后再试!");
            }
        };
    }
}

推荐使用fallbackFactory,可以通过打印降级的异常,查询出问题原因。

hystrix配置

feign.hystrix.enabled:true

#方案一:配置核心线程数量,以及最大线程数量

hystrix.threadpool.default.coreSize = 50
hystrix.threadpool.default.maximumSize = 100
hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize = true

#方案二:配置队列长度以及拒绝长度

hystrix.threadpool.default.maxQueueSize: 1000 #BlockingQueue的最大队列数,默认值-1
hystrix.threadpool.default.queueSizeRejectionThreshold: 800 #即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝,默认值5

猜你喜欢

转载自blog.csdn.net/baidu_41934937/article/details/131163897