RestTemplate-微服务间通信

126 阅读3分钟

RestTemplate-微服务间通信

demo地址

gitee.com/w--kk/RestT…

服务间通信方式

服务间的服务该如何调用,有哪些调用方式?

image.png

总结: 在springcloud中服务间调用方式主要是使用 http restful方式进行服务间调用

  1. 什么是微服务
    定义: 基于单体应用围绕业务进行服务拆分,拆分出来每一个服务独立应用,独立运行,独立部署,运行在自己计算机进程中,基于分布式服务管理

  2. 如何解决微服务的服务间通信问题?
    a. HTTP Rest 方式  使用http协议进行数据传递  JSON  springcloud 使用HTTP协议传递数据
    b. RPC  方式 远程过程调用  二进制
    OSI: 物理层  数据链路层  网络层  传输层(RPC)  会话层  表示层  应用层(Http)

RPC比HTTP快,但是也需要付出代价,如果使用RPC,SpringCloud只能基于两个java之间去传递数据

  1. 如何在java代码中发起http方式请求?
    a. spring框架提供HttpClient对象, RestTemplate(类似于浏览器概念) ,发起一个http请求

可以把RestTemplate想象成浏览器,java代码中的浏览器,能传get,post等,能拿到响应

  1. 实现服务间通信写一个案例
    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=8500
    

    e. 在入口类中加入服务注册 consul client注解

基于RestTemplate的服务调用

RestTemplate是Spring框架提供的,与springcloud没有关系 image.png

  1. 说明
  • spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

RestTemplate 服务调用

1 .创建两个服务并注册到consul注册中心中

  • users 代表用户服务 端口为 9999
  • products 代表商品服务 端口为 9998
    注意:这里服务仅仅用来测试,没有实际业务意义
  1. 在商品服务中提供服务方法
@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;
    }
}
  1. 在用户服务中使用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;
    }
}
  1. 启动服务

  2. 测试服务调用

集群 image.png

image.png

使用RestTemplate对象实现服务间通信存在问题

  1. 现有RestTemplate方式通信存在问题?
RestTemplate restTemplate = new RestTemplate();
String orderResult = restTemplate.getForObject("http://localhost:8001/order", String.class);
  1. 现有RestTemplate在进行服务间通信时?
    a. 调用服务的路径主机和服务端口直接写死在url中无法实现,服务集群时请求负载均衡。
    b. 调用服务的请求路径写死在代码中, 日后提供服务服务路径发生变化时不利于后续维护工作

  2. 解决restTemplate负载均衡问题?
    a. 自定义负载均衡解决策略
    问题:1.无法实现服务健康检查  2. 负载均衡策略过于单一(随机)
    b. 使用springcloud提供组件 ribbon 解决负载均衡调用  推荐

  3. Ribbon springcloud-netflix-ribbon
    作用:负载均衡客户端组件  就是用来实现请求调用时负载均衡

引用 编程不良人