Spring Cloud Ribbon:封装于Netflix Ribbon, [ˈrɪbən],带状物
功能:负载均衡(服务选取)
原理:@LoadBalanced、@FeignClient 底层都调用了Ribbon组件
服务调用之 RestTemplate
方式一:使用 LoadBalancerClient 选取服务实例
@Autowired
private LoadBalancerClient lbc; // Eureka Client 应用的容器中 有 这个 Bean
RestTemplate rt = new RestTemplate();
ServiceInstance si = lbc.choose("SERVICE_NAME"); // 选取服务实例
String url = String.format("http://%s:%s",si.getHost(), si.getPort()) + "/api";
String response = rt.getForObject(url, String.class); // 使用RestTemplate 调用服务
方式二:使用 @LoadBalanced 选取服务实例
1、装配 RestTemplate
@Component
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(60*60*1000); // 提交超时时间
requestFactory.setReadTimeout(60*60*1000); // 下载超时时间
RestTemplate restTemplate = new RestTemplate(requestFactory);
restTemplate.getMessageConverters().add(new FastJsonHttpMessageConverter()); // 格式转换器
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); // Charset.forName("GBK")
return restTemplate;
}
}
2、使用
@Autowired
private RestTemplate restTemplate;
/* Get请求 */
// 得到对象,Response 为自定义的POJO;要求response body 得是JSON格式,否则 Response 只能是 String
Response response = restTemplate.getForObject(url, Response.class);
// 或者 直接用 JSONObject 来接
JSONObject response = restTemplate.getForObject(url, JSONObject.class);
// 无论response body是什么格式,都可以用String来接,进而可以转成 JSONObject
String response = restTemplate.getForObject(url, String.class);
JSONObject jsonObject = JSONObject.parseObject(response);
// 得到ResponseEntity,包含response header 和 response body,其中body被转换成 Response 实例
ResponseEntity responseEntity = restTemplate.getForEntity(url, Response.class);
// 得到数组
Response[] responses = restTemplate.getForObject(url, Response[].class);
/* Put请求,Get请求带header */
HttpHeaders headers = new HttpHeaders();
// 传给 HttpEntity 的请求体可以是 JSONObject
HttpEntity requestEntity = new HttpEntity(jsonObject , headers);
ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.PUT, requestEntity, JSONObject.class);
JSONObject response = responseEntity.getBody();
/* Post请求,提交表单 */
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap map= new LinkedMultiValueMap();
map.add("filed_1", "**");
// 传给 HttpEntity 的请求体可以是 MultiValueMap
HttpEntity> requestEntity = new HttpEntity(map, headers);
// 发送MultiValueMap,得到对象,同getForObject
Response response = restTemplate.postForObject(url, requestEntity, Response.class);
// 得到Entity,同getForEntity
ResponseEntity responseEntity = restTemplate.postForEntity(url, requestEntity, Response.class);
/* Post请求,提交带文件表单 */
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap map= new LinkedMultiValueMap();
File file = new File(); // 待发送的文件
FileSystemResource fileResource = new FileSystemResource(file);
map.add("file", fileResource);
HttpEntity> requestEntity = new HttpEntity(map, headers);
Response response = restTemplate.postForObject(url, requestEntity, Response.class);
/* Post请求,提交JSON格式 */
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 可以明确指定 Accept
List acceptList = new ArrayList<>(1);
acceptList.add(MediaType.APPLICATION_JSON);
headers.setAccept(acceptList);
// 发送 HttpEntity 包装的 JSON(用ObjectNode 或 JSONObject 实现)
ObjectNode objectNode = new ObjectMapper().createObjectNode();
objectNode.put("field_1", "**");
// 传给 HttpEntity 的请求体可以是 JSON字符串
HttpEntity requestEntity = new HttpEntity(objectNode.toString(), headers);
Response response = restTemplate.postForObject(url, requestEntity, Response.class);
// 或者 直接发送ObjectNode 或 JSONObject实例,默认的 content-type 就是 application/json
Response response = restTemplate.postForObject(url, objectNode, Response.class);
// 传给 HttpEntity 的请求体可以是 POJO实例
HttpEntity requestEntity = new HttpEntity(request, headers);
Response response = restTemplate.postForObject(url, requestEntity, Response.class);
// 或者 直接发送POJO实例,默认的 content-type 就是 application/json
Response response = restTemplate.postForObject(url, request, Response.class);
/*Post请求,提交XML格式*/
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity requestEntity = new HttpEntity<>(xml, headers);
// 发送 xml 字符串
ResponseEntity responseEntity = restTemplate.postForObject(url, requestEntity, Response.class);
服务调用之 OpenFein
1、配置Maven依赖
org.springframework.cloud
spring-cloud-starter-openfeign
2.0.2.RELEASE
2、注解主类:@EnableFeignClients
3、定义Fein Client 接口
@FeignClient(name= "Eureka-Client") // 服务名不支持下划线
public interface Client {
// 与Controller里的写法相同
@GetMapping("/my/send2") // @GetMapping相当于@RequestMapping( method=RequestMethod.GET)
String getMsg();
}
4、调用
@Autowired
private Client client;
String response = client.getMsg();
负载均衡算法
配置 application.yml
SERVICE_NAME:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 默认为轮询,这里改成随机
ribbon负载均衡算法实现类查找方法:IRule 的实现类