Spring Cloud Ribbon 负载均衡

      Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTPTCP的客户端负载均衡器。它可以通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的作用。

服务端负载均衡

       负载均衡主要是实现对系统的高可用、网络压力的缓解、处理能力的伸缩。对于数据流量过大,往往单一设备是无法承担的,需要多台的设计进行分流。

1.软负载均衡

  在一台机器上安装附加的某种软件,如nginx负载均衡配置简单、成本低。根据部署的应用于系统的状态来分配资源进行负载、负载的能力不过受限于机器本身,性能越好,负载能力越大。

2.硬负载均衡

  通过服务器和外部网络间安装负载均衡的设备,称为"负载均衡器",硬件的负载均衡在功能上、性能上往往高于软负载均衡不过价格昂贵,例:F5负载均衡器。能够通过智能交换机来实现负载,负载的能力与系统、应用无关,主要是通过网络层来判断,比如某时候系统处理能力已经不行了,但是可以通过网络来进行分配,成本高,除设备价格高昂,而且配置冗余.很难想象后面服务器做一个集群,但最关键的负载均衡设备却是单点配置;无法有效掌握服务器及应用状态

服务端负载均衡都能以类似下图的架构方式构建起来:

 

在微服务架构中使用客户端负载均衡的使用只需要两步:

1.服务提供者启动多个服务 注册到服务注册中心同一个实例。

2.服务消费者通过使用注解的方式修饰RestTemplate实现向服务的接口进行调用。

package com.spring.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class App {

    //实例化ribbon使用的RestTemplate 
    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}

 

RestTemplate详解

RestTemplate对象会使用Ribbon的自动化配置,同时通过配置@LoadBalanced还能够开启客户端负载均衡。

GET请求

 第一种:getForEntity函数

访问USER-SERVER服务的/user请求,同时最后一个参数didi会替换url中的{1}占位符,而返回的ResponseEntity对象中的body内容类型会根据第二个参数转换为String类型。

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://USER-SERVICE/user?name={1}",String.class,"didi");
String body = responseEntity.getBody();

 若我们希望返回的body是一个User对象类型,也可以:

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<User> responseEntity = restTemplate.getForEntity("http://USER-SERVICE/user?name={1}",User.class,"didi");
User body = responseEntity.getBody();

getForEntity函数实际上提供了以下三种不同的重载实现:

getForEntity(String url,Class responseType,Object... urlVariables);

getForEntity(String url,Class responseType,Map urlVariables);

getForEntity(URI url,Class responseType);

 第二种:getForObject函数

该方法可以理解为对getForEntity的进一步封装,它通过HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。

RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri,String.class);

当body是一个User对象时,可以这样实现:

RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri,User.class);

getForObject函数提供了三种不同的重载实现:

getForObject(String url,Class responseType,Object... urlVariables);

getForObject(String url,Class responseType,Map urlVariables);

getForObject(URI url,Class responseType);

POST请求

对POST请求可以通过三个方法进行调用。

第一种:postForEntity函数。

post请求:

@PostMapping("/queryLoginPrivilegeByUser")
 public List<String> queryLoginPrivilegeByUser(@RequestBody User user){
        List<String> menulist = restTemplate.postForEntity("http://localhost:8080/queryLoginPrivilegeByUser",user,List.class).getBody();
        return menulist;
}


@PostMapping("/queryLoginPrivilegeByUser2")
public List<String> queryLoginPrivilegeByUser2(@RequestBody User user){
        UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://localhost:8080/queryLoginPrivilegeByUser").build();
        URI uri = uriComponents.toUri();
        List<String> menulist = restTemplate.postForEntity(uri,user,List.class).getBody();
        return menulist;
}

postForEntity函数提供了三种不同的重载实现:

@Override
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}


@Override
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}


@Override
public <T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor);
}

第二种:postForObject函数。

该方法可以理解为对getForEntity的进一步封装,它通过org.springframework.web.client.HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。

@PostMapping("/queryUserByPrivilege")
public User queryUserByPrivilege(@RequestParam String privilege){
        HttpHeaders headers = new HttpHeaders();

        MultiValueMap<String, Object> parammap = new LinkedMultiValueMap<>();
        parammap.add("privilege",privilege);
        
        HttpEntity<Map> entity = new HttpEntity<>(parammap,headers);
        
        User user = restTemplate.postForObject(userService+"/queryUserByPrivilege",entity,User.class);
        return user;
}

postForObject函数提供了三种不同的重载实现:

@Override
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        HttpMessageConverterExtractor<T> responseExtractor =
                new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}


@Override
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
            throws RestClientException {

        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        HttpMessageConverterExtractor<T> responseExtractor =
                new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}


@Override
public <T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        HttpMessageConverterExtractor<T> responseExtractor =
                new HttpMessageConverterExtractor<T>(responseType, getMessageConverters());
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor);
}

第三种:postForLocation函数。

该方法实现了以post提交资源,返回新资源的URI。

@PostMapping("/queryLoginPrivilegeByUser3")
public void queryLoginPrivilegeByUser3(@RequestBody User user){
        URI uri = restTemplate.postForLocation("http://localhost:8080/queryLoginPrivilegeByUser",user);
        System.out.println("uri=="+uri);

}

postForLocation函数提供了三种不同的重载实现:

@Override
public URI postForLocation(String url, Object request, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
        return headers.getLocation();
}


@Override
public URI postForLocation(String url, Object request, Map<String, ?> uriVariables) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
        return headers.getLocation();
}


@Override
public URI postForLocation(URI url, Object request) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor());
        return headers.getLocation();
}

PUT请求

在RestTemplate中,对PUT请求可以通过put方法实现,比如:

RestTemplate restTemplate = new RestTemplate();
Long id = 1000L;
User user = new User("age",40);
restTemplate.put("http://USER-SERVICE/user/{1}",user,id);

put函数也实现了三种不同的重载方法:

@Override
public void put(String url, Object request, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        execute(url, HttpMethod.PUT, requestCallback, null, uriVariables);
}


@Override
public void put(String url, Object request, Map<String, ?> uriVariables) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        execute(url, HttpMethod.PUT, requestCallback, null, uriVariables);
}


@Override
public void put(URI url, Object request) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        execute(url, HttpMethod.PUT, requestCallback, null);
}

DELETE请求

在RestTemplate中,对DELETE请求可以通过delete方法实现,比如:

RestTemplate restTemplate = new RestTemplate();
Long id = 1000L;
restTemplate.delete("http://USER-SERVICE/user/{1}",id);

delete函数也有三种不同的重载方法:

@Override
public void delete(String url, Object... uriVariables) throws RestClientException {
        execute(url, HttpMethod.DELETE, null, null, uriVariables);
}


@Override
public void delete(String url, Map<String, ?> uriVariables) throws RestClientException {
        execute(url, HttpMethod.DELETE, null, null, uriVariables);
}


@Override
public void delete(URI url) throws RestClientException {
        execute(url, HttpMethod.DELETE, null, null);
}

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值