微服务分解成多个不同的服务,那么多个服务之间怎么调用呢?
Spring Cloud最新面试题
Spring Cloud Nacos详解之注册中心
Spring Cloud Nacos详解之配置中心
Spring Cloud Nacos详解之集群配置
Spring Cloud Eureka详解
Spring Cloud Ribbon详解
Spring Cloud Gateway详解
Spring Cloud Hystrix详解
现在有两个服务,订单服务(服务消费者)和用户服务(服务提供者),分别对应不同的数据库。
注意: 因为远程调用都是服务消费者调用服务提供者,所以配置和业务编写,都在服务消费者里面。
用两个不同的数据库,模拟部署在两台服务器的数据库
订单yml配置 访问路径:@GetMapping("order/{orderId}")
server:
port: 8082
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
application:
name: orderservice //订单服务的名称
用户yml配置 访问路径:@GetMapping("user/{id}")
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
application:
name: userservice //用户服务的名称
1.注入RestTemplate
/**
* 因为启动类本身也是一个配置了,所以我们在启动类进行注入,你自己自定义配置类注入也行
* 创建RestTemplate并注入Spring容器
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
2.编写远程调用
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 根据订单id查询订单
Order order = orderMapper.findById(orderId);
// 利用RestTemplate发起http请求,根据用户id查询用户
// url路径 http://服务名称(上面配置了)/请求路径/参数
String url = "http://localhost:8081/user/" + order.getUserId();
// 发送http请求,实现远程调用,现在是get请求类型
User user = restTemplate.getForObject(url, User.class);
// 封装user到Order
order.setUser(user);
// 返回值
return order;
}
3.RestTemplate的缺点
1.引入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
2.在启动类使用注解开启Feign功能
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
}
3.编写远程调用
//服务名称
@FeignClient(value = "userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
4.调用接口
@Autowired
private UserClient userClient;
public Order queryOrderById(Long orderId) {
// 根据订单id查询订单
Order order = orderMapper.findById(orderId);
// 用Feign远程调用
User user = userClient.findById(order.getUserId());
// 封装user到Order
order.setUser(user);
// 返回
return order;
}
5.Feign还集成了Ribbon,所以我们不用考虑负载均衡问题
类型 | 作用 | 说明 |
---|---|---|
feign.Logger.Level | 修改日志级别 | 四种不同的级别:NONE(没有任何日志)、BASIC(发起请求的开始结束时间)、HEADERS(会记录请求头请求体)、FULL(请求和响应信息) |
feign.codec.Decoder | 响应结果的解析器 | http远程调用的结果做解析,例如解析json字符串为java对象 |
feign.codec.Encoder | 请求参数编码 | 将请求参数编码,便于通过http请求发送 |
feign. Contract | 支持的注解格式 | 默认是SpringMVC的注解 |
feign. Retryer | 失败重试机制 | 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试 |
一般我们自定义配置的是日志
1.配置文件配置日志
//全局配置
feign:
client:
config:
default://default全局配置,远程调用的服务的接口也会打印。
loggerLevel:FULL //日志级别
//局部配置
feign:
client:
config:
orderservice://只打印服务名为orderservice的日志。
loggerLevel:FULL //日志级别
2.代码方式配置日志
//第一步:注入对象
public class DefaultFeignConfiguration {
@Bean
public Logger.Level logLevel(){
//日志级别
return Logger.Level.BASIC;
}
}
//第二步:注解配置
//全局配置
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)
//局部配置
@FeignClient(value = "userservice",confiquration = FeignClientConfiguration.class)
Feign底层客户端实现:
1.使用连接池替代默认的URL Connection(使用HttpClient支持)
①pom文件引入依赖
<dependency>
<groupId>io.github.openfeigngroupId>
<artifactId>feign-httpclientartifactId>
dependency>
②yml文件进行配置
feign:
httpclient:
enabled: true # 支持HttpClient的开关
max-connections: 100 # 最大连接数
max-connections-per-route: 25 # 单个路径的最大连接数
2.日志级别最好是basic或none
如果A、B、C服务都要调用D服务,那我们要在A、B、C里面都使用Feign调用D吗,如果写就造成了很多代码冗余,所以我们要把Feign抽离出来放在一个公共的服务里面。我们新建一个Feign-api服务,然后谁用谁就在pom文件引入一下。
注意: 需要把调用的接口(加上@FeignClient(vaule=服务名)
注解)和实体类写在公共的服务里面。
<dependency>
<groupId>cn.xinxin.demogroupId>
<artifactId>feign-apiartifactId>
<version>1.0version>
dependency>
但是这样做会导致SpringBootApplication在扫描包时找不到定义FeignClient对象,那么怎么解决呢?
解决
方式一:指定FeignClient所在包
@EnableFeignClients(basePackages = "cn.xinxin.feign.clients")
方式二:指定FeignClient字节码
EnableFeignClients(clients = {UserClient.class})
Feign的pom文件
<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-demoartifactId>
<groupId>cn.xinxin.demogroupId>
<version>1.0version>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>feign-apiartifactId>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
dependencies>
project>