关注“蛋皮皮”公众号,回复“666”获取独家整理的学习视频资料!
Ribbon简介
简单的说,Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon 会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用 Ribbon 实现自定义的负载均衡算法。
RestTemplate的使用
RestTemplate是一个HTTP客户端,使用它我们可以方便的调用HTTP接口,支持GET、POST、PUT、DELETE等方法。
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);
getForObject方法
@GetMapping("/{id}") public CommonResult getUser(@PathVariable Long id) { return restTemplate.getForObject(userServiceUrl + "/user/{1}", CommonResult.class, id); }
getForEntity方法
//返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头、响应状态码、响应体等 @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); } }
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);
postForObject示例
@PostMapping("/create") public CommonResult create(@RequestBody User user) { return restTemplate.postForObject(userServiceUrl + "/user/create", user, CommonResult.class); }
postForEntity示例
@PostMapping("/create") public CommonResult create(@RequestBody User user) { return restTemplate.postForEntity(userServiceUrl + "/user/create", user, CommonResult.class).getBody(); }
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);
PUT请求示例
@PutMapping("/update") public CommonResult update(@RequestBody User user) { restTemplate.put(userServiceUrl + "/user/update", user); return new CommonResult("操作成功",200); }
DELETE请求方法
void delete(String url, Object... uriVariables); void delete(String url, Map<String, ?> uriVariables); void delete(URI url);
DELETE请求示例
@DeleteMapping("/delete/{id}") public CommonResult delete(@PathVariable Long id) { restTemplate.delete(userServiceUrl + "/user/delete/{1}", null, id); return new CommonResult("操作成功",200); }
创建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>
添加配置文件
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常用接口
package com.macro.cloud.controller; import com.macro.cloud.domain.CommonResult; import com.macro.cloud.domain.User; import com.macro.cloud.service.UserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; /** * Created by danpipi. */ @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模块,调用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>
配置文件
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负载均衡
package com.macro.cloud.config; 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; /** * Created by 蛋皮皮 on 2020/8/29. */ @Configuration public class RibbonConfig { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } }
UserRibbonController
package com.macro.cloud.controller; import com.macro.cloud.domain.CommonResult; import com.macro.cloud.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; /** * Created by 蛋皮皮 on 2020/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); } }
启动后调用接口测试http://localhost:8301/user/1
Ribbon的常用配置
#全局配置
ribbon:
ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
OkToRetryOnAllOperations: true #对超时请求启用重试机制
MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
MaxAutoRetries: 1 # 切换实例后重试最大次数
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法
指定服务配置
user-service: ribbon: ConnectTimeout: 1000 #服务请求连接超时时间(毫秒) ReadTimeout: 3000 #服务请求处理超时时间(毫秒) OkToRetryOnAllOperations: true #对超时请求启用重试机制 MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数 MaxAutoRetries: 1 # 切换实例后重试最大次数 NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法
使用到的模块
springcloud-learning ├── eureka-server -- eureka注册中心 ├── user-service -- 提供User对象CRUD接口的服务 └── ribbon-service -- ribbon服务调用测试服务