前言
微服务的服务提供者和服务消费者解耦合之后,我们可以借助restTemplate这样的HTTP客户端,向微服务的服务提供者发起远程调用;
但是这样的代码有2大缺陷:
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:b5737d4b-c67f-494f-ab24-db1b90ce375f
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:3670496e-b22f-4e34-b244-549a7696f2bf
* 当URL参数复杂时难以维护
//使用RestTemplate发起远程调用
@Autowired
private RestTemplate restTemplate;
public Order findById(Long orderId) {
// 1.查询订单
Order order = orderMapper.selectById(orderId);
//2.调用user-service服务查询当前订单的用户信息
//String url = "http://127.0.0.1:8081/user/" + order.getUserId();
//使用RestTemplate发起远程调用
String url = "http://user-service/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);
//3.user封装到order对象
order.setUser(user);
// 4.返回
return order;
}
一、SpringCloud项目搭建
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:d51b9890-ec58-48ff-b942-0c2518ac52f6
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:46bfcbf5-3bd0-47fe-8e05-40bae98d9231
如果用户微服务需要查询订单微服务的数据,就需要使用Feign发起远程调用;
在远程调用过程中user-service是消费者order-service是生产者;
1.搭建流程图
2.搭建父项目
2.1.父项目依赖版本锁定
<?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"> <modelVersion>4.0.0modelVersion><span><</span><span>groupId</span><span>></span>com.zhanggen<span><span>groupId</span><span>></span> <span><</span><span>artifactId</span><span>></span>spring-cloud-demo<span><span>artifactId</span><span>></span> <span><</span><span>version</span><span>></span>1.0-SNAPSHOT<span><span>version</span><span>></span> <span><</span><span>packaging</span><span>></span>pom<span><span>packaging</span><span>></span> <span><</span><span>parent</span><span>></span> <span><</span><span>groupId</span><span>></span>org.springframework.boot<span><span>groupId</span><span>></span> <span><</span><span>artifactId</span><span>></span>spring-boot-starter-parent<span><span>artifactId</span><span>></span> <span><</span><span>version</span><span>></span>2.3.9.RELEASE<span><span>version</span><span>></span> <span><</span><span>relativePath</span><span>/></span> <span><span>parent</span><span>></span> <span><</span><span>dependencyManagement</span><span>></span> <span><</span><span>dependencies</span><span>></span> <span><</span><span>dependency</span><span>></span> <span><</span><span>groupId</span><span>></span>org.springframework.cloud<span><span>groupId</span><span>></span> <span><</span><span>artifactId</span><span>></span>spring-cloud-dependencies<span><span>artifactId</span><span>></span> <span><</span><span>version</span><span>></span>Hoxton.SR10<span><span>version</span><span>></span> <span><</span><span>type</span><span>></span>pom<span><span>type</span><span>></span> <span><</span><span>scope</span><span>></span>import<span><span>scope</span><span>></span> <span><span>dependency</span><span>></span> <span><</span><span>dependency</span><span>></span> <span><</span><span>groupId</span><span>></span>com.alibaba.cloud<span><span>groupId</span><span>></span> <span><</span><span>artifactId</span><span>></span>spring-cloud-alibaba-dependencies<span><span>artifactId</span><span>></span> <span><</span><span>version</span><span>></span>2.2.6.RELEASE<span><span>version</span><span>></span> <span><</span><span>type</span><span>></span>pom<span><span>type</span><span>></span> <span><</span><span>scope</span><span>></span>import<span><span>scope</span><span>></span> <span><span>dependency</span><span>></span> <span><span>dependencies</span><span>></span> <span><span>dependencyManagement</span><span>></span> <span><</span><span>modules</span><span>></span> <span><</span><span>module</span><span>></span>user-service<span><span>module</span><span>></span> <span><</span><span>module</span><span>></span>order-service<span><span>module</span><span>></span> <span><span>modules</span><span>></span>
project>
pom.xml3.搭建子项目
3.1.子项目依赖导入
<?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>spring-cloud-demoartifactId> <groupId>com.zhanggengroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>order-serviceartifactId><span><</span><span>dependencies</span><span>></span> <span><</span><span>dependency</span><span>></span> <span><</span><span>groupId</span><span>></span>org.springframework.boot<span><span>groupId</span><span>></span> <span><</span><span>artifactId</span><span>></span>spring-boot-starter-web<span><span>artifactId</span><span>></span> <span><span>dependency</span><span>></span> <span><</span><span>dependency</span><span>></span> <span><</span><span>groupId</span><span>></span>com.alibaba.cloud<span><span>groupId</span><span>></span> <span><</span><span>artifactId</span><span>></span>spring-cloud-starter-alibaba-nacos-discovery<span><span>artifactId</span><span>></span> <span><span>dependency</span><span>></span> <span><</span><span>dependency</span><span>></span> <span><</span><span>groupId</span><span>></span>org.springframework.cloud<span><span>groupId</span><span>></span> <span><</span><span>artifactId</span><span>></span>spring-cloud-starter-openfeign<span><span>artifactId</span><span>></span> <span><span>dependency</span><span>></span> <span><</span><span>dependency</span><span>></span> <span><</span><span>groupId</span><span>></span>io.github.openfeign<span><span>groupId</span><span>></span> <span><</span><span>artifactId</span><span>></span>feign-httpclient<span><span>artifactId</span><span>></span> <span><span>dependency</span><span>></span> <span><span>dependencies</span><span>></span>
project>
pom3.2.application配置文件
server: port: 9090 spring: application: name: order-service cloud: nacos: discovery: server-addr: 127.0.0.1:8848
application.yml
二、Feign介绍
Feign是1个声明式的HTTP客户端,通过HTTP协议使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。
其作用就是帮助我们优雅的实现HTTP请求的发送,解决上面提到的问题。
而且Feign默认集成了Ribbon,所以使用Feign默认就实现了客户端负载均衡的效果。
三、Feign使用
1.引入依赖
<dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-openfeignartifactId> dependency>2.添加 @EnableFeignClients 注解
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:26b875b6-18fb-4abd-baac-861db9e2acc2
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:221a4d6a-f7c5-4a0c-bc22-e67562659ace
在order-service的启动类添加注解开启Feign的功能;
@MapperScan("com.zhanggen.order.mapper") @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients //开启Feign public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
3.编写Feign的客户端
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:cd228e7e-7486-4d75-8817-ccef56296f4f
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:9b95c824-de80-4e82-88d6-e7b94eb9d8fb
在order-service项目中com.zhanggen.order.mapper 包下新建一个接口,内容如下:
//FeignClient必须和@EnableFeignClients标注的类在同一个包下 //该接口用于向user-service微服务发起远程调用 //Feign底层默认使用HTTP协议发起远程调用 //@FeignClient("user-service")+@GetMapping("/user/{id}")确定服务提供者的URL(http://user-service/user/{id}) @FeignClient("user-service") public interface UserClient { //根据userId查询用户信息 @GetMapping("/user/{id}") User findById(@PathVariable Long id); }
这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。
4.修改OrderService类
是不是看起来优雅多了。
//使用Feign发起远程调用 @Autowired private UserClient userClient; public Order findById(Long orderId) { // 1.查询订单 Order order = orderMapper.selectById(orderId); //2.调用user-service服务查询当前订单的用户信息 //String url = "http://127.0.0.1:8081/user/" + order.getUserId(); //使用RestTemplate发起远程调用 //String url = "http://user-service/user/" + order.getUserId(); //User user = restTemplate.getForObject(url, User.class); User user = userClient.findById(order.getUserId()); //3.user封装到order对象 order.setUser(user); // 4.返回 return order; }
四、 Feign配置
Feign可以支持很多的自定义配置,如下表所示:
类型作用说明 feign.Logger.Level修改日志级别包含四种不同的级别:NONE(默认)、BASIC、HEADERS、FULLNONE
,不记录。默认选项BASIC
,仅记录请求方法和URL以及响应状态代码和执行时间。HEADERS
,记录基本信息以及请求和响应标头。FULL
,记录请求和响应的标题,正文和元数据。feign.codec.Decoder 响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象feign.codec.Encoder 请求参数编码将请求参数编码,便于通过http请求发送,例如POST请求,将请求参数编码到请求体中feign.Contract 支持的注解格式默认是SpringMVC的注解feign.Retryer 失败重试机制请求失败的重试机制,默认是没有,不过会使用Ribbon的重试,例如A服务无法访问,会尝试访问集群中的B服务一般情况下,Feign的默认配置就能满足我们使用,如果要自定义配置时,只需要创建自定义的@Bean覆盖默认Bean即可。
下面以日志为例来演示如何自定义配置,修改Feign日志有 2 种方式: 配置文件方式、Java代码方式
1.配置文件方式(推荐)
基于配置文件修改feign的日志级别可以针对单个服务:
feign: client: config: user-service: # 针对某个微服务的配置,也可以针对所有服务,这个位置换成default loggerLevel: FULL # 日志级别
2.Java代码方式
也可以基于Java代码来修改日志级别,在
com.zhanggen.order.config
包下创建类,然后声明一个Logger.Level的对象:package com.zhanggen.order.config; import feign.Logger; import org.springframework.context.annotation.Bean; public class FeignDefaultConfiguration { @Bean public Logger.Level feignLogLevel(){ return Logger.Level.FULL; // 日志级别为FULL } }
2.1.配置局部
如果我想让以上日志配置在调用某1个服务提供者时生效,在FeigClien接口中修改如下;
@FeignClient(value = "user-service",configuration = FeignDefaultConfiguration.class) public interface UserClient { //根据userId查询用户信息 @GetMapping("/user/{id}") User findById(@PathVariable Long id); }
2.2.配置全局
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:794bb111-aebb-46ba-9c5e-fb58ca08d50c
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:da1e7a9c-b784-40b2-bc78-e6d039c7e5a7
@EnableFeignClients(defaultConfiguration = FeignDefaultConfiguration.class) public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); }
五、Feign连接池
Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:
- URLConnection:默认实现,不支持连接池,每次请求都是新建连接
- Apache HttpClient :支持连接池
- OKHttp:支持连接池
因此提高Feign的性能主要手段就是使用 连接池代替默认的URLConnection。
1.pom引入依赖
<dependency> <groupId>io.github.openfeigngroupId> <artifactId>feign-httpclientartifactId> dependency>
2.application.yml配置
max-connections-per-route:再调用某1个服务提供者时,最多从连接池中拿出50个连接发起远程调用,避免服务雪崩;
feign:
httpclient:
enabled: true # 开启feign对HttpClient的支持
max-connections: 200 # 设置最大的连接数
max-connections-per-route: 50 # 并行接收一个服务的请求数量
六、Feign公共模块
在微服务架构中肯定会存在多个服务消费者,这些服务消费者都需要借助Feign发起远程调用;
在实际的分布式架构开发中我们一般把Feign抽取出来作为1个公共模块,以便于其他微服务模块使用;
1.创建feign-api公共模块
把之前在order-service中编写的UserClient、User、FeignDefaultConfiguration剪切到feign-api项目中
在fein-api模块中添加spring-cloud-starter-openfeign依赖
<dependencies> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-openfeignartifactId> dependency> <dependency> <groupId>com.baomidougroupId> <artifactId>mybatis-plus-coreartifactId> <version>3.4.0version> dependency> <dependency> <groupId>io.github.openfeigngroupId> <artifactId>feign-httpclientartifactId> dependency> dependencies>
2.服务消费者(调用方)
2.1.引入公共模块
服务消费者pom文件引入feign-api公共模块的依赖;
<dependency> <groupId>com.zhanggengroupId> <artifactId>fein-apiartifactId> <version>1.0-SNAPSHOTversion> dependency>
2.2.启动类
服务消费者启动类设置@EnableFeignClients注解一定要设置Feign公共模块中的配置类和Feign公共模块的包;
@EnableFeignClients(defaultConfiguration = FeignDefaultConfiguration.class,
basePackages = "com.zhanggen.feign")
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
服务消费者配置文件
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:063fbd2d-c651-49eb-9cda-397ce7575a5e
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:fc5b95da-c0c1-48fc-a78b-7745783c3f92
feign:
client:
config:
default:
#不设置connectTimeout会导致readTimeout设置不生效
connectTimeout: 3000
readTimeout: 6000
2.3.Feign常见报错
Did you forget to include spring-cloud-starter-netflix-ribbon?
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
3.服务提供者(被调用方)
创建1个client包专门对内面向Feign远程调用,而controller包专门对外面向前端调用;
参考
Original: https://www.cnblogs.com/sss4/p/16414981.html
Author: Martin8866
Title: 微服务之同步远程调用(Feign)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/562581/
转载文章受原作者版权保护。转载请注明原作者出处!