spring-cloud 负载均衡器 ribbon与loadBalanced(读音 老的瓣兰茨的) 的使用

ribbon

是一个客户端负载均衡器

spring-cloud是微服务的解决方案它会把服务注册到 注册中心 比如nacos 这时我们就可以通过调用nacos的接口让它返回我们想要的模块信息然后把信息拼装成请求地址 再使用调用接口的类比如

1)Httpclient
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 Http 协议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传统 JDK 自带的 URLConnection,提升了易用性和灵活性,使客户端发送 HTTP 请求变得容易,提高了开发的效率。

2)Okhttp
一个处理网络请求的开源项目,是安卓端最火的轻量级框架,由 Square 公司贡献,用于替代 HttpUrlConnection 和 Apache HttpClient。OkHttp 拥有简洁的 API、高效的性能,并支持多种协议(HTTP/2 和 SPDY)。

3)HttpURLConnection
HttpURLConnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送 GET 请求、POST 请求。HttpURLConnection 使用比较复杂,不像 HttpClient 那样容易使用。

4)RestTemplate WebClient
RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。
就可以请求到模块对应的方法上 而ribbon跟loadBalanced给我实现了去注册中心查找模块的信息 然后拼装成请求地址的功能 比如使用RestTemplate只需要给RestTemplate添加一个ribbon的拦截器 我们就不要管 去注册中心查找服务的信息拼装请求地址的业务了 只需要关注我们的业务就可以了

  @Autowired
    LoadBalancerClient loadBalancer;
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
//        return new RestTemplate();
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setInterceptors(Collections.singletonList(new LoadBalancerInterceptor(loadBalancer)));
        return restTemplate;
    }

@Autowired
LoadBalancerClient loadBalancer; 这句代码 如果导入了ribbon依赖会创建RibbonLoadBalancerClient这样的一个实例 然后通过restTemplate.setInterceptors(Collections.singletonList(new LoadBalancerInterceptor(loadBalancer)));这句代码给RestTemplate设置拦截器 设置了拦截器 当我们使用RestTemplate调用接口时会进入ribbon的拦截器 给我解析请求 比如 aa是服务名 请求地址是http://aa/a 就是去访问aa服务中的a接口 这是ribbon会给我把aa当作服务名去注册中心查找这个服务的真实地址 比如127.0.0.1:9090 就会把地址拼接成http://127.0.0.1:9090/a 这样 然后根据这个真实地址去调用服务

Spring-Cloud 整合Ribbon



org.springframework.cloud
spring-cloud-starter-netflix-ribbon

添加@loadBalanced注解

@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    } 

添加了@LoadBalanced这个注解 就是会给RestTemplate添加一个ribbon实现了拦截器 这个拦截器就是去注册中心根据服务名去找地址 然后调用

controller层

@Autowired
private RestTemplate restTemplate;

@RequestMapping(value = "/findOrderByUserId/{id}")
public R  findOrderByUserId(@PathVariable("id") Integer id) {
    // RestTemplate调用
    //String url = "http://localhost:8020/order/findOrderByUserId/"+id;
    //模拟ribbon实现  mall-order是服务名
    //String url = getUri("mall-order")+"/order/findOrderByUserId/"+id;
    // 添加@LoadBalanced  mall-order是服务名
    String url = "http://mall-order/order/findOrderByUserId/"+id;
    R result = restTemplate.getForObject(url,R.class);

    return result;
}

模拟ribbon实现

@Autowired
private RestTemplate restTemplate;

@RequestMapping(value = "/findOrderByUserId/{id}")
public R  findOrderByUserId(@PathVariable("id") Integer id) {
    // RestTemplate调用
    //String url = "http://localhost:8020/order/findOrderByUserId/"+id;
    //模拟ribbon实现
    String url = getUri("mall-order")+"/order/findOrderByUserId/"+id;
    // 添加@LoadBalanced
    //String url = "http://mall-order/order/findOrderByUserId/"+id;
    R result = restTemplate.getForObject(url,R.class);
    return result;
}

@Autowired
private DiscoveryClient discoveryClient;
public String getUri(String serviceName) {
    List serviceInstances = discoveryClient.getInstances(serviceName);
    if (serviceInstances == null || serviceInstances.isEmpty()) {
        return null;
    }
    int serviceSize = serviceInstances.size();
    //轮询
    int indexServer = incrementAndGetModulo(serviceSize);
    return serviceInstances.get(indexServer).getUri().toString();
}
private AtomicInteger nextIndex = new AtomicInteger(0);
private int incrementAndGetModulo(int modulo) {
    for (;;) {
        int current = nextIndex.get();
        int next = (current + 1) % modulo;
        if (nextIndex.compareAndSet(current, next) && current < modulo){
            return current;
        }
    }
}

Ribbon扩展点

参考: org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
IClientConfig:Ribbon的客户端配置,默认采用DefaultClientConfigImpl实现。
IRule:Ribbon的负载均衡策略,默认采用ZoneAvoidanceRule实现,该策略能够在多区域环境下选出最佳区域的实例进行访问。
IPing:Ribbon的实例检查策略,默认采用DummyPing实现,该检查策略是一个特殊的实现,实际上它并不会检查实例是否可用,而是始终返回true,默认认为所有服务实例都是可用的。
ServerList:服务实例清单的维护机制,默认采用ConfigurationBasedServerList实现。
ServerListFilter:服务实例清单过滤机制,默认采ZonePreferenceServerListFilter,该策略能够优先过滤出与请求方处于同区域的服务实例。
ILoadBalancer:负载均衡器,默认采用ZoneAwareLoadBalancer实现,它具备了区域感知的能力。

Spring Cloud LoadBalancer

LoadBalancer是spring cloud官方用来替代ribbon的

提供了两个客户端

RestTemplate

RestTemplate是spring提供的用来访问http服务的工具类 可以提高编程效率

WebClient

非阻塞的基于响应式编程的进行Http请求的客户端工具。

RestTemplate整合LoadBalancer



    org.springframework.cloud
    spring-cloud-starter-loadbalancer




    org.springframework.boot
    spring-boot-starter-web




    com.alibaba.cloud
    spring-cloud-starter-alibaba-nacos-discovery
    
        
            org.springframework.cloud
            spring-cloud-starter-netflix-ribbon
        
    

在yml文件中设置不适用ribbon即可

spring:
  application:
    name: mall-user-loadbalancer-demo
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    # 不使用ribbon
    loadbalancer:
      ribbon:
        enabled: false

使用@LoadBalanced配置RestTemplate

@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

使用

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private RestTemplate restTemplate;

@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
    String url = "http://mall-order/order/findOrderByUserId/"+id;
    R result = restTemplate.getForObject(url,R.class);
    return result;
}
}

WebClient整合LoadBalancer

引入依赖



    org.springframework.cloud
    spring-cloud-starter-loadbalancer




    org.springframework.boot
    spring-boot-starter-webflux




    com.alibaba.cloud
    spring-cloud-starter-alibaba-nacos-discovery
    
        
            org.springframework.cloud
            spring-cloud-starter-netflix-ribbon
        
    

配置WebClient作为负载均衡器的client

@Configuration
public class WebClientConfig {

@LoadBalanced
@Bean
WebClient.Builder webClientBuilder() {
    return WebClient.builder();
}

@Bean
WebClient webClient() {
  return webClientBuilder().build();
}
}

使用

@Autowired
private WebClient webClient;

@RequestMapping(value = "/findOrderByUserId2/{id}")
public Mono findOrderByUserIdWithWebClient(@PathVariable("id") Integer id) {

String url = "http://mall-order/order/findOrderByUserId/"+id;
//基于WebClient
Mono result = webClient.get().uri(url)
        .retrieve().bodyToMono(R.class);
return result;
}

使用webFlux

@Autowired
private ReactorLoadBalancerExchangeFilterFunction lbFunction;

@RequestMapping(value = "/findOrderByUserId3/{id}")
public Mono findOrderByUserIdWithWebFlux(@PathVariable("id") Integer id) {

String url = "http://mall-order/order/findOrderByUserId/"+id;
//基于WebClient+webFlux
Mono result = WebClient.builder()
        .filter(lbFunction)
        .build()
        .get()
        .uri(url)
        .retrieve()
        .bodyToMono(R.class);
return result;
}

你可能感兴趣的:(个人学习,负载均衡,ribbon,spring,cloud)