Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)

文章目录

  • Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)
    • 1. 修改服务提供者并注册到Eureka中
      • 1.1 Maven依赖:
      • 1.2 编写Service
      • 1.3 编写Controller
      • 1.4 配置
      • 1.5 主启动类
      • 1.6 启动并测试
    • 2. 创建服务消费者
      • 2.1 新建消费者项目
      • 2.2 编写配置
      • 2.3 在启动类添加注解,并注入Bean
      • 2.4 编写Controller
      • 2.5 启动测试
      • 2.6 问题反思?
    • 3. Rest + Ribbon 实现负载均衡
      • 3.1 启动注册2个服务提供者
      • 3.2 修改服务消费者
      • 3.3 启动消费者并测试

Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)

学习 Spring Cloud 之路,文中 Spring Boot 版本为 2.1.3.RELEASESpring Cloud 版本为 Greenwich.SR1 。因能力有限,难免会有不足或者错误之处,还望不吝指正,谢!

接上篇 Spring Cloud 学习 | - 02 - Eureka集群实现高可用,我们把服务提供者注入到Eureka注册中心,注册完了,我们最终是要消费服务的。本篇将开始进行服务消费的过程。

1. 修改服务提供者并注册到Eureka中

1.1 Maven依赖:

主要的依赖如下:

		<dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

1.2 编写Service

新增接口 UserService ,并添加一个方法 findAll()
UserService.java

public interface UserService {
    /**
     * 查询所有用户
     * @return
     */
    List findAll();
}

并实现该接口 UserServiceImpl 。我们要使用 Spring 的自动注入功能,加上 @Service 注解:
UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {
    /**
     * 查询所有用户
     * @return
     */
    @Override
    public List findAll() {
        List list = Arrays.asList("Cindy","Pony","Marry");
        return list;
    }
}

1.3 编写Controller

新增 UserController ,对外暴露一个 list 接口。
UserController.java

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/list")
    public List list(){
        return userService.findAll();
    }
}

@RestController 表示这是一个Rest风格的接口,返回的是JSON ,这个注解等效于 @Controller + @ResponseBody

1.4 配置

server:
  port: 8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true # 返回ip而不是host名称
#    ip-address: 127.0.0.1 # 指定自己的ip信息
    lease-expiration-duration-in-seconds: 15 # 服务失效时间,默认值90秒
    lease-renewal-interval-in-seconds: 5 # 服务续约(renew)的间隔,默认为30秒
spring:
  application:
    name: user-provider

1.5 主启动类

@SpringBootApplication
@EnableDiscoveryClient
public class UserProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserProviderApplication.class, args);
    }
}

1.6 启动并测试

依次启动Eureka服务和user-provider,访问http://localhost:8761/:
Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)_第1张图片
我们测试一下接口是否正常:
Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)_第2张图片
接口正常取到数据。
至此,服务提供者成功注册到eureka注册中心。接下来,开始服务消费者。

2. 创建服务消费者

2.1 新建消费者项目

利用Spring Initializr快速创建一个Spring Boot项目,名称为:user-consumer,主要依赖如下:

		<dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>

2.2 编写配置

编写application.yml配置文件,将服务注册到eureka注册中心,完整的.yml配置如下:

server:
  port: 8080
spring:
  application:
    name: user-consumer
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true

2.3 在启动类添加注解,并注入Bean

在XxxApplication启动类上添加@EnableDiscoveryClient启用客户端发现功能,并向IoC容器中注入一个Bean:RestTemplate,Rest API调用需要用到。

@SpringBootApplication
@EnableDiscoveryClient
public class UserConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplication.class, args);
    }
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

2.4 编写Controller

@RestController
public class UserController {
    @Autowired(required = false)
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/list")
    public Object findAll(){
        List<ServiceInstance> instanceList = discoveryClient.getInstances("user-provider");
        // 我们这里用第一个实例
        ServiceInstance instance = instanceList.get(0);
        StringBuffer buffer = new StringBuffer("http://");
        buffer.append(instance.getHost()).append(":").append(instance.getPort()).append("/user/list");
        return restTemplate.getForObject(buffer.toString(), Object.class);
    }
}

2.5 启动测试

我们启动user-consumer服务,查看eureka注册中心,已经有了user-consumer服务:
Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)_第3张图片
我们测试一下接口是否正常:
Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)_第4张图片
成功拿到结果。

2.6 问题反思?

这里我们用的是实例列表里取第一个实例,如果是要实现负载均衡,应该是顺序选择或者随机一个实例或者其它什么的。其实我们修改取到实例的方法即可。但是我们是快速开发,不是造轮子,SpringCloud已经帮我们弄好了解决方法,Rest + Ribbon 实现注解式的负载均衡。下边,我们用Rest + Ribbon的方式实现负载均衡的功能。

3. Rest + Ribbon 实现负载均衡

3.1 启动注册2个服务提供者

  • 我们修改以下消费提供者的UserController.javalist()方法,返回参数多一个port端口:
@GetMapping("/list")
    public Map list(){
        Map<String,Object> data = new HashMap<>(16);
        data.put("port", port);
        data.put("rows", userService.findAll());
        return data;
    }
  • 我们复制一份user-provider的配置启动类,取名:UserProviderApplication-2,确定OKSpring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)_第5张图片
  • 修改user-provider的配置端口,改为8091:
server:
  port: 8091
  • 保存并启动,启动完成后,三个启动项目如下:
    在这里插入图片描述
  • 查看注册中心:
    在这里插入图片描述

3.2 修改服务消费者

  • RestTemplate这个Bean上加注解@LoadBalanced,完整的代码如下:
@SpringBootApplication
@EnableDiscoveryClient
public class UserConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
  • 修改UserController,调用方式采用Rest+Ribbon的方式,完整的代码如下:
@RestController
public class UserController {
    @Autowired(required = false)
    private RestTemplate restTemplate;

    @GetMapping("/list")
    public Object findAll(){
        // List instanceList = discoveryClient.getInstances("user-provider");
        // // 我们这里用第一个实例
        // ServiceInstance instance = instanceList.get(0);
        // StringBuffer buffer = new StringBuffer("http://");
        // buffer.append(instance.getHost()).append(":").append(instance.getPort()).append("/user/list");
        StringBuffer buffer = new StringBuffer("http://").append("user-provider").append("/user/list");
        return restTemplate.getForObject(buffer.toString(), Object.class);
    }
}

3.3 启动消费者并测试

启动user-consumer进行API接口测试:
结果是对的,并且我们发现返回的数据里port交替出现。已经作了负载均衡,之所以交替出现,是因为默认的负载均衡策略规则是轮询策略,就是一个一个按顺序来。
Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)_第6张图片
Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡)_第7张图片

你可能感兴趣的:(Spring,Cloud,Spring,Cloud,学习之路)