作者:翡翠雕刻师李贵 | 来源:互联网 | 2023-09-23 19:52
简介
OpenFeign
声明性REST客户端:OpenFeign
创建用JAX-RS或Spring MVC注释修饰的接口的动态实现,OpenFeign
是Netflix的一个声明性HTTP客户端,它简化了我们与其他服务交互的方式。
OpenFeign
提供了两个重要标注@FeignClient
和@EnableFeignClients
。
@FeignClient
标注用于声明Feign客户端可访问的Web服务。
@EnableFeignClients
标注用于修饰Spring Boot应用的入口类,以通知Spring Boot启动应用时,扫描应用中声明的Feign
客户端可访问的Web服务。
OpenFeign
是通过Eureka
调用的组件并做为Eureka
的Client
端一起使用,所以提前启动Eureka
服务,请看上一篇博客
提供者
- 跟我们之前构建项目一样, 使用
idea
工具直接创建一个新的SpringBoot
项目,在选择依赖的界面勾选Cloud Discovert -> OpenFeign
依赖,创建完成后的pom.xml
配置文件内容如下:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
- 在主启动类上添加
OpenFeign
的注解@EnableEurekaClient
,如下所示:
@EnableEurekaClient
@SpringBootApplication
public class EurekaClientOneApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientOneApplication.class, args);
}
}
@RestController
public class TestEurekaController {
@GetMapping("/test/eureka")
public String aaa() {
return "hello world!";
}
}
server:
port: 8081
spring:
application:
name: client-one
main:
allow-bean-definition-overriding: true
eureka:
instance:
hostname: localhost
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 10
client:
service-url:
defaultZone: http://localhost:8080/eureka
调用者
新建项目和依赖同上
- 在主启动类上添加
OpenFeign
的注解@EnableFeignClients
,如下所示:
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OpenFeignClientApplication {
public static void main(String[] args) {
SpringApplication.run(OpenFeignClientApplication.class, args);
}
}
- 新建一个接口,通过
FeignClient
调用接口,FeignClient
参数值为Eureka
注册中心的Application Name
,@GetMapping
是请求服务接口地址。代码和图如下:
@FeignClient("CLIENT-ONE")
public interface RpcService {
//这里调用无参方法,如果是有参数把提供者暴露接口方法复制过来,把mapping换成完整路径
@GetMapping("/test/eureka")
String getRpc();
}
server:
port: 8082
spring:
application:
name: client-two
main:
allow-bean-definition-overriding: true
eureka:
instance:
hostname: localhost
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 10
client:
service-url:
defaultZone: http://localhost:8080/eureka
运行测试
新建一个Controller代码如下:
@RestController
public class CityController {
@Autowired
private RpcService rpcService;
@GetMapping("/cities")
public String listCity(){
String body = rpcService.getRpc();
return body;
}
}
在浏览器访问:localhost:8080/cities
得到数据就是Feign
调用接口返回数据
加强配置
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 3000
CLIENT-ONE:
readTimeout: 5000
connectTimeout: 3000
CLIENT-ONE:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
自定义路由策略
定义:CustomRuleBalancer类并实现IRule接口。
功能:传递一组端口,从服务列表中删除这些端口对应服务,对剩余服务进行随机访问。
注解入Bean:
@Bean
public IRule loadBalancer(){
return new CustomRuleBalancer(Collections.singletonList(8080));
}
代码:
public class CustomRuleBalancer implements IRule {
private ILoadBalancer lb;
private List<Integer> excludePorts;
public CustomRuleBalancer() {
}
CustomRuleBalancer(List<Integer> excludePorts) {
this.excludePorts = excludePorts;
}
@Override
public Server choose(Object o) {
List<Server> servers = lb.getReachableServers();
List<Server> availableServers = getAvailableServers(servers);
return getAvailableRandomServers(availableServers);
}
private List<Server> getAvailableServers(List<Server> servers) {
if (CollectionUtils.isEmpty(excludePorts)) {
return servers;
}
return servers.stream()
.filter(f -> !excludePorts.contains(f.getPort()))
.collect(Collectors.toList());
}
private Server getAvailableRandomServers(List<Server> availableServers) {
int index = new Random().nextInt(availableServers.size());
return availableServers.get(index);
}
@Override
public void setLoadBalancer(ILoadBalancer iLoadBalancer) {
this.lb = iLoadBalancer;
}
@Override
public ILoadBalancer getLoadBalancer() {
return lb;
}
}