Spring Cloud之—— OpenFeign(服务间调用)

简介

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调用的组件并做为EurekaClient端一起使用,所以提前启动Eureka 服务,请看上一篇博客

提供者

  • 跟我们之前构建项目一样, 使用idea工具直接创建一个新的SpringBoot项目,在选择依赖的界面勾选Cloud Discovert -> OpenFeign依赖,创建完成后的pom.xml配置文件内容如下:
		<!--OpenFeign做为Eureka组件的Client端,必须依赖Eureka-client-->
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
	
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  • 在主启动类上添加OpenFeign的注解@EnableEurekaClient,如下所示:
@EnableEurekaClient
@SpringBootApplication
public class EurekaClientOneApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientOneApplication.class, args);
    }
}
  • controller接口如下所示:
@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
    #心跳间隔5s,默认30s。每一个服务配置后,心跳间隔和心跳超时时间会被保存在server端,不同服务的心跳频率可能不同,server端会根据保存的配置来分别探活
    lease-renewal-interval-in-seconds: 5
    #心跳超时时间10s,默认90s。从client端最后一次发出心跳后,达到这个时间没有再次发出心跳,表示服务不可用,将它的实例从注册中心移除
    lease-expiration-duration-in-seconds: 10

  client:
    ##不向注册中心注册自己
#    register-with-eureka: false
    ##取消检索服务
#    fetch-registry: false
    ##注册中心路径,如果有多个eureka server,在这里需要配置其他eureka server的地址,用","进行区分,如"http://address:8888/eureka,http://address:8887/eureka"
    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
    #心跳间隔5s,默认30s。每一个服务配置后,心跳间隔和心跳超时时间会被保存在server端,不同服务的心跳频率可能不同,server端会根据保存的配置来分别探活
    lease-renewal-interval-in-seconds: 5
    #心跳超时时间10s,默认90s。从client端最后一次发出心跳后,达到这个时间没有再次发出心跳,表示服务不可用,将它的实例从注册中心移除
    lease-expiration-duration-in-seconds: 10

  client:
    ##不向注册中心注册自己
    #    register-with-eureka: false
    ##取消检索服务
    #    fetch-registry: false
    ##注册中心路径,如果有多个eureka server,在这里需要配置其他eureka server的地址,用","进行区分,如"http://address:8888/eureka,http://address:8887/eureka"
    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:
        # 连接超时,Feign客户端连接提供者的超时阈值
        connectTimeout: 5000
        # 读超时,从Feign客户端请求发出到接收到提供者响应,这段时间超时阈值
        readTimeout: 3000
      # 设置指定某个服务超时阈值,其优先级要高于全局
      CLIENT-ONE: # 服务名称:spring.application.name
        # readTimeout和connectTimeout需要同时配置,否则不生效
        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) {
        //所有可用的servers
        List<Server> servers = lb.getReachableServers();

        //过滤server
        List<Server> availableServers = getAvailableServers(servers);
        return getAvailableRandomServers(availableServers);
    }

    /**
     * 从所有servers中获得排队端口以外的servers
     *
     * @param servers
     * @return
     */
    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());
    }

    /**
     * 从servers中随机一个
     *
     * @param availableServers
     * @return
     */
    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;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值