SpringCloud入门之服务消费

Posted marklogzhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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:采用双重过滤,同时过滤不是同一区域的实例和故障实例,选择并发较小的实例。

以上是关于SpringCloud入门之服务消费的主要内容,如果未能解决你的问题,请参考以下文章

Springcloud之Zuul网关入门

SpringCloud第二季之消费模块与支付模块学习笔记

SpringCloud第二季之消费模块与支付模块学习笔记

springcloud+eureka简单入门案例

springcloud基础入门

SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介创建消息生产者创建消息消费者自定义消息通道分组与持久化设置 RoutingKey)(代码片段