RestTemplate-微服务间通信
demo地址
服务间通信方式
服务间的服务该如何调用,有哪些调用方式?
总结: 在springcloud中服务间调用方式主要是使用 http restful方式进行服务间调用
-
什么是微服务
定义: 基于单体应用围绕业务进行服务拆分,拆分出来每一个服务独立应用,独立运行,独立部署,运行在自己计算机进程中,基于分布式服务管理 -
如何解决微服务的服务间通信问题?
a. HTTP Rest 方式 使用http协议进行数据传递 JSON springcloud 使用HTTP协议传递数据
b. RPC 方式 远程过程调用 二进制
OSI: 物理层 数据链路层 网络层 传输层(RPC) 会话层 表示层 应用层(Http)
RPC比HTTP快,但是也需要付出代价,如果使用RPC,SpringCloud只能基于两个java之间去传递数据
- 如何在java代码中发起http方式请求?
a. spring框架提供HttpClient对象,RestTemplate(类似于浏览器概念) ,发起一个http请求
可以把RestTemplate想象成浏览器,java代码中的浏览器,能传get,post等,能拿到响应
-
实现服务间通信写一个案例
a. 开发两个测试服务 用户服务 users 订单服务 orders
b. 用户服务 订单服务 都是两个独立springboot应用
c. 两个服务都引入consul client 依赖 & 健康检查依赖<!--引入springbootweb--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--引入consul依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <!-- 这个包是用做健康度监控的--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>d. 配置两个服务application.properties
# consul server spring.cloud.consul.host=localhost spring.cloud.consul.port=8500e. 在入口类中加入服务注册 consul client注解
基于RestTemplate的服务调用
RestTemplate是Spring框架提供的,与springcloud没有关系
- 说明
- spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
RestTemplate 服务调用
1 .创建两个服务并注册到consul注册中心中
- users 代表用户服务 端口为 9999
- products 代表商品服务 端口为 9998
注意:这里服务仅仅用来测试,没有实际业务意义
- 在商品服务中提供服务方法
@RestController
@Slf4j
public class ProductController {
@Value("${server.port}")
private int port;
@GetMapping("/product/findAll")
public Map<String,Object> findAll(){
log.info("商品服务查询所有调用成功,当前服务端口:[{}]",port);
Map<String, Object> map = new HashMap<String,Object>();
map.put("msg","服务调用成功,服务提供端口为: "+port);
map.put("status",true);
return map;
}
}
- 在用户服务中使用restTemplate进行调用
@RestController
@Slf4j
public class UserController {
@GetMapping("/user/findAll")
public String findAll(){
log.info("调用用户服务...");
//1.使用restTemplate调用商品服务
RestTemplate restTemplate = new RestTemplate();
String forObject = restTemplate.getForObject("http://localhost:9998/product/findAll",
String.class);
return forObject;
}
}
-
启动服务
-
测试服务调用
- 浏览器访问用户服务 http://localhost:9999/user/findAll
集群
使用RestTemplate对象实现服务间通信存在问题
- 现有RestTemplate方式通信存在问题?
RestTemplate restTemplate = new RestTemplate();
String orderResult = restTemplate.getForObject("http://localhost:8001/order", String.class);
-
现有RestTemplate在进行服务间通信时?
a. 调用服务的路径主机和服务端口直接写死在url中无法实现,服务集群时请求负载均衡。
b. 调用服务的请求路径写死在代码中, 日后提供服务服务路径发生变化时不利于后续维护工作 -
解决restTemplate负载均衡问题?
a. 自定义负载均衡解决策略
问题:1.无法实现服务健康检查 2. 负载均衡策略过于单一(随机)
b. 使用springcloud提供组件 ribbon 解决负载均衡调用 推荐 -
Ribbon springcloud-netflix-ribbon
作用:负载均衡客户端组件 就是用来实现请求调用时负载均衡
引用 编程不良人