栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

ribbon

是一个客户端负载均衡器

spring-cloud把服务注册到 注册中心比如nacos 我们要的服务地址只需要写模块名 就可以掉到对应的服务上 这么个功能 ribbon给我们实现了 也就是当我们调用服务时 要先去注册中心找服务的地址 为了只关心业务 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;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/338087.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号