SpringCloud学习路线(6)—— 远程调用HTTP客户端Feign

一、Feign替代RestTemplate

RestTemplate示例

String url = "http://userservice/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);

RestTemplate的缺陷:

  • 代码可读性差,编码体验不统一。
  • 参数复杂URL难以维护

(一)Fegin的概念

Fegin是一个声明式的http客户端,官网:https://github.com/OpenFeign/feign
作用是 帮助简化实现http请求的发送。

(二)基本使用Fegin

1、引入依赖

<dependency>
	<groupId>org.springframework.cloud</gourpId>
	<artifactId>spring.cloud.starter.openfeign</artifactId>
</dependency>

2、启动类加注解启动Fegin

@EnableFeignClients //启动Fegin客户端
@MapperScan("xxx.xxx.xxx.mapper")
@SpringBootApplication
public class OrderApplication {
    
    
	public static void main(String[] args) {
    
    
		SpringApplication.run(OrderApplication.class,args);
	}
}

3、定义Fegin客户端

@FeignClient("userservice")
public interface UserClient {
    
    
	@GetMapping("/user/{id}")
	User findById(@PathVariable("id") Long id);
}

主要是基于SpringMVC的注解来声明远程调用的信息,比如:

  • 服务名称:userservice
  • 请求方式:GET
  • 请求路径:/user/{id}
  • 请求参数:Long id
  • 返回值:User

3、Service使用Feign客户端

@Service 
public class OrderService {
    
    
	@Autowired
	private OrderMapper mapper;
	
	@Autowired
	private UserClient userClient;

	public Order queryOrderById(Long orderId) {
    
    
		Order order = orderMapper.findById(orderId);
		User user = userClient.getById(order.getUserId());
		order.setUser(user);
		return order;
	}
	
}

二、自定义配置

可以修改的配置表

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

(一)修改配置的实现

方式一:配置文件方式

fegin:
	client:
		config:
			default: #设置全局配置,若是直接写服务名称,则是针对某一个微服务的配置
				loggerLevel: FULL #全日志级别

方式二:自定义Feign配置

FeignClientConfiguration 配置类

//配置注解选择一种即可
//全局配置:在启动类上加上该注解
//@EnableFeginClients(defaultConfiguration = FeignClientConfiguration.class)
//局部配置:具体Client类上加该注解
//@FeginClient(value = "userservice", configuration = FeignClientConfiguration.class)
public class FeignClientConfiguration {
    
    
	@Bean
	public Logger.Level.feignLogLevel(){
    
    
		return Logger.Level.BASIC;
	}
}

三、Feign优化

(一)Feign底层的客户端实现(三种模式)

  • URLConnection: 默认实现,不支持连接池(JDK自带)
  • Apache HttpClient: 支持连接池
  • OKHttp: 支持连接池

(二)对Fegin进行优化的性能

  • 1、使用连接池代替URLConnection
  • 2、日志级别,最好配置为 BASICNONE

(三)配置连接池代替URLConnection

1、引入HttpClient依赖

<dependency>
	<groupId>io.github.openfeign</groupId>
	<artifactId>feign-httpclient</artifactId>
</dependency>

2、配置连接池

feign:
	client:
		config:
			default: #全局配置
				loggerLevel: BASIC #日志级别,打印最基本的请求和响应信息
	httpclient:
		enabled: true #开启feign对httpclient的支持
		max-connections: 200 #最大连接数
		max-connections-per-route: 50 #每个路径的最大连接数

四、实践总结的实现FeignClient的经验

(一)方式一(继承): 给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。

1、实现:

父接口

public interface UserAPI{
    
    
	@GetMapping("/user/{
    
    id})
	User findById(@PathVariable("id") Long id);
}

UserClient继承父接口

@FeignClient(value = "userservice")
public interface UserClient extends UserAPI{
    
    

}

UserController实现父接口

@RestController
public class UserController implements UserAPI {
    
    
	public User findById(@PathVariable("id") Long id) {
    
    
		//...实现业务
	}
}

2、这种方式的缺陷

  • 服务紧耦合
  • 父接口参数列表映射不会被继承

(二)方式二(抽取): 将FeignClient抽取为独立模块,并且把接口有关的POJO、默认Feign配置都放置在这个模块中给所有消费者使用。

在这里插入图片描述
1、实现

(1)模块创建

创建一个module,命名为feign-api,引入feign的starter依赖

(2)模块功能类抽取

将需要抽取的类放到feign-api模块中。

(3)使用feign-api

消费者服务引入feign-api依赖

(4)消费者服务 import feign-api

2、可能会出现的问题

UserClient 没有被Spring 创建 Bean 对象

  • 原因: FeginClient脱离了消费者服务包扫描的范围,导致有引入没实例的情况。

  • 解决方案:

方式一:指定FeignClient坐在包

@EnableFeignClients(basePackages = "xxx.xxx.xxx.clients")

方式二:指定FeignClient字节码

@EnableFeignClients(clients= {
    
    UserClient.class})

猜你喜欢

转载自blog.csdn.net/Zain_horse/article/details/131811525