springcloud之feign远程调用

feign 简介

feignnetflix 开发的声明式、模板化的 http 客户端,它使得 http 请求变得更简单,feign 底层的使用的 http 通信框架是 HttpClientfeign 默认集成了 ribbon,并和 Eureka 结合实现了负载均衡。feign 被广泛应用在 springcloud 的解决方案中,是学习基于 springcloud 微服务架构不可或缺的重要组件

官方 githubhttps://github.com/OpenFeign/feign

feign 实现远程调用

上一篇 文章中,已经实现了 ribbon 的客户端负载均衡,虽然使用 RestTemplate 也可以实现服务之间的调用,但是它不够理想化,不够规范化,标准化。所以,本篇将使用 feign 实现服务之间的调用

项目结构依然使用上一篇文章的项目,稍加改动就可实现

Maven 主要依赖

eureka-client-consumer 消费方添加如下依赖

<!--springcloud feign-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

application.properties 配置文件

eureka-client-producer 服务提供方

server.port=8080

#注册进eureka的名称
spring.application.name=eureka-client-producer

#JDBC 配置
spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/shiro?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC
spring.datasource.druid.username=root
spring.datasource.druid.password=123456
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

#druid 连接池配置
spring.datasource.druid.initial-size=3
spring.datasource.druid.min-idle=3
spring.datasource.druid.max-active=10
spring.datasource.druid.max-wait=60000

#指定 mapper 文件路径
mybatis.mapper-locations=classpath:org/example/mapper/*.xml
mybatis.configuration.cache-enabled=true
#开启驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true
#打印 SQL 语句
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

eureka.client.service-url.defaultZone=http://eureka7001:8761/eureka/
eureka.instance.prefer-ip-address=true

`eureka-client-consumer`` 服务提供方

server.port=8090

#注册进eureka的名称
spring.application.name=eureka-client-consumer

eureka.client.service-url.defaultZone=http://eureka7001:8761/eureka/
eureka.instance.prefer-ip-address=true

eureka-client-consumer 提供方主要代码

eureka-client-producer 服务提供方的代码,与上一篇文章的一致,保持不变

项目结构如下

在这里插入图片描述

feign 远程调用的接口

如上一样,创建包名 feign,用来实现远程调用。一定要标注注解 @FeignClient

@FeignClient(name = "eureka-client-producer", fallback = UserConsumerFeignFallback.class)
public interface UserConsumerFeign {
    
    

    @GetMapping(path = "/user/selectUserById")
    ResultVo selectUserById(@RequestParam(name = "id") Integer id);
}
  • @FeignClient 注解被 @Target(ElementType.TYPE) 修饰,表示 FeignClient 注解的作用在目标接口上
  • name:指定 FeignClient 的名称,name 属性就是注册进 eureka 的服务名称,用于服务发现
  • fallback:定义降级的处理类,当调用远程接口失败或超时时,会调用对应接口的降级逻辑,fallback 指定的类必须实现 @FeignClient 标记的接口

此处关于传递参数详情,可参考文章:https://blog.csdn.net/uotail/article/details/84673347

feign 服务降级的实现类

@Component
public class UserConsumerFeignFallback implements UserConsumerFeign {
    
    

    @Override
    public ResultVo selectUserById(Integer id) {
    
    
        ResultVo resultVo = new ResultVo();
        resultVo.setId(id);
        resultVo.setUsername("feign远程调用时,失败或超时");
        resultVo.setNickname("feign远程调用时,失败或超时");
        return resultVo;
    }
}

service

@Slf4j
@Service
public class UserConsumerServiceImpl implements UserConsumerService {
    
    

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UserConsumerFeign userConsumerFeign;

    /**
     * ribbon 实现负载均衡
     */
    @Override
    public ResultVo findOneById(Integer id) {
    
    
        // eureka-client-producer:是生产者端服务名称
        ResponseEntity<ResultVo> responseEntity = restTemplate.getForEntity("http://eureka-client-producer/user/selectUserById?id=" + id, ResultVo.class);
        ResultVo resultVo = responseEntity.getBody();
        assert resultVo != null;
        log.info("resultVo为:" + resultVo.toString());
        log.info("调用服务提供方的端口为:" + resultVo.getPort());
        return resultVo;
    }

    /**
     * feign 进行远程调用
     */
    @Override
    public ResultVo queryOneById(Integer id) {
    
    
        ResultVo resultVo = userConsumerFeign.selectUserById(id);
        log.info("resultVo为:" + resultVo.toString());
        log.info("调用服务提供方的端口为:" + resultVo.getPort());
        return resultVo;
    }
}

controller

@Slf4j
@Controller
@RequestMapping(path = "/UserConsumer")
public class UserConsumerController {
    
    

    @Autowired
    private UserConsumerService userConsumerService;

    /**
     * ribbon 实现负载均衡
     */
    @GetMapping(path = "/findOneById")
    @ResponseBody
    public ResultVo findOneById(Integer id) {
    
    
        return userConsumerService.findOneById(id);
    }

    /**
     * feign 进行远程调用
     */
    @GetMapping(path = "/queryOneById")
    @ResponseBody
    public ResultVo queryOneById(@RequestParam(name = "id") Integer id) {
    
    
        return userConsumerService.queryOneById(id);
    }
}

config 配置类

@Configuration
public class UserConsumerConfig {
    
    

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
    
    
        return new RestTemplate();
    }
}

启动类

注意:@EnableFeignClients 一定要标注

@EnableFeignClients
@EnableEurekaClient
@Slf4j
@SpringBootApplication
public class AppConsumer {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(AppConsumer.class, args);
        log.info("------AppConsumer Running------");
    }
}

测试

测试 feign 远程调用中的负载均衡

同样,分别启动 eureka-server-oneeureka-client-producereureka-client-consumer3 个服务,其中服务提供方 eureka-client-producer 分别以端口 8080,8070 启动两个实例,用于测试负载均衡

在这里插入图片描述
注意 http://127.0.0.1:8090/UserConsumer/queryOneById?id=1 是使用 feign 进行远程调用的接口,使用 postman 来发送 9 次请求,查看控制台日志,如下

在这里插入图片描述
这也就印证了:feign 默认集成了 ribbon 并和 eureka 结合,实现了负载均衡

测试 feign 远程调用中的 hystrix 服务降级

eureka-client-consumer 消费方的 application.properties 配置文件添加配置

server.port=8090

#注册进eureka的名称
spring.application.name=eureka-client-consumer

eureka.client.service-url.defaultZone=http://eureka7001:8761/eureka/
eureka.instance.prefer-ip-address=true

#Feign默认整合了Hystrix,要想为Feign打开Hystrix支持,需要此项设置
#在springcloud Dalston之前的版本中,Feign默认开启Hystrix支持,无需设置feign.hystrix.enabled=true
#从springcloud Dalston版本开始,Feign的Hystrix支持默认关闭,需要手动设置开启
feign.hystrix.enabled=true

此时,我们关闭 eureka-client-producer 服务提供方的两个实例,再重启 eureka-client-consumer 服务让其配置生效,再来测试接口 http://127.0.0.1:8090/UserConsumer/queryOneById?id=1postman 测试结果如下

在这里插入图片描述
这不就是执行了 feign 服务降级的实现类 UserConsumerFeignFallback 中的方法嘛,结论:feign 默认集成了 ribbonhystrix,并和 eureka 结合,实现了负载均衡

猜你喜欢

转载自blog.csdn.net/weixin_38192427/article/details/121172606