摘自 方志朋博客(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 )