(二)Spring Cloud之feign远程调用

Feign组件

Feign使用方式

 使用动态代理技术,生成接口的代理类对象,在代理类对象中完成远程调用.
 封装了如下代码: 硬编码
        String url = "http://userservice/user/findById/"+order.getUserId();
        TbUser user = restTemplate.getForObject(url, TbUser.class);

1.导入feign的启动器

 <!-- Feign启动器 -->
 <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>

2.开启Feign客户端支持

 在服务消费者引导类中添加注解
 @EnableFeignClients

3.编写feign客户端接口

客户端接口要与服务提供者的入口方法保持一致(与服务提供者Controller中的方法名一致)
@FeignClient("userservice") // 设置服务提供者的名称
@Component  // 创建接口实现类对象,并将对象存放到IOC容器中




/**
 * @Author: huahua
 * @name:UserFeignClient
 * @Date:2023/8/15 14:38
 * todo: Feign原理: 使用动态代理技术生成当前接口的代理类,在代理类中使用RestTemplate进行远程访问
 */
@FeignClient(value = "userservice",path = "/user")
@Component // 创建当前接口的代理类对象,并将对象存放到IOC容器中
public interface UserFeignClient {
	// 直接从被调用的服务中(controller层)抄过来即可
    @RequestMapping("/findById/{id}")
    TbUser findById(@PathVariable Integer id);
}

4.调用Feign客户端实现远程调用


/**
* @author 85190
* @description 针对表【tb_order】的数据库操作Service实现
* @createDate 2023-08-14 18:45:59
*/
@Service
public class TbOrderServiceImpl extends ServiceImpl<TbOrderMapper, TbOrder>
    implements TbOrderService{
//    @Autowired
//    private RestTemplate restTemplate;

    @Autowired
    private UserFeignClient userFeignClient;

    @Override
    public TbOrder findById(Integer id) {
        // todo:根据ID查询订单信息
        TbOrder order = this.getById(id);
        // todo: 远程访问user服务,根据ID查询用户信息
        TbUser user = userFeignClient.findById(Integer.parseInt(order.getUserId()+""));
        // todo: 封装结果
        order.setUser(user);
        return order;
    }

//    @Override
//    public TbOrder findById(Integer id) {
//        // todo:根据ID查询订单信息
//        TbOrder order = this.getById(id);
//        // todo: 远程访问user服务,根据ID查询用户信息
//        //String url = "http://localhost:8081/user/findById/"+order.getUserId();
//        String url = "http://userservice/user/findById/"+order.getUserId();
//        //String forObject = restTemplate.getForObject(url, String.class);
//        TbUser user = restTemplate.getForObject(url, TbUser.class);
//        // todo: 封装结果
//        order.setUser(user);
//        return order;
//    }

}

Hystix支持(了解)

1.开启Feign内部Hystrix支持

feign:
  hystrix:
    enabled: true # 开启Feign的熔断功能

2.编写降级类,提供降级方法

/**
 * @Author: huahua
 * @name:UserFeignClientHystrix
 * @Date:2023/8/15 15:06
 */
@Component
public class UserFeignClientHystrix implements UserFeignClient{
    @Override
    public TbUser findById(Integer id) {
        TbUser user = new TbUser();
        user.setUsername("Feign降级了...");
        return user;
    }
}

3.在Feign客户端类上指定降级类

/**
 * @Author: huahua
 * @name:UserFeignClient
 * @Date:2023/8/15 14:38
 * todo: Feign原理: 使用动态代理技术生成当前接口的代理类,在代理类中使用RestTemplate进行远程访问
 */
@FeignClient(value = "userservice",path = "/user",fallback = UserFeignClientHystrix.class)
@Component // 创建当前接口的代理类对象,并将对象存放到IOC容器中
public interface UserFeignClient {

    @RequestMapping("/findById/{id}")
    TbUser findById(@PathVariable Integer id);
}

日志级别

记录服务调用时生成的日志信息

1.配置日志包

logging:
  level:
    com.huahua: debug

2.编写配置类,定义日志级

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

这里指定的Level级别是FULL,Feign支持4种级别:

  • NONE:不记录任何日志信息,这是默认值。

  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间

  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息

  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

3.Feign客户端开启日志记录


/**
 * 作用: user-service服务客户端接口
 *      feign会生成当前接口的代理类对象,
 *      在代理类对象中完成对user-service的远程调用
 */
@FeignClient(
        value = "user-service",
        fallback = UserServiceFeignHystrix.class,
        configuration = FeignConfig.class
)
@Component
public interface UserServiceFeignClient {

    @RequestMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

Feign负载均衡

ribbon:
  ConnectTimeout: 500 # 连接超时时长
  ReadTimeout: 2000 # 数据通信超时时长
  MaxAutoRetries: 3 # 当前服务器的重试次数
  MaxAutoRetriesNextServer: 1 # 重试多少个实例
  OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试
  # 修改ribbon获取服务地址的加载策略: 饥饿加载(默认为懒加载)
  eager-load:
    enabled: true
    clients: user-service

Feign-API抽取

创建一个feign-api模块

导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-parent</artifactId>
        <groupId>com.bw.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>feign-api</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- Feign启动器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

</project>

提供相关的Feign接口

/**
 * @Author: huahua
 * @name:UserFeignClient
 * @Date:2023/8/15 14:38
 * todo: Feign原理: 使用动态代理技术生成当前接口的代理类,在代理类中使用RestTemplate进行远程访问
 */
@FeignClient(value = "userservice",
        path = "/user",
        fallback = UserFeignClientHystrix.class,
        configuration = FeignConfig.class)
@Component // 创建当前接口的代理类对象,并将对象存放到IOC容器中
public interface UserFeignClient {

    @RequestMapping("/findById/{id}")
    TbUser findById(@PathVariable Integer id);
}

提供相关的降级方法

/**
 * @Author: huahua
 * @name:UserFeignClientHystrix
 * @Date:2023/8/15 15:06
 */
@Component
public class UserFeignClientHystrix implements UserFeignClient {
    @Override
    public TbUser findById(Integer id) {
        TbUser user = new TbUser();
        user.setUsername("Feign降级了...");
        return user;
    }
}

配置Feign的日志级别

// 声明配置类
@Configuration
public class FeignConfig {
    @Bean // 将方法的返回值存放到IOC容器中
    Logger.Level feignLoggerLevel(){
        //- NONE:不记录任何日志信息,这是默认值。
        //- BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
        //- HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
        //- FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
        return Logger.Level.FULL;
    }
}

在需要使用的服务中导入


<dependency>
    <groupId>com.huahua.cloud</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: hauhua
 * @name:OrderApp
 * @Date:2023/8/14 18:47
 */
// 当不声明需要扫描的包时,扫描将从引导类所在的包开始扫描
@SpringBootApplication
@MapperScan("com.bw.order.mapper")
@EnableHystrix
// 声明Feign接口所在的位置 UserFeignClient
@EnableFeignClients(basePackages = "com.bw.feign")
// 配置SpringBoot需要扫描的包(一旦设置了扫描的包,那么SpringBoot默认的扫包机制将不再生效)
@ComponentScan({"com.bw.feign","com.bw.order"})
public class OrderApp {
    public static void main(String[] args) {
        SpringApplication.run(OrderApp.class,args);
    }
}

Feign优化

OpenFeign 
    --> RestTemplate(Spring) 
        -->  URLConnection|Apache HttpClient|OKHttp 
            --> 对网络编程的客户端进行的封装

Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:

•URLConnection:默认实现,不支持连接池

•Apache HttpClient :支持连接池

•OKHttp:支持连接池

因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。

这里我们用Apache的HttpClient来演示。

1)引入依赖

在order-service的pom文件中引入Apache的HttpClient依赖:

 <!--httpClient的依赖 -->
 <dependency>
     <groupId>io.github.openfeign</groupId>
     <artifactId>feign-httpclient</artifactId>
 </dependency>

2)配置连接池

在order-service的application.yml中添加配置:

 feign:
   client:
     config:
       default: # default全局的配置
         loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
   httpclient:
     enabled: true # 开启feign对HttpClient的支持
     max-connections: 200 # 最大的连接数
     max-connections-per-route: 50 # 每个路径的最大连接数
  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值