在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的。Spring cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。在这一篇文章首先讲解下基于ribbon+rest。

一、前言

Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于 Netflix Ribbon 实现。 通过 Spring Cloud 的封装, 可以让我们轻松地将面向服务的 REST 模板请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、 配置中心、 API 网关那样需要独立部署, 但是它几乎存在于每一个Spring Cloud 构建的微服务和基础设施中。 因为微服务间的调用,API 网关的请求转发等内容实际上都是通过Ribbon 来实现的,包括后续我们将要介绍的 Feign, 它也是基于 Ribbon实现的工具。

二、Ribbon

ribbon是一个负载均衡客户端,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon。

而之前用的nginx来实现负载均衡,他是一种服务端的负载均衡。

集成Ribbon也是比较简单的。新建一个项目spring-cloud-eureka-ribbon

2.1 引入依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>

2.2 然后就是注册一个专门负载均衡的一个客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudEurekaApplication {

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

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

在工程的启动类中,通过@EnableDiscoveryClient向服务中心注册;并且向程序的ioc注入一个bean: restTemplate;并通过@LoadBalanced注解表明这个restRemplate开启负载均衡的功能。

2.3 配置文件

就是向注册中心集群注册而已。所以,上章中提到的Eureka两个服务端要启动起来。

1
2
3
4
5
6
7
8
9
server:
port: 8082
spring:
application:
name: eureka-ribbon
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka

2.4 测试的controller

这个ribbon来接收请求,然后由他来决定转发到哪个服务。

所以这里要启动起来两个服务,让我来实际调用,我们就给他一个最简单的功能:打印出来端口。

1
2
3
4
5
6
7
8
9
10
11
@RestController
public class HelloController {
@Value("${server.port}")
private String port;

@RequestMapping("hello")
public String hello(@RequestParam("name")String name){
return "hi "+ name +",you are from " + port;
}

}

然后在我的ribbon中写一个controller作为一个统一的入口:

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class HelloController {

@Autowired
private IHelloServie helloServie;

@RequestMapping("hello")
public String hello(@RequestParam("name")String name){
return helloServie.hiService(name);
}

}

具体的service就是用刚才定义的restTemplate来根据服务实例的名称去发起调用:

1
2
3
4
5
6
7
8
9
10
11
@Service
public class HelloServiceImpl implements IHelloServie {

@Autowired
RestTemplate restTemplate;

@Override
public String hiService(String name) {
return restTemplate.getForObject("http://SERVICE-HI/hello?name="+name,String.class);
}
}

2.5 页面测试

浏览器输入http://localhost:8082/hello?name=sunweiguo,不停地刷新,我们会看到轮流显示:

hi sunweiguo,you are from 8080hi sunweiguo,you are from 8081这两句,说明负载均衡已经生效,并且算法是轮询。当然,我们也可以用其他的负载均衡算法。这里就不做演示了。