Eureka中RestTemplate服务通信和Ribbon客户端负载均衡

如何实现服务通信

1.1.流程说明

上一章节我们对Eureka Server做了高可用集群搭建,这一章节我们来实现简单版的服务通信。

目前除了Eureka Server以外我们的微服务有订单服务springcloud-order-server-1030,和用户服务springcloud-user-server-1020 , 我们就用这两个服务来演示微服务的通信,他们的调用关系应该是:浏览器 -> 订单服务 -> 用户服务,如下图:
在这里插入图片描述
这里订单服务通过RestTemplate向用户服务发起调用,目的是要获取到用户服务返回的User对象,最终是需要浏览器获取到User。

1.2.解决方案

用户服务需要提供User对象,我们需要为其编写Controller接口,编写相关方法返回User,订单服务需要从用户服务获取到User对象,而浏览器需要访问订单服务获取到User对象,所以订单服务也需要编写Controller接口供浏览器来调用。

我们发现不管是用户服务还是订单服务都需要用到User对象,那么是不是在用户服务和订单服务都需要创建User的模型?当然没必要,公共的东西就是要抽取,所以我们会把User对象封装在一个公共的模块 springcloud-user-common中然后让用户服务和订单服务都去依赖这个模块。

1.3.RestTemplate介绍

微服务的通信协议主流的有RPC,Http,SpringCloud是基于Http Restful 风格 ,在Java中发起一个Http请求的方式很多,比如 Apache的HttpClient , OKHttp等等 。Spring为我们封装了一个基于Restful的使用非常简单的Http客户端工具 RestTemplate ,我们就用它来实订单服务和用户服务的通信。需要注意的是,RestTmplate本身不具备服务发现和负载均衡器的功能,我们本章的案例只是演示在订单服务中使用RestTemplate基于ip和端口的方式向用户服务发起调用,即:不走注册中心,不使用服务发现方式。

实战

搭建user模块

在这里插入图片描述

User对象
package com.huawei.domain;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
// 字段随意设
    private Long id;
    private String name;

    private String intro;
}
用户和订单依赖User模块
<dependency>
            <groupId>com.huawei</groupId>
            <artifactId>springcloud-netflix-pojo-user</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
用户服务返回User(controller)
@RestController
public class UserController {

    @Value("${server.port}")
    private String port;
    @GetMapping("/user/{id}")
    public User getById(@PathVariable("id")Long id){
        return new User(id,"zs",port);
    }
}
订单服务获取User

在订单服务中需要使用RestTemplate调用用户服务,我们需要把RestTmplate配置成Bean方便使用(当然也可以不创建Bean,用的时候直接new对象也可以) ,修改工程springcloud-order-server-1030在主配置类配置RestTemplate如下:

@SpringBootApplication
@EnableEurekaClient
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

	//配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

创建controller,通过RestTemplate调用用户服务

@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/order/{id}")
    public User getById(@PathVariable("id")Long id){
        //User user = restTemplate.getForObject("http://localhost:10030/user/" + id, User.class);
        User user = restTemplate.getForObject("http://user-server/user/" + id, User.class);
        return user;
    }
}
测试服务通信

依次启动Eureka Server注册中心(不启动也行) , 用户服务 ,订单服务 , 浏览器访问订单服务:http://localhost:10020/order/1

Ribbon客户端负载均衡

1.基本概念

1.1.为什么要Ribbon

我们知道,为了防止应用出现单节点故障问题,同时为了提高应用的作业能力,我们需要对应用做集群 ,如果我们对user-server(用户服务)做了集群 ,那么这个时候回衍生出一些问题:现在有两个user-server(用户服务)就意味着有两个user-server(用户服务)的通信地址,我的order-server(订单服务)在向user-server(用户服务)发起调用的时候该访问哪个?如何访问?这个时候就需要有一个组件帮我们做请求的分发,即:负载均衡器,而Ribbon就是一个 - 客户端负载均衡器。

1.2.什么是Ribbon

Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端负载均衡算法。Ribbon客户端组件提供一系列完善的配置项,如,连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,Ribbon可以按照负载均衡算法(如简单轮询,随机连接等)向多个服务发起调用(正好可以解决上面的问题),我们也很容易使用Ribbon实现自定义的负载均衡算法。

1.3.Ribbon的工作机制

如下图,我们将user-server(用户服务)做集群处理,增加到2个节点(注意:两个user-server(用户服务)的服务名要一样,ip和端口不一样),在注册中心的服务通信地址清单中user-server(用户服务)这个服务下面会挂载两个通信地址 。 order-server(订单服务)会定时把服务通信地址清单拉取到本地进行缓存, 那么当order-server(订单服务)在向user-server(用户服务)发起调用时,需要指定服务名为 user-server(用户服务);那么这个时候,ribbon会根据user-server(用户服务)这个服务名找到两个user-server的通信地址 , 然后ribbon会按照负载均衡算法(默认轮询)选择其中的某一个通信地址,发起http请求实现服务的调用,如下图:
在这里插入图片描述

用户服务集群配置

yml文件中

server:
  port: 10031 // 10030
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:10010/eureka/
  instance:
    instance-id: user-server1 #user-server 端口号和实例名不同
spring:
  application:
    name: user-server #集群的服务名必须相同

Order-server集成Ribbon

Ribbon集成官方文档:https://cloud.spring.io/spring-cloud-static/Greenwich.SR5/multi/multi_spring-cloud-ribbon.html#netflix-ribbon-starter

导入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
开启负载均衡
@SpringBootApplication
@EnableEurekaClient
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

	//配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
    //@LoadBalanced :让RestTemplate有负载均衡的功能
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
修改controller
@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/order/{id}")
    public User getById(@PathVariable("id")Long id){
        //User user = restTemplate.getForObject("http://localhost:10030/user/" + id, User.class);
        User user = restTemplate.getForObject("http://user-server/user/" + id,User.class); // 将localhost:10030 改为集群的服务名user-server
        return user;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值