Spring Cloud Ribbon -- 服务负载均衡

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 的实现类

你可能感兴趣的:(Spring Cloud Ribbon -- 服务负载均衡)