spring cloud学习之服务消费者Ribbon和Feign
文章中涉及到的源码已上传github:https://github.com/BLF2/SpringCloud
Ribbon
Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。
创建服务提供者和服务注册中心
在上一篇文章中详细介绍了服务提供者和服务注册中心的构建,spring cloud 学习之服务提供者和服务注册中心Eureka。现在我们把两个服务提供者和服务注册中心都启动起来。
创建服务消费者
- 新建Module,Group为net.blf2,Artifact为servicecustomerribbon,Project Name为service-consumer-ribbon,依赖选择Ribbon和Spring Web Start,然后Finish创建Module。
- 在包net.blf2.serviceconsumerribbon创建config包,然后创建RibbonConfig类,配置RestTemplate和负载均衡策略,如下:
package net.blf2.serviceconsumerribbon.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RetryRule;
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 RibbonConfig {
@Bean
@LoadBalanced //此注解用来标记这个restTemplate进行客户端负载均衡
public RestTemplate ribbonRestTemplate(){
return new RestTemplate();
}
@Bean
public IRule myRule(){
//轮询调用+超时失败重试策略
return new RetryRule();
}
}
- 在包net.blf2.serviceconsumerribbon创建controller包,添加HomeController类,添加一个测试接口,如下:
package net.blf2.serviceconsumerribbon.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@RestController
@RequestMapping("/ribbon")
public class HomeController {
//调用url 协议+服务名+路径(path)
public static final String URL = "http://SERVICE-PROVIDER/hello/hi";
//注入配置好的restTemplate
@Autowired
private RestTemplate restTemplate;
@GetMapping("/test")
public Map<String,Object> testRibbon(){
return restTemplate.getForObject(URL,Map.class);
}
}
- 启动类添加@EnableEurekaClient注解,用来服务发现,如下:注意@EnableEurekaClient用于Eureka服务注册中心,其它服务注册中心需要使用@EnableDiscoveryClient
package net.blf2.serviceconsumerribbon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ServiceConsumerRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerRibbonApplication.class, args);
}
}
- application.yml(application.properties)配置服务注册中心地址,当前服务名和端口
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9001/eureka/,http://localhost:9002/eureka/
server:
port: 7001
spring:
application:
name: service-consumer-ribbon
测试服务提供者
按照顺序启动服务,顺序为:服务注册中心,服务提供者,服务消费者,打开Postman,测试Ribbon,发送两个请求,结果如下:
(1) 第一次请求返回:
(2) 第二次请求返回:
可以看到轮询策略成功了。
Feign的使用
- 新建一个Module,Group是net.blf2,Artifact是serviceconsumerfeign,Project Name是service-consumer-feign
- 在net.blf2.serviceconsumerfeign下新建包service,然后在service下新建接口FeignClientService,代码如下:
package net.blf2.serviceconsumerfeign.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Map;
//服务提供者的spring.application.name
@FeignClient(value = "SERVICE-PROVIDER")
public interface FeignClientService {
//服务提供者的controller中method的RequestMapping的value值
@GetMapping("/hello/hi")
//服务提供者的controller中method的相同方法名和返回值
//如果有参数,个数,类型,顺序应一致
Map<String,Object> hello();
}
- 在net.blf2.serviceconsumerfeign下新建包controller包,然后在controller下新建类HomeController,添加一个REST接口,代码如下:
package net.blf2.serviceconsumerfeign.controller;
import net.blf2.serviceconsumerfeign.service.FeignClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/feign")
public class HomeController {
@Autowired
private FeignClientService feignClientService;
@GetMapping("/test")
public Map<String,Object> testFeign(){
return feignClientService.hello();
}
}
- 启动类添加@EnableFeignClients和@EnableDiscoveryClient注解,代码如下:
package net.blf2.serviceconsumerfeign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class ServiceConsumerFeignApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerFeignApplication.class, args);
}
}
- application.yml(application.properties)配置如下:
server:
port: 7002
#配置eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9001/eureka,http://localhost:9002/eureka
#服务名称
spring:
application:
name: service-consumer-feign
- 按顺序启动服务注册中心,服务提供者和Feign客户端。
测试
打开Postman,GET请求http://localhost:7002/feign/test,请求两次:
(1)第一次请求:
(2)第二次请求:
可以看到Feign客户端和负载均衡功能正常。
Ribbon和Feign
两者都提供客户端负载均衡功能,Feign中包含Ribbon,在前面的实践中我们发现Feign只需要一个对应服务提供者的接口即可进行对外提供Bean的注入和使用,而Ribbon需要配置RestTemplate。对Feign和Ribbon使用较少,其它区别还需使用过程中和分析源码过程中慢慢发现,欢迎补充。