Feign是一个声明式的Web服务客户端,使用Feign可使得Web服务客户端的写入更加方便.它具有可插拔注释支持,包括Feign注解和JAX-RS注解、Feign还支持可插拔编码器和解码器、Spring Cloud增加了对Spring MVC注释的支持,并HttpMessageConverters在Spring Web中使用了默认使用的相同方式。Spring Cloud集成了Ribbon和Eureka,在使用Feign时提供负载平衡的http客户端。Fegin对Robbin进行了封装,如果需要配置自己的负载算法,可以自定义Ribbon的算法即可。 Spring Cloud Feign 提供的声明式服务绑定功能来实现对该服务接口的调用。
1.创建 一 个 Spring Boot 基础工程,对pom文件修改
UTF-8
UTF-8
1.8
Finchley.SR3
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.cloud
spring-cloud-starter-feign
1.4.6.RELEASE
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.boot
spring-boot-maven-plugin
2.application.yml
server:
port: 9012
spring:
application:
name: feign-server #服务注册到Eureka上使用的名称
eureka:
client:
serviceUrl:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/
instance:
instance-id: feign-server-9012
prefer-ip-address: true #访问路径显示IP地址
3.修改主启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.wuzz.demo"})
public class FeignApp
{
public static void main( String[] args )
{
SpringApplication.run(FeignApp.class, args);
}
}
4.负载均衡配置
@Configuration
public class ConfigBean {
// Eureka是基于REST(Representational State Transfer)服务,
// 主要以AWS云服务为支撑,提供服务发现并实现负载均衡和故障转移。
// 我们称此服务为Eureka服务。
// Eureka提供了Java客户端组件,Eureka Client,方便与服务端的交互。
// 客户端内置了基于round-robin实现的简单负载均衡。
// 在Netflix,为Eureka提供更为复杂的负载均衡方案进行封装,
// 以实现高可用,它包括基于流量、资源利用率以及请求返回状态的加权负载均衡。
/**
* Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端负载均衡算法。
Ribbon客户端组件提供一系列完善的配置项,如,连接超时,重试等。
简单的说,Ribbon是一个客户端负载均衡器,
我们可以在配置文件中列出load Balancer后面所有的机器,
Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,
我们也很容易使用Ribbon实现自定义的负载均衡算法
*
*/
// Feign是一个声明式的Web服务客户端,使用Feign可使得Web服务客户端的写入更加方便。
// 它具有可插拔注释支持,包括Feign注解和JAX-RS注解、Feign还支持可插拔编码器和解码器、
// Spring Cloud增加了对Spring MVC注释的支持,
// 并HttpMessageConverters在Spring Web中使用了默认使用的相同方式。
// Spring Cloud集成了Ribbon和Eureka,在使用Feign时提供负载平衡的http客户端。
@Bean
@LoadBalanced // ribbon是客户端 的负载均衡工具
//默认算法是轮询算法 核心组件IRule
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@Bean
public IRule myRule() { // 负载均衡算法。。。。
// return new RoundRobinRule();
return new RandomRule();
}
}
5.声明式服务类
@FeignClient(value ="cloud-provider")
public interface ClientService {
//如果feign代理的是get请求,必须用@RequestMapping 不能用@GetMapping
// 每个参数必须带上@RequestParam,否则会报post not support!
@RequestMapping(value = "/hello", method = RequestMethod.GET)
String hello(@RequestParam("id") String id) ;
}
6.controller
@RestController
public class FeignController {
@Autowired
private ClientService service;
@RequestMapping(value ="/feign/hello")
public String hello() {
return service.hello("1");
}
}
这样就配置好了。
大多数情况下,我们对于服务调用的超时时间可能会根据实际服务的特性做 一 些调整,所以仅仅依靠默认的全局配置是不行的。 在使用SpringCloud Feign的时候,针对各个服务客户端进行个性化配置的方式与使用SpringCloud Ribbon时的配置方式是 一 样的, 都采用
cloud-provider.ribbon.ConnectTimeout = 500 //请求连接的超时时间。
cloud-provider.ribbon.ReadTimeout = 2000 //请求处理的超时时间。
cloud-provider.ribbon.OkToRetryOnAllOperations = true //对所有操作请求都进行重试。
cloud-provider.ribbon.MaxAutoRetriesNextServer = 2 //切换实例的重试次数。
cloud-provider.ribbon.MaxAutoRetries = 1 //对当前实例的重试次数。
在 Spring Cloud Feign 中默认实 现了 请 求 的重 试 机 制 , 而上面我 们对 于 cloud-provider 客户端的配置内容就是对于请求超时以及重试机制配置的详情.
这里需要注意一 点, Ribbon的超时 与Hystrix的超时是两个概念。 为了让上述实现有效,我们需要 让Hystrix的超时时间大于Ribbon的超时时间, 否则Hystrix命令超时后, 该命令直接熔断, 重试机制就 没有任何意义了。
要么设置 Hystrix 的超时时间比Ribbon大(hystrix.command.default.execution.isolation.thread. timeoutInMilliseconds = 5000),要么直接关闭 Hystrix 超时配置(feign.hystrix.enabled= false).配置的时候不提示没关系,配置上就有效果。
如果不想全局关闭可以只针对服务进行关闭:@FeignClient(name="HELLO - SERVICE", configuration = DisableHystrixConfiguration.class)
在 feign-server应用中增加上文中提到的重试配置参数。其中,由于 cloud-provider.ribbon.MaxAutoRetries 设置为 1, 所以重试策略先尝试访问首选实例 一 次, 失败后才更换实例访问, 而更换实例访问的次数通过 cloud-provider.ribbon.MaxAutoRetriesNextServer 参数 设置为 2, 所以会尝试更换两次实例进行重试。
最后, 启动这些应用, 并尝试访问几次 http://localhost:9012/feign/hello 接口。可以通过 cloud-provider 服务打印请求信息,修改对应/hello接口如下
public String hello(String id) throws InterruptedException {
// 测试fegin 超时重试代码开始
List instances = client.getInstances("feign-server");
//测试超时
int sleepTime = new Random().nextInt(3000);
System.out.println("sleepTime:" + sleepTime);
Thread.sleep(sleepTime);
System.out.println("/hello, host:" + instances.get(0).getHost() +
instances.get(0).getServiceId());
// 测试fegin 超时重试代码结束
return "Hello Eureka Provider1";
}
然后控制台来查看重试的日志。
从控制台输出中,我们可以看到这次访问的第 一 次请求延迟时间为 2088毫秒,由于超时时间设置为 2000 毫秒, Feign 客户端发起了重试,第二次请求的延迟为 1338 秒,没有超时 。Feign客户端在进行服务调用时, 虽然经历了一 次失败,但是通过重试机制, 最终还是获得了请求结果。所以, 对于 重试机制的实现, 对于构建高可用的 服务集群来说非常重要, 而 SpringCloud Feign也为其提供了足够的支持。
请求压缩。Spring Cloud Feign支持对请求与响应进行 GZIP 压缩,以减少通信过程中的性能损耗 。我们只需通过下面两个参数设置, 就能开启请求与响应的压缩功能:
feign.compression.request.enabled = true
feign.compression.response.enabled = true
同时, 我们还能对请求压缩做 一 些更细致的设置, 比如下面的配置内容指定了压缩的请求数据类型, 并设置了请求压缩的大小下限, 只有超过这个大小的请求才会对其进行压缩。
feign.compression.request.enabled = true
feign.compression.request.mime-types = text/xml,application/xml,application/json //默认值
feign.compression.request.min-request-size=2048 //默认值
Spring Cloud Feign 在构建被 @FeignClient 注解修饰的服务客户端时,会为每 一 个客户端都创建 一 个 feign.Logger 实例,我们可以利用该日志对象的 DEBUG 模式来帮助分析 Feign 的请求细节。可以在 application.properties 文件中使用 logging.level.
logging.level.com.wuzz.demo.HelloService = DEBUG
但是, 只是添加了如上配置, 还无法实现对 DEBUG 日志的输出。 这时由于 Feign 客户端默认的 Logger.Level 对象定义为 NONE 级别, 该级别不会记录任何 Feign 调用过程中的信息, 所以我们需要调整它的级别, 针对全局的日志级别, 可以在应用主类中直接加入 Logger.Level 的 Bean 创建, 具体如下:
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
或者添加个配置类:
@Configuration
public class FullLogConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@FeignClient(name = "cloud-provider", configuration = FullLogConfiguration.class)
public interface HelloService {
。。。。。。
}
在调整日志级别为 FULL 之后, 我们可以再访问一 下之前的http://localhost:9012/feign/hello 接口,这时我们在 feign-server的控制台中就可以看到对应的日志。类似如下信息:
对于 Feign 的 Logger 级别主要有下面 4 类, 可根据实际需要进行调整使用。
整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开起会来。所谓降级,一般是从整体负荷考虑,就是当某个服务熔断后,服务器将不再被调用,此时客户端可以准备自己本地的一个fallback回调,返回一个缺省值,这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,服务降级是在客户端进行的.
1. 根据目标接口,创建一个实现了FallbackFactory的类
@Component
public class HystrixClientService implements FallbackFactory {
@Override
public ClientService create(Throwable throwable) {
return new ClientService() {
@Override
public String hello() {
return "服务降级。。。。";
}
};
}
}
2. 在目标接口上的@FeignClient中添加fallbackFactory属性值
@FeignClient(value ="cloud-provider", fallbackFactory = HystrixClientService.class)
public interface ClientService {
@RequestMapping(value ="/hello",method= RequestMethod.GET)
String hello() ;
}
3.修改 application.yml ,添加一下
feign:
hystrix:
enabled: true
这样就完成了服务降级的基本配置,可以进入测试。。。。