SpringCloud入门之服务消费

在之前我们实现了服务的注册和发现,今天我们来实现下服务的消费。

一、准备工作

1.1 创建 user-service 模块

用于给 Ribbon 提供服务调用。

1.2 在pom.xml 文件中添加依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

1.3 在 application.yml 文件中进行配置

# 指定服务名称
spring:
  application:
    name: user-service

eureka:
  client:
    # 注册到 Eureka 的注册中心
    register-with-eureka: true
    # 获取注册实例列表
    fetch-registry: true
    service-url:
      # 向注册中心注册
      defaultZone: http://replica1:9001/eureka,http://replica2:9002/eureka

注:为了之后启动多个服务,端口我们将通过命令参数指定

1.4 创建用户实体类

public class User {

    private String username;
    public User(){}
    public User(String username){
        this.username = username;
    }
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                '}';
    }
}

1.5 创建 UserController

@RestController
public class UserController {

    private static final Logger log = LoggerFactory.getLogger(UserController.class);

    @GetMapping("/user/{username}")
    public User getUser(@PathVariable String username) {
        log.info("username :{}", username);
        return new User(username);
    }

    @PostMapping("/user")
    public User modify(String username){
        log.info("username :{}", username);
        return new User("modify");
    }

}

1.6 创建两个服务,配置不同端口并启动

1.7 查看注册中心

确认 user-service 已经注册成功。

二、 ribbon-service

2.1 创建 ribbon-service 模块 pom 依赖如下

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

2.2 在application.yml 文件中配置

# 指定运行端口
server:
  port: 8210
# 指定服务名称
spring:
  application:
    name: ribbon-service

eureka:
  client:
    # 注册到 Eureka 的注册中心
    register-with-eureka: true
    # 获取注册实例列表
    fetch-registry: true
    service-url:
      # 同时注册到两个注册中心
      defaultZone: http://replica1:9001/eureka,http://replica2:9002/eureka

service-url:
  user-service: http://user-service

2.3 启用 RestTemplate 负载均衡功能

@Configuration
public class RibbonConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

注:通过 @LoadBalanced 注解就能开启 RestTemplate 对象的负载均衡功能。

2.4 创建 UserRibbonController

@RequestMapping("/user")
@RestController
public class UserRibbonController {

    @Value("${service-url.user-service}")
    private String userServiceUrl;

    private final RestTemplate restTemplate;

    public UserRibbonController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @GetMapping("/get/{username}")
    public User getUser(@PathVariable String username) {
        return restTemplate.getForObject(userServiceUrl + "/user/{1}", User.class, username);
    }

    @GetMapping("/post/{username}")
    public User modify(@PathVariable String username) {
        Map<String, Object> map = new HashMap<>();
        map.put("username", username);
        User result = restTemplate.postForObject(userServiceUrl + "/user/{1}", map, User.class);
        return result;
    }

}

2.5 启动项目

访问 http://localhost:8210/user/get/marklogzhu,返回如下 JSON 数据:

{
  username: "marklogzhu"
}

说明调用 user-service 服务成功,我们再多次调用,然后查看两个 user-service 的控制台:

user-service01 控制台:

2020-05-26 10:05:26.860  INFO 17000 --- [nio-8112-exec-2] c.l.s.u.controller.UserController        : username :marklogzhu
2020-05-26 10:05:28.564  INFO 17000 --- [nio-8112-exec-3] c.l.s.u.controller.UserController        : username :marklogzhu

user-service02 控制台:

2020-05-26 10:05:27.915  INFO 7896 --- [nio-8111-exec-2] c.l.s.u.controller.UserController        : username :marklogzhu
2020-05-26 10:05:29.081  INFO 7896 --- [io-8111-exec-10] c.l.s.u.controller.UserController        : username :marklogzhu

可以看出 RestTemplate 默认是采用轮询的方式进行负载均衡。

三、Ribbon 介绍

在微服务架构中,很多服务都会部署多个,其他服务去调用该服务的时候,如何保证负载均衡是个不得不去考虑的问题。负载均衡可以增加系统的可用性和扩展性,当我们使用 RestTemplate 来调用其他服务时,Ribbon 可以很方便的实现负载均衡功能。

**Spring Cloud Netflix Ribbon ** 是 Spring Cloud Netflix 子项目的核心组件之一,主要给服务间调用及 API 网关转发提供负载均衡的功能。

3.1 Ribbon的常用配置

全局配置:

ribbon:
  ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
  ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
  OkToRetryOnAllOperations: true #对超时请求启用重试机制
  MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
  MaxAutoRetries: 1 # 切换实例后重试最大次数
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法

指定服务进行配置:

user-service:
  ribbon:
    ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
    ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
    OkToRetryOnAllOperations: true #对超时请求启用重试机制
    MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
    MaxAutoRetries: 1 # 切换实例后重试最大次数
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法

可以看出与全局配置的区别就是 ribbon 节点挂在服务名称下面。

3.2 Ribbon的负载均衡策略

ribbon可以选择以下几种负载均衡策略:

* com.netflix.loadbalancer.RandomRule:从提供服务的实例中以随机的方式;
* com.netflix.loadbalancer.RoundRobinRule:以线性轮询的方式,就是维护一个计数器,从提供服务的实例中按顺序选取,第一次选第一个,第二次选第二个,以此类推,到最后一个以后再从头来过;
* com.netflix.loadbalancer.RetryRule:在RoundRobinRule的基础上添加重试机制,即在指定的重试时间内,反复使用线性轮询策略来选择可用实例;
* com.netflix.loadbalancer.WeightedResponseTimeRule:对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择;
* com.netflix.loadbalancer.BestAvailableRule:选择并发较小的实例;
* com.netflix.loadbalancer.AvailabilityFilteringRule:先过滤掉故障实例,再选择并发较小的实例;
* com.netflix.loadbalancer.ZoneAwareLoadBalancer:采用双重过滤,同时过滤不是同一区域的实例和故障实例,选择并发较小的实例。

猜你喜欢

转载自www.cnblogs.com/markLogZhu/p/12963876.html