在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于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 8080
和hi sunweiguo,you are from 8081
这两句,说明负载均衡已经生效,并且算法是轮询。当然,我们也可以用其他的负载均衡算法。这里就不做演示了。