摘自 方志朋博客(http://blog.csdn.net/forezp/article/details/69788938) ;
在微服务架构中,业务都会被拆成一个个独立的服务,服务与服务的通讯是基于http restful 的;
spring cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign。
Ribbon是一个基于HTTP和TCP客户端的负载均衡器,其实feign也使用了ribbon, 只要使用@FeignClient时,ribbon就会自动使用。
先梳理一下 ribbon + restTemplate ;
一. ribbon 简介
Ribbon is a client side load balancer which gives you a lot of control over the behaviour of HTTP and TCP clients. Feign already uses Ribbon, so if you are using @FeignClient then this section also applies. —–摘自官网
二.准备
ribbon的作用是用于负载均衡,所以必须要有服务发现组件。同案例eureka
2.1 建立服务注册中心 eureka-server;端口:8761;启动工程;
2.2 创建服务提供者 eureka-client,name为:service-hi ; 端口:8762;启动工程;
2.3 将service-hi的端口号改成8763,启动工程;
(在运行框的右下角有一个向下的三角形,点开,选择 edit configuration--将右上角的single instance only勾选掉,就可以同时运行两个不同端口的同名服务)
此时,运行 http://localhost:8761,可以看到上面同时注册了名为service-hi的两个服务;

三. 建立服务消费者
3.1 新建一个springboot 的module,取名为 service-ribbon;
3.2 导包(勾选上web + cloud discovery / Eureka Discovery 即可少导这两个包)

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
3.3 配置其applicationyaml ;名称 service-ribbon 端口:8764;如下:
server:
port: 8764
spring:
application:
name: service-ribbon
eureka:
client:
serviceUrl:
defaultzone: http://localhost:8761/eureka/
3.4 在工程的启动类中 通过@EnableDiscoveryClient 向服务中心注册服务; 注入bean:RestTemplate; 通过@LoadBalanced注解表明这个restTemplate开启负载均衡功能;
@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.5 写一个测试类HelloService,通过注入容器的restTemplate来消费service-hi服务的 /hi 接口。(此处我们直接用程序名service-hi代替了具体的url地址,在ribbon中它会根据服务名来选择具体的服务实例,根据服务实例在请求的时候会用具体的url替换服务名)(注意:SERVICE-HI 服务名必须大写)
@Service
public class HelloService {
@Autowired
private RestTemplate restTemplate;
public String hiService(String name){
return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
}
}
3.6 写一个controller,在controller中调用service的方法
@RestController
public class HelloController {
@Autowired
HelloService helloService;
@RequestMapping("/hi")
public String hi(@RequestParam String name){
return helloService.hiService(name);
}
}
3.7 测试 : 在浏览器中多次访问 http://localhost:8764/hi?name=zdj , 浏览器会交替出现 :
hi, i am from port : 8763 hi, i am from port : 8762
这说明,当我们通过调用 restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class)的方法时,已经做了负载均衡,访问了不同的端口的服务实例。
3.8 分析

service-hi工程跑了两个实例,端口分别为8762,8763,分别向服务注册中心注册
sercvice-ribbon端口为8764,向服务注册中心注册
当sercvice-ribbon通过restTemplate调用service-hi的hi接口时,因为用ribbon进行了负载均衡,会轮流的调用service-hi:8762和8763 两个端口的hi接口;
注:
在service中调用restTemplate.getForObject("http://SERVICR-HI/hi?name="+name,String.class)时候,访问路径注意写清楚,而且 SERVICE-HI必须大写!
restTemplate.getForObject("http://SERVICR-HI/hi?name="+name,String.class) 标注部分指的是eureka-client的访问路径,如果在测试ribbon的@RequestMapping("/hello"),此处的写法仍然是 /hi (因为eureka-client 的是访问路径没变,仍是 http:// ip:port/hi )