Spring Cloud Ribbon:负载均衡的服务调用
Spring Cloud Ribbon 是Spring Cloud Netflix 子项目的核心组件之一,主要给服务间调用及API网关转发提供负载均衡的功能,本文将对其用法进行详细介绍
Ribbon简介
Ribbon 是 Netflix 公司开源的一个用于负载均衡的客户端组件,它是 Spring Cloud 生态系统中的一部分;Ribbon 的主要目标是提供一种简单且可定制的负载均衡解决方案,用于在微服务架构中实现服务之间的调用和负载均衡
RestTemplate
RestTemplate 是 Spring Framework 提供的一个用于进行 HTTP 请求的客户端工具类;简化了在 Java 应用程序中进行 HTTP 通信的过程,并提供了丰富的方法来处理请求和响应
RestTemplate 提供了各种方法来执行不同类型的 HTTP 请求,包括 GET、POST、PUT、DELETE 等;支持发送请求并接收响应的各种数据类型,如字符串、字节数组、JSON 对象等
GET请求方法
<T> T getForObject(String url, Class<T> responseType, Object... uriVariables);
<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables);
<T> T getForObject(URI url, Class<T> responseType);
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables);
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables);
<T> ResponseEntity<T> getForEntity(URI var1, Class<T> responseType);
POST请求方法
<T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables);
<T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables);
<T> T postForObject(URI url, @Nullable Object request, Class<T> responseType);
<T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables);
<T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables);
<T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType);
PUT请求方法
void put(String url, @Nullable Object request, Object... uriVariables);
void put(String url, @Nullable Object request, Map<String, ?> uriVariables);
void put(URI url, @Nullable Object request);
DELETE请求方法
void delete(String url, Object... uriVariables);
void delete(String url, Map<String, ?> uriVariables);
void delete(URI url);
创建user-service模块
创建user-service,用于给Ribbon提供服务调用
- 添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
- 添加application.yml配置
server: port: 8201 spring: application: name: user-service eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://localhost:8001/eureka/
- 添加UserController用于提供调用接口
/** * Created by macro on 2019/8/29. */ @RestController @RequestMapping("/user") public class UserController { private Logger LOGGER = LoggerFactory.getLogger(this.getClass()); @Autowired private UserService userService; @PostMapping("/create") public CommonResult create(@RequestBody User user) { userService.create(user); return new CommonResult("操作成功", 200); } @GetMapping("/{id}") public CommonResult<User> getUser(@PathVariable Long id) { User user = userService.getUser(id); LOGGER.info("根据id获取用户信息,用户名称为:{}",user.getUsername()); return new CommonResult<>(user); } @GetMapping("/getUserByIds") public CommonResult<List<User>> getUserByIds(@RequestParam List<Long> ids) { List<User> userList= userService.getUserByIds(ids); LOGGER.info("根据ids获取用户信息,用户列表为:{}",userList); return new CommonResult<>(userList); } @GetMapping("/getByUsername") public CommonResult<User> getByUsername(@RequestParam String username) { User user = userService.getByUsername(username); return new CommonResult<>(user); } @PostMapping("/update") public CommonResult update(@RequestBody User user) { userService.update(user); return new CommonResult("操作成功", 200); } @PostMapping("/delete/{id}") public CommonResult delete(@PathVariable Long id) { userService.delete(id); return new CommonResult("操作成功", 200); } }
创建ribbon-service模块
创建ribbon-service模块调用user-service模块演示负载均衡的服务调用
- 添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
- 配置application.yml
配置端口、注册中心地址及user-service的调用路径
server: port: 8301 spring: application: name: ribbon-service eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://localhost:8001/eureka/ service-url: user-service: http://user-service
负载均衡
- @LoadBalanced注解赋予RestTemplate负载均衡的能力
/** * Created by macro on 2019/8/29. */ @Configuration public class RibbonConfig { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } }
- 添加UserRibbonController类
注入RestTemplate,使用其调用user-service中提供的相关接口
/** * Created by macro on 2019/8/29. */ @RestController @RequestMapping("/user") public class UserRibbonController { @Autowired private RestTemplate restTemplate; @Value("${service-url.user-service}") private String userServiceUrl; @GetMapping("/{id}") public CommonResult getUser(@PathVariable Long id) { return restTemplate.getForObject(userServiceUrl + "/user/{1}", CommonResult.class, id); } @GetMapping("/getByUsername") public CommonResult getByUsername(@RequestParam String username) { return restTemplate.getForObject(userServiceUrl + "/user/getByUsername?username={1}", CommonResult.class, username); } @GetMapping("/getEntityByUsername") public CommonResult getEntityByUsername(@RequestParam String username) { ResponseEntity<CommonResult> entity = restTemplate.getForEntity(userServiceUrl + "/user/getByUsername?username={1}", CommonResult.class, username); if (entity.getStatusCode().is2xxSuccessful()) { return entity.getBody(); } else { return new CommonResult("操作失败", 500); } } @PostMapping("/create") public CommonResult create(@RequestBody User user) { return restTemplate.postForObject(userServiceUrl + "/user/create", user, CommonResult.class); } @PostMapping("/update") public CommonResult update(@RequestBody User user) { return restTemplate.postForObject(userServiceUrl + "/user/update", user, CommonResult.class); } @PostMapping("/delete/{id}") public CommonResult delete(@PathVariable Long id) { return restTemplate.postForObject(userServiceUrl + "/user/delete/{1}", null, CommonResult.class, id); } }