在微服务中架构中,业务都会被拆分成一个独立的服务,服务于服务的通讯是基于http restful的。Spring Cloud有两种服务调动方式, 一种是RestTemplate+Ribbon,另一种是Feign;此处使用RestTemplate+Ribbon实现服务消费者。
Ribbon简介
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。 Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。 因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。
准备工作
- 启动服务提供者
eureka-client
,端口号为:8762
- 修改配置文件的端口号为:
8763
,再启动一个实例,然后Eureka Server中会注册两个eureka-client
的实例,这相当于一个小集群。
创建服务消费者
创建SpringBoot工程eureka-consumer-ribbon
,pom.xml
文件配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springcloud.bh</groupId>
<artifactId>eureka-consumer-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-consumer-ribbon</name>
<description>服务消费者-ribbon</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
</properties>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
主要是增加了Ribbon的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
配置application.yml
设置端口号为8764
server:
port: 8764
spring:
application:
name: eureka-consumer-ribbon
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
Application
通过@EnableDiscoveryClient
注解注册到服务中心
package com.springcloud.bh;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaConsumerRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerRibbonApplication.class, args);
}
}
Configuration
配置注入RestTemplate
的Bean,并通过@LoadBalanced
注解开启负载均衡功能。
新建config包,在此新建RestTemplateConfiguration
配置类
package com.springcloud.bh.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfiguration {
@Bean
@LoadBalanced /*开启负载均衡*/
public RestTemplate restTemplate()
{
return new RestTemplate();
}
}
创建测试用的Service
在这里直接使用程序名代替了具体的URL地址,在Ribbon中它会根据服务名来选择具体的服务实例,根据服务实例在请求的时候会用具体的URL替换掉服务名,代码如下:
package com.springcloud.bh.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class AdminService {
@Autowired
private RestTemplate restTemplate;
public String sayHi(String message)
{
return restTemplate.getForObject("http://eureka-client/hi?message="+message,String.class);
}
}
创建测试用的Controller
package com.springcloud.bh.controller;
import com.springcloud.bh.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AdminController {
@Autowired
private AdminService adminService;
@GetMapping("hi")
public String sayHi(String message)
{
return adminService.sayHi(message);
}
}
测试访问
打开浏览器,多次访问http://localhost:8764/hi?message=hi,Ribbon 浏览器交替显示:
- 你的消息是:hi,Ribbon 端口号:8762
- 你的消息是:hi,Ribbon 端口号:8763
请求成功则表示已成功实现了负载均衡功能来访问不同端口的实例。
架构
- eureka-server服务注册中心,端口号为:
8761
- eureka-client服务提供者,运行了两个实例,端口号为:
8762
,8763
- eureka-consumer-ribbon服务消费者,端口号为:
8764
- eureka-consumer-ribbon通过
RestTemplate
调用eureka-client
接口时因为启用了负载均衡,所以会轮流调用它的8762
和8763
端口
源码地址
Github: https://github.com/yeshang5/springcloud-example