Nacos整合OpenFegin实现RPC调用

往期回顾

Nacos的安装与配置

Spring Cloud集成Nacos作为注册中心

LoadBalacer集成Nacos实现负载均衡

常见的负载均衡策略分析

Spring Cloud集成Dubbo实现RPC调用

SpringCloud集成Nacos作为配置中心

前面我们已经介绍了Nacos 的安装与配置,Spring Cloud 集成Nacos 作为服务的注册中心和配置中心,集成Nacos 实现服务的负载均衡和一些常见的负载均衡策略以及使用Dubbo进行RPC调用

接下来,将介绍如何使用OpenFeign 进行RPC调用

关于RPC的一些相关概念前面的文章已经介绍过,这里不再赘述。如果还有疑问的同学可以参见

Spring Cloud集成Dubbo实现RPC调用

OpenFeign介绍

Spring Cloud OpenFeign 是声明式的服务调用工具,它整合了RibbonHystrix ,拥有负载均衡和服务容错功能

Feign 是声明式的服务调用工具,我们只需创建一个接口并用注解的方式来配置它,就可以实现对某个服务接口的调用,简化了直接使用RestTemplate 来调用服务接口的开发量。Feign 具备可插拔的注解支持,同时支持Feign 注解、JAX-RS注解及SpringMvc注解。当使用Feign时,Spring Cloud集成了RibbonEureka 以提供负载均衡的服务调用及基于Hystrix 的服务容错保护功能。

大家经常听到有人说OpenFeign,有人说Feign,给人一种好像是两个东西的错觉。其实是因为Feign本身也是Netflix的开源项目,后面独立出来单独做了开源项目,改名为OpenFeign。这种情况其实很常见,比如鸿蒙-HarmonyOS就有Open HarmonyOS。

快速开始

引入依赖

我们先在原有的项目工程上创建一个新的消费者模块

引入对应依赖

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <!-- 将ribbon排除 -->
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>  
		        <!--添加loadbalancer依赖
            由于 Netflix Ribbon 进入停更维护阶段,因此 SpringCloud 2020.0.1 版本之后 删除了eureka中的ribbon,
            替代ribbon的是spring cloud自带的LoadBalancer,默认使用的是轮询的方式
            新版本的 Nacos discovery 都已经移除了 Ribbon ,此时我们需要引入 loadbalancer 代替,才能调用服务提供者提供的服务
        -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

添加相关配置

Nacos配置

详见SpringCloud集成Nacos作为配置中心

新建bootstrap.yml

spring:
  application:
    name: user-openfeign-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.199.128:8848 #Nacos地址
      config:
        server-addr: 192.168.199.128:8848 #Nacos地址
        file-extension: yaml #这里我们获取的yaml格式的配置

添加application.yml

server:
  port: 7002
spring:
  profiles:
    active: dev

配置OpenFeign 日志级别

日志的级别分为四种:

  • NONE :不记录任何日志信息,这是默认值。
  • BASIC :仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS :在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL :记录所有请求和响应的明细,包括头信息、请求体、元数据

日志的级别如果没有特殊要求,一般使用 NONE、BASIC 两个就好了,默认是NONE

注意:因为feign调试日志是debug级别输出,springboot默认的日志级别是info,所以feign的debug日志级别就不会输出,所以需要对Feign接口单独配置日志输出级别

# 因为feign调试日志是debug级别输出,springboot默认的日志级别是info,所以feign的debug日志级别就不会输出
# logging.level=debug这样配置是对所有的日志级别进行配置
# 该场景只需要对feign接口进行debug配置,所以是这样配置logging.level.com.example.order.feign=debug
logging:
  level:
    cuit.epoch.pymjl.service.UserFeignClient: debug
  1. Java代码的方式

可以基于Java代码来修改日志级别,先声明一个类,然后声明一个Logger.Level 的对象

先创建一个配置类

package cuit.epoch.pymjl.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;


/**
 * 在启动类的注解@EnableFeignClients上指定
 * 局部生效就在@FeignClient中指定,不能加@Configuration注解
 *
 * @author Pymjl
 * @version 1.0
 * @date 2022/9/1 13:17
 **/
public class OpenFeignConfig {
    
    
    @Bean
    public Logger.Level feignLogLevel() {
    
    
        // 日志级别为BASIC
        return Logger.Level.FULL;
    }
}

如果要全局生效,将其放到 启动类的@EnableFeignClients 这个注解中

@SpringBootApplication
@EnableFeignClients(defaultConfiguration = OpenFeignConfig.class)
public class OpenFeignApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OpenFeignApplication.class, args);
    }
}

如果是局部生效,则把它放到对应的@FeignClient 这个注解中

@FeignClient(value = "user-service",configuration = OpenFeignConfig.class)
  1. 配置文件的方式
# 针对某个微服务的配置  userservice:微服务名称  FULL:日志级别
feign.client.config.userservice.logger-level=FULL
# 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
#feign.client.config.default.logger-level=FULL

配置LoadBalancer

详见LoadBalacer集成Nacos实现负载均衡

  1. 配置负载均衡策略
/**
 * 注意不要加@Configuration
 *
 * @author Pymjl
 * @version 1.0
 * @date 2022/8/26 13:05
 **/
public class MyLoadBalancerConfig {
    
    
    @Resource
    NacosDiscoveryProperties nacosDiscoveryProperties;

    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
    
    
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        // Nacos权重轮询
        return new NacosLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class), name, nacosDiscoveryProperties);
    }
}

  1. 配置RestTemplate
/**
 * 在这里配置我们自定义的LoadBalancer策略 如果想自己扩展算法 需要实现ReactorServiceInstanceLoadBalancer接口
 * @LoadBalancerClients(defaultConfiguration = {name = "CLOUD-PAYMENT-SERVICE", configuration = MyLoadBalancerConfig.class})
 * 注意这里的name属性 需要和Nacos页面中的服务提供者名字一致
 *
 * @author Pymjl
 * @version 1.0
 * @date 2022/8/26 12:20
 **/
@Configuration
@LoadBalancerClient(name = "user-service", configuration = MyLoadBalancerConfig.class)
public class RestTemplateConfig {
    
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
    
    
        return new RestTemplate();
    }
}

超时配置

我们在通过 Feign 去调用接口,难免会遇到超时的问题,我们可以在 yml 文件设置超时属性,防止系统抛出超时异常

feign:
    client:
        config:
		   # 全局配置(default 默认就是适用于全部微服务)
            default:
                connectTimeout: 100000
                readTimeout: 100000
            # 单独配置
            user-service:
                connectTimeout: 300000
                readTimeout: 300000

OpenFeign的其他配置

类型 作用 说明
feign.Logger.Level 修改日志级别 包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder 响应结果的解析器 http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送
feign. Contract 支持的注解格式 默认是SpringMVC的注解
feign. Retryer 失败重试机制 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可

常用的配置如下:

feign:
  hystrix:
    enabled: true #在Feign中开启Hystrix
  compression:
    request:
      enabled: false #是否对请求进行GZIP压缩
      mime-types: text/xml,application/xml,application/json #指定压缩的请求数据类型
      min-request-size: 2048 #超过该大小的请求会被压缩
    response:
      enabled: false #是否对响应进行GZIP压缩
logging:
  level: #修改日志级别
    com.macro.cloud.service.UserService: debug

OpenFeign的优化

默认情况下,Feign 使用的是 UrlConnetcion 去请求,这种原生的请求方式一旦遇到高并发的情况下,响应会变得很慢,所以我们可以考虑加入连接池技术来优化性能, 比如常用的Ok HttpApache Http Client

在HTTP 通信的过程中,建立连接是一个很复杂的过程,涉及到多个数据包的交换,很耗时间,而且HTTP连接需要3次握手和4次挥手开销都很大。

这时可以采用HTTP连接池,节约大量的3次握手4次挥手时间,提升吞吐量。

默认的HttpURLConnection是JDK自带的,并不支持连接池,如果要实现连接池的机制,还需要自己来管理连接对象。

HttpClient 相比传统JDK自带的HttpURLConnection,它封装了访问HTTP的请求头,参数,内容体,响应等等。它不仅使客户端发送HTTP请求变得容易,而且也方便了开发人员测试接口(基于HTTP协议的),既提高了开发的效率,又提高了代码的健壮性。另外高并发大量的请求网络的时候,也是用"连接池"提升吞吐量。

OkHttp作为后期之秀,功能和性能上,可能稍优于HttpClient ,但是几乎没多大区别,实际使用时,都是可以的,不过HttpClient集成起来更方便

下面介绍下如何集成 Apache 下的 HttpClient 的连接池

  1. 先引入依赖
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>
  1. 编写对应的yml文件
feign:
  httpclient:
    enabled: true
    max-connections: 200
    max-connections-per-route: 50

编写对应的接口

  1. 先在服务提供者正常的编写service 代码,然后将service 注入进controller 完成controller 的编写
/**
 * @author Pymjl
 * @version 1.0
 * @date 2022/8/25 12:48
 **/
@RestController
@RequestMapping("/user")
public class UserController {
    
    
    @Resource
    UserService userService;

    @GetMapping("/register")
    public CommonResult<String> register() {
    
    
        userService.register();
        return ResultUtils.success();
    }

    @GetMapping("/get/{id}")
    public CommonResult<User> get(@PathVariable("id") Long id) {
    
    
        return ResultUtils.success(userService.get(id));
    }

}

  1. 在消费者端编写对应的FeignClient ,和我们平常的service接口没太大的区别,只是在上面加上对应的SpringMVC注解
/**
 * @author Pymjl
 * @version 1.0
 * @date 2022/9/1 0:03
 **/
@FeignClient(value = "user-service")
public interface UserFeignClient {
    
    
    /**
     * 注册
     *
     * @return {@code CommonResult<String>}
     */
    @GetMapping("/user/register")
    CommonResult<String> register();

    /**
     * 得到
     *
     * @param id id
     * @return {@code CommonResult<User>}
     */
    @GetMapping("/user/get/{id}")
    CommonResult<User> get(@PathVariable("id") Long id);
}

注意value 的值要和nacos 中的服务提供者的名字相同

然后编写对应的消费者controller

/**
 * @author Pymjl
 * @version 1.0
 * @date 2022/9/1 0:09
 **/
@RestController
@RequestMapping("/consumer")
public class TestController {
    
    
    @Resource
    UserFeignClient userFeignClient;

    @GetMapping("/register")
    public CommonResult<String> register() {
    
    
        return userFeignClient.register();
    }

    @GetMapping("/get/{id}")
    public CommonResult<User> get(@PathVariable Long id) {
    
    
        return userFeignClient.get(id);
    }
}

测试

  1. 先启动服务提供者user-service,再启动消费者

image-20220901140039863

  1. 访问对应接口

image-20220901140307734

  1. 查看消费者后台日志输出

image-20220901140333458

从上面可以看见,因为我们对OpenFegin 配置了日志的输出级别,控制台在访问对应的请求时打印了对应的HTTP接口的详情

  1. 查看提供者的日志输出

image-20220901140446778

至此,整合NacosOpenFegin 就完成了,至于OpenFegin 整合Hystrix 进行服务的降级与熔断这里不做赘述,后面考虑整合Sentinel

Spring Cloud 之前使用的断路器是 Netfilx 开源的 Hystrix 。被很多开发人员作为默认的断路器来使用。2018 年 11 月,当 Netflix 宣布将这个项目置于维护模式时(不再开发新特性,只进行例行维护),Spring Cloud 官方也不得不跟进了 Netfix ,在 SpringOne 2019中,Spring 宣布将从 Spring Cloud 3.1 版本中删除 Hystrix 仪表板。要不了多长时间 Spring Cloud Netfix 将结束生命周期。

应的请求时打印了对应的HTTP接口的详情

  1. 查看提供者的日志输出

[外链图片转存中…(img-J4Qu3Fig-1662298670269)]

至此,整合NacosOpenFegin 就完成了,至于OpenFegin 整合Hystrix 进行服务的降级与熔断这里不做赘述,后面考虑整合Sentinel

Spring Cloud 之前使用的断路器是 Netfilx 开源的 Hystrix 。被很多开发人员作为默认的断路器来使用。2018 年 11 月,当 Netflix 宣布将这个项目置于维护模式时(不再开发新特性,只进行例行维护),Spring Cloud 官方也不得不跟进了 Netfix ,在 SpringOne 2019中,Spring 宣布将从 Spring Cloud 3.1 版本中删除 Hystrix 仪表板。要不了多长时间 Spring Cloud Netfix 将结束生命周期。

项目源码:gitee github

猜你喜欢

转载自blog.csdn.net/apple_52109766/article/details/126695067