Feign快速入门
由于使用feign进行服务调用是要使用到注册中心的,所以可以直接在之前的eureka服务中新建一个feign-client的module。
1、导包
//1、引入eureka依赖时因为里面带有loadbalancer的依赖,也可以直接引入loadbalancer,但如果是
//直接引入loadbalancer的话,还得重新引入服务发现的依赖,否则服务不能注册,那么服务就不能发现
其他服务
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-loadbalancer</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
//2、熔断器依赖,这里配合feign顺带使用熔断机制
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
//3、web包带有tomcat容器,不引入会无法启动
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1、不引入loadbalancer的依赖
No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?
原理:
SpringCloud Feign在Hoxton.M2 RELEASED版本之后不再使用ribbon
而是使用spring-cloud-loadbalancer,所以在不引入spring-cloud-loadbalancer情况下会报错
我使用的版本是2021版,那么Hoxton.M2 RELEASED应该是无需引入的
3、不引入web依赖
For 'eureka-client' URL not provided. Will try picking an instance via load-balancing.
2023-03-02 11:39:17.239 WARN 60180 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2023-03-02 11:39:17.240 INFO 60180 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2023-03-02 11:39:17.243 WARN 60180 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2023-03-02 11:39:17.243 INFO 60180 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2023-03-02 11:39:17.722 WARN 60180 --- [ main] iguration$LoadBalancerCaffeineWarnLogger : Spring Cloud LoadBalancer is currently working with the default cache. While this cache implementation is useful for development and tests, it's recommended to use Caffeine cache in production.You can switch to using Caffeine cache, by adding it and org.springframework.cache.caffeine.CaffeineCacheManager to the classpath.
2023-03-02 11:39:17.780 INFO 60180 --- [ main] c.e.feignclient.FeignClientApplication : Started FeignClientApplication in 2.559 seconds (JVM running for 3.652)
2023-03-02 11:39:17.795 WARN 60180 --- [ionShutdownHook] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2023-03-02 11:39:17.795 INFO 60180 --- [ionShutdownHook] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2、写配置
server:
port: 8086
eureka:
instance:
hostname: localhost
//注册地址其实随便写一个之前的注册中心的就行
client:
service-url:
defaultZone: http://jq1:8083/eureka/,http://jq2:8084/eureka/
spring:
application:
name: feign-client
在·启动类上加上注解
@EnableDiscoveryClient
@EnableFeignClients
3、测试
1、写一个feignclient调用之前的eurekaclient服务
package com.example.feignclient.feignclient;
import com.example.feignclient.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
//FeignClient注解标识这是个feign调用端,name是要调用的服务的服务名,
//fallback为发生熔断后要调用的熔断方法
@FeignClient(name = "eureka-client",fallback = EurekaClient.EurekaClientFallback.class)
public interface EurekaClient {
//这里修改了一下,注解修改了
@PostMapping("/v1/hello")
String hello(@RequestParam String name);
@PostMapping("/v1/hellouser")
String hellouser(@RequestBody User user);
@Component
class EurekaClientFallback implements EurekaClient {
@Override
public String hello(String name) {
return "hello方法异常";
}
@Override
public String hellouser(User user) {
return "hellouser方法异常";
}
}
}
2、控制器
package com.example.feignclient.controller;
import com.example.feignclient.feignclient.EurekaClient;
import com.example.feignclient.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/feign")
public class hellocontroller {
@Qualifier("com.example.feignclient.feignclient.EurekaClient")
@Autowired
1、bug1
//@Resource
private EurekaClient eurekaClient;
@PostMapping("/hello")
public String hello() {
String s = eurekaClient.hello("lly");
return s;
}
@PostMapping("/hellouser")
public String hellouser(){
User user = new User();
user.setId("1");
user.setName("world");
String s = eurekaClient.hellouser(user);
return s;
}
}
bug1:
使用@Resource注解时,可能会出问题
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'xxxx' could not be injected as a xxxx' because it is a JDK dynamic proxy that implements:
Action:
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.
Process finished with ex 类it code 1
-----------------------
出问题就使用
@Qualifier("com.example.feignclient.feignclient.EurekaClient")
@Autowired
双注解注入好了
运行结果:
由于启动了两个客户端,所以feign在请求eureka的时候,会根据服务名称请求到不同的端口,由此输出的
端口号会在两者之间改变
搭配hystrix实现熔断机制
1、导包
在上面已经引入了hystrix的依赖,hystrix的版本也要和使用的cloud版本适配,否则熔断会不生效。
比如我使用了2021版本的cloud,但搭配了1.x的hystrix,测试时熔断机制失效。
2、写配置
在配置文件加上以下配置,表示开启熔断机制,feign本身就支持hystrix,但没有开启,默认是false
feign:
circuitbreaker:
enabled: true
在启动类上加上注解
@EnableHystrix
内置了一个
@EnableCircuitBreaker注解
Spring Cloud 2020之前的版本版本使用的配置和注解是:
feign.hystrix.enabled=true
和
@EnableCircuitBreaker
但对于之后的版本来说已过期,配置信息也不能被识别
3、测试
关掉eureka的两个客户端
测试:
测试结果显示,会调用在EurekaClient 上配置的fallback 指定的类里对应的方法。
没有熔断机制,则会报500
也可以服务提供端设置休眠时间,模拟调用服务超时现象,默认超过2000ms超时。
@PostMapping("/hello")
public String hello(@RequestParam String name) throws InterruptedException {
int sleepTime = new Random().nextInt(4000);
System.out.println("sleepTime:"+ sleepTime);
Thread.sleep(sleepTime);
String str = "hello " + name + ",this service port is:" + port;
return str;
}
feign的重试机制
以上模拟服务超时设置休眠时间为2秒钟对于重试机制来说是不合理的,为了测试重试机制,现将使用熔断机制的配置信息注释掉
feign:
circuitbreaker:
enabled: false
查看源码发现
FeignClient的默认超时时间为10s,不会开启重试机制,需要自定义配置。
public interface Retryer extends Cloneable {
Retryer NEVER_RETRY = new Retryer() {
public void continueOrPropagate(RetryableException e) {
throw e;
}
public Retryer clone() {
return this;
}
};
自定义重试配置
//超时时间设置,开启重试机制,默认为5次(包含首次请求)
package com.example.feignclient.config;
import feign.Request;
import feign.Retryer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfigure {
//自定义重试次数
@Bean
public Retryer feignRetryer(){
Retryer retryer = new Retryer.Default(100, 1000, 5);
return retryer;
}
}
period:周期,重试间隔时间
maxPeriod:最大周期,重试间隔时间按照一定的规则逐渐增大,但不能超过最大周期
maxAttempts:最大尝试次数,重试次数
以上配置信息为:最大重试次数5此,0.1s一个周期。
在EurekaClient上加上此配置类:
@FeignClient(name = "eureka-client",configuration = FeignConfigure.class,fallback = EurekaClient.EurekaClientFallback.class)
public interface EurekaClient {
在服务的提供方加入休眠时间,模拟超时,由于feign对超时时间有定义
public Options() {
//10秒是tcp握手过程最大耗时,60秒是等待服务器处理返回的结果的最大时间
this(10L, TimeUnit.SECONDS, 60L, TimeUnit.SECONDS, true);
}
所以可以在服务提供方出加入休眠时间为60s的代码
Thread.sleep(60000);
调用服务可以看到会在两个端口的服务进行调用。且重试5次,耗时5分钟。
返回结果
也可以修改默认的超时时间,就不用休眠60s那么久了,但为了不和ribbon的配置冲突(或者可能是不生效的问题),但feign的配置会覆盖ribbon的。
feign:
circuitbreaker:
enabled: false
client:
config:
default:
ConnectTimeout: 1000 #毫秒 连接超时时间
ReadTimeout: 2000 #毫秒 逻辑处理超时时间
feign重试配合熔断机制
打开熔断机制
feign:
circuitbreaker:
enabled: true
但由于hystrix的超时时间只有2s,所以为了不因连接超时导致直接熔断,需要配置熔断的超时时间。
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 60000
让Hystrix的超时时间大于Feign的超时时间, 否则Hystrix命令超时后, 该命令直接熔断, 重试机制就
没有任何意义了。
Spring Cloud Feign还支持对请求与响应进行 GZIP压缩,以减少通信过程中的性能损耗。
通过下面两个参数设置, 就能开启请求与响应的压缩功能:
feign:
compression:
request:
enabled: true
response:
enabled: true
还有其他功能就不介绍了,只是基础入门而已