-----------------微服务------------------
- Feign远程调用
- 简单的认识一下
(1)声明式或者说是模板化的HTTP客户端。
(2)快捷的并优雅的调用HTTP相关的API。
(3)具备了Ribbon负载均衡和Eureka的服务注册相关功能。
(4)支持的注解比较丰富。
(5)SpringCloud对其进行增强,支持了SpringMVC的相关的注解,并且整合了Ribbon和Eureka。
(6)使用的时候更多的注意力集中服务的消费者以及如何调用服务提供者为其提供的服务。
(7)官网地址:https://github.com/OpenFeign/feign
- 使用Feign代替RestTemplate
- 之前的代码:
// 1、准备url
String url = "http://userservice/user/" + order.getUid();
// 2、发起远程调用
User user = restTemplate.getForObject(url, User.class);
此时还是有点不舒服:
(1)不统一,可读性比较差。
(2)相对来说URL比较复杂。
- 使用Feign来解决如上问题
(1)在订单微服的pom文件中引入feign相关依赖
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)在订单微服务的启动类使用注解开启Feign的功能。
@EnableFeignClients // 开启Feign功能
@MapperScan("com.neusoft.order.mapper")
@SpringBootApplication
public class OrderApp {
(3)准备Feign的客户端【处理远程调用】,在订单微服中创建一个处理接口即可。
- 服务名称:userservice
- 请求方式:get
- 请求路径:/user/{id}
- 请求参数:Integer id
- 返回类型:User
package com.neusoft.order.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import com.neusoft.order.beans.User;
/**
* Feign客户端接口,注意基于SpringMVC注解实现
* - 服务名称:userservice
* - 请求方式:get
* - 请求路径:/user/{id}
* - 请求参数:Integer id
* - 返回类型:User
*/
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
public User getUserById(@PathVariable Integer id);
}
(4)使用Feign发起远程调用,订单微服务中服务层实现类中的相关处理。
// 自动注入Feign客户端接口
@Resource
private UserClient userClient;
@Override
public Orders getOrdersInfoById(Integer id) {
// 查询订单
Orders order = orderMapper.findOrdersById(id);
// 使用Feign远程调用用户微服务获取用户信息
User user = userClient.getUserById(order.getUid());
// 将用户对象封装到订单对象中
order.setUser(user);
// 将订单对象返回
return order;
}
(5)启动相关的微服务进行测试即可。
- nacos管理界面验证正常。
- 访问路径:
http://localhost:9002/order/5
- 结果:
{"id":5,"uid":5,"name":"纪念卡","price":30,"num":3,"user":{"id":5,"uname":"刘能","address":"铁岭"}}
- Feign的自定义配置
一般情况下默认就可以满足需要了,也支持自定义的。
(1)自定义的配置
- 修改日志级别
- NONE:不记录任何的信息。【默认的情况】
- BASIC:记录请求的方法、URL、响应状态码和执行时间。【推荐使用】
- HEADERS:记录请求的方法、URL、响应状态码、执行时间以及请求和响应的头信息。
- FULL:记录所有请求和响应的详细信息,比如头信息、请求体以及其他的数据。
- 响应结果的处理器
- 请求参数的具体的编码
- 注解格式
- 失败处理机制
(2)自定义配置的有效范围
- 全局有效:所有的微服务都起作用。
- 局部有效:针对个别的微服务起作用。
(3)实现自定义的方式
比如自定义日志级别处理,注意原本SpringBoot日志输出配置是要有的。
# 配置日志
logging:
level:
'[com.neusoft]': debug
pattern:
dateformat: MM-dd HH:mm:ss:SSS
否则没有的话就不会看到想要的日志结果。
- 基于配置文件
(1)全局
# Feign自定义配置日志级别
feign:
client:
config:
default: # 此时代表的就是全局
logger-level: full #日志级别,不推荐使用该级别。
(2)局部
# Feign自定义配置日志级别
feign:
client:
config:
userservice: # 指定的是具体的服务名称代表局部
logger-level: full #日志级别,不推荐使用该级别。
- 基于编码实现
直接声明一个配置类,然后设置日志级别。
package com.neusoft.order.config;
import org.springframework.context.annotation.Bean;
import feign.Logger;
/**
* 自定义一个配置类修改日志的级别
* @author 辽A丶孙悟空
*
*/
public class DFConfig {
@Bean
public Logger.Level feignLogLevel(){
// 直接返回一个日志级别,推荐使用BASIC级别。
return Logger.Level.BASIC;
}
}
(1)全局
如果全局生效,需要在启动类的开启Feign功能注解@EnableFeignClients进行配置。
@EnableFeignClients(defaultConfiguration = DFConfig.class)
(2)局部
@FeignClient(value = "userservice",configuration = DFConfig.class)
(4)基本测试日志的输出情况
最后在这还是要提醒各位默认的SpringBoot日志输出要配置。
- Feign的基本优化
底层实现在发起HTTP请求的时候或者客户端的具体的实现,都是依赖其他的框架的。
(1)主要的方式
- 使用连接池。
(2)基本的总结
- 日志级别
推荐使用BASIC级别。
- 使用连接池
引入相关依赖,修改相关的配置文件即设置连接池的相关参数。
- Feign的正常使用
在之前的基本使用的时候发现一个问题:Feign的客户端代码和用户微服务的控制层代码非常接近。
- 客户端:
public interface UserClient {
@GetMapping("/user/{id}")
public User getUserById(@PathVariable Integer id);
}
- 服务的提供者【用户微服务】:
@GetMapping("/{id}")
public User queryUserInfoById(@PathVariable Integer id) {
// 需要服务层的支持:调用相关的方法处理
return userService.getUserById(id);
}
很清楚的看见代码可以说是重复的,如果想要去掉重复的代码可以通过如下的方式:
(1)使用工具类【不推荐使用】
(2)使用Java的继承【不推荐使用】
不推荐的理由是耦合问题:无论原来的业务代码和非业务代码的耦合还是现在的服务的提供者和消费者耦合。
(3)抽取模块【类似AOP的理解】
第一步:创建一个单独的微服务模块。
跟以前一样正常创建,注意引入的时候需要版本,添加版本号。
<version>1.0</version>
第二步:修改pom文件引入feign相关依赖。
<dependencies>
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
第三步:提取公共的User实体类、Feign的客户端、默认的配置类。
直接到订单微服务中复制并修改各个相关包的引入。
第四步:删除原来订单微服务中User实体类、Feign的客户端、默认的配置类。
开心点直接删除即可。
第五步:引入新建公共模块,在订单微服pom文件引入公共模块坐标即可。
<!-- 引入Feign—Api -->
<dependency>
<groupId>com.neusoft.feign</groupId>
<artifactId>Feign-Api</artifactId>
<version>1.0</version>
</dependency>
第六步:重新导入相关类的包。
直接相关的三个类或者接口导入即可。
第七步:启动各个相关的微服务测试。
出现异常:客户端接口找不到,因为包扫描不到。
第八步:处理异常。
- 姿势一:指定Feign应该扫描的包。【个人推荐使用】
@EnableFeignClients(basePackages = "com.neusoft.feign.client")
- 姿势二:指定需要加载的客户端接口。
@EnableFeignClients(clients = {UserClient.class})
第九步:最后重启相关微服务测试。
- 地址:
http://localhost:9002/order/7
- 结果:
{"id":7,"uid":1,"name":"华为","price":5600,"num":1,"user":{"id":1,"uname":"猴哥","address":"沈阳"}}
- Gateway服务网关
SpringCloudGateway是SpringCloud一个项目主要负责网关,为微服务架构提供一套简单的统一的API的路由管理方式。
- 主要的作用:
(1)权限控制
网关可以看做此时微服务的入口,需要验证用户的是否具有某些权限,如果有就放行,否则就直接拦截。
(2)路由和负载均衡
不负责具体的业务相关的处理,只是拦截判断权限,根据权限看是否给相关资源【去访问相关的微服务】。
具体访问的时候可以有比较多的服务实例【列表】,需要负载均衡的处理。
(3)限制流量
当请求的流量比较大的时候,需要控制放行的速度【根据服务提供者的处理速度而定】,起到一定程度的保护。