亚洲一区精品自拍_2021年国内精品久久_男同十八禁gv在线观看_免费观看a级性爱黄片

Article / 文章中心

微服務(wù)4.1 基于 Ribbon 負(fù)載均衡詳解

發(fā)布時(shí)間:2022-01-26 點(diǎn)擊數(shù):870

前言

參考資料
《Spring Microservices in Action》
《Spring Cloud Alibaba 微服務(wù)原理與實(shí)戰(zhàn)》
《B站 尚硅谷 SpringCloud 結(jié)構(gòu)開(kāi)發(fā)教程 周陽(yáng)》

Spring Cloud Ribbon 是根據(jù) Netflix Ribbon 完成的一套客戶端負(fù)載均衡的工具;供給客戶端的軟件負(fù)載均衡算法和服務(wù)調(diào)用;


1. Ribbon 基礎(chǔ)常識(shí)

1.1 Ribbon 是什么

  • Spring Cloud Ribbon 是根據(jù) Netflix Ribbon 完成的一套客戶端負(fù)載均衡的工具;供給客戶端的軟件負(fù)載均衡算法和服務(wù)調(diào)用;
  • Ribbon 客戶端組件供給一系列完善的裝備項(xiàng)如銜接超時(shí),重試等。簡(jiǎn)略的說(shuō),就是在裝備文件中列出 Load Balancer(簡(jiǎn)稱LB)后面一切的機(jī)器,Ribbon 會(huì)主動(dòng)根據(jù)某種規(guī)則(如簡(jiǎn)略輪詢,隨機(jī)銜接等)去銜接這些機(jī)器;
  • 能夠很容易運(yùn)用Ribbon完成自界說(shuō)的負(fù)載均衡算法;

1.2 與 Ribbon 交互的三種等級(jí)層次

  • Spring DiscoveryClient:供給了對(duì) Ribbon 和 Ribbon 中緩存的注冊(cè)服務(wù)的最低層次拜訪;
  • 啟用了 RestTemplate 的 Spring DiscoveryClient;
  • Netflix Feign 客戶端;

1.3 Ribbon在作業(yè)時(shí)分成兩步

Ribbon 架構(gòu)圖

  • 第一步先挑選 EurekaServer,它優(yōu)先挑選在同一個(gè)區(qū)域內(nèi)負(fù)載較少的 server;

第二步再根據(jù)用戶指定的戰(zhàn)略,在從 server 取到的服務(wù)注冊(cè)列表中挑選一個(gè)地址;

1.4 服務(wù)的供給者與顧客

  • 供給者:服務(wù)供給者將自己注冊(cè)進(jìn)注冊(cè)中心,讓顧客發(fā)現(xiàn);在本例中有多個(gè)供給者給顧客供給服務(wù);
  • 顧客:顧客運(yùn)用服務(wù)發(fā)現(xiàn),找到供給者并調(diào)用供給者服務(wù);在本例中只要一個(gè)顧客在多個(gè)供給者中選出一個(gè)為自己服務(wù);

1.5 Ribbon 中心組件 IRule

IRule 負(fù)載均衡

  • 根據(jù)特定算法中從服務(wù)列表中選取一個(gè)要拜訪的服務(wù);
  • 界說(shuō)了負(fù)載均衡的方式;
  • 有以下幾種負(fù)載均衡的完成方式:

    • RoundRobinRule:輪詢;
    • RandomRule:隨機(jī);
    • RetryRule:先依照 RoundRobinRule 的戰(zhàn)略獲取服務(wù),假如獲取服務(wù)失利則在指定時(shí)間內(nèi)會(huì)進(jìn)行重試,獲取可用的服務(wù);
    • WeightedResponseTimeRule:對(duì) RoundRobinRule 的擴(kuò)展,響應(yīng)速度越快的實(shí)例挑選權(quán)重越大,越容易被挑選;
    • BestAvailableRule:會(huì)先過(guò)濾掉由于多次拜訪毛病而處于斷路器跳閘狀態(tài)的服務(wù),然后挑選一個(gè)并發(fā)量最小的服務(wù);
    • AvailabilityFilteringRule:先過(guò)濾掉毛病實(shí)例,再挑選并發(fā)較小的實(shí)例;
    • ZoneAvoidanceRule:默許規(guī)則,復(fù)合判別 server 所在區(qū)域的性能和 server 的可用性挑選服務(wù)器;


2. 服務(wù)顧客獲取供給者的三個(gè)層次示例

2.1 引進(jìn) pom.xml 依靠

<dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-ribbonartifactId> dependency>
  • 假如運(yùn)用 Eureka 作為注冊(cè)中心,則不必引進(jìn)該依靠,因?yàn)?Eureka 的依靠里包含 ribbon 相關(guān)依靠 jar 包;

2.2 運(yùn)用 Spring DiscoveryClient 查找服務(wù)實(shí)例

2.2.1 在主程序類上增加注解

  • @EnableDiscoveryClient:表明能夠被注冊(cè)中心發(fā)現(xiàn)。是 Sring Cloud 的觸發(fā)器,其作用是使應(yīng)用程序能夠運(yùn)用 DiscoveryClient 和 Ribbon 庫(kù);

2.2.2 運(yùn)用 DiscoveryClient 查找信息

在服務(wù)顧客的 client 包下;
@Component public class ProviderDiscoveryClient { //主動(dòng)注入 DiscoveryClient 類,該類用于與 Ribbon 交互 @Autowired private DiscoveryClient discoveryClient; public Provide getProvide(String providerId) {
        RestTemplate restTemplate = new RestTemplate(); //獲取服務(wù)供給者的一切實(shí)例列表,ServiceInstance 用于保存關(guān)于服務(wù)的特定實(shí)例(包含主機(jī)名、端口荷 URL) Listinstances = discoveryClient.getInstances("provider-instance-name"); if (instances.size()==0) return null; //檢索要調(diào)用的服務(wù)端點(diǎn) String serviceUri = String.format("%s/providers/%s",instances.get(0).getUri().toString(), providerId); //運(yùn)用標(biāo)準(zhǔn)的 Spring REST 模板類去調(diào)用服務(wù) ResponseEntity< provider > restExchange =
                restTemplate.exchange(
                        serviceUri,
                        HttpMethod.GET, null, Provider.class, providerId); return restExchange.getBody();
    }
}
  • 這種方法存在以下問(wèn)題:

    • 沒(méi)有利用 Ribbon 的客戶端負(fù)載均衡,調(diào)用哪個(gè)服務(wù)實(shí)例需要開(kāi)發(fā)人員界說(shuō);
    • 開(kāi)發(fā)人員有必要構(gòu)建一個(gè)用來(lái)調(diào)用服務(wù)的 URL;
    • 實(shí)例化 ResTemplate 類,不符合 Spring IoC 標(biāo)準(zhǔn);
  • 結(jié)合本篇《5. 本地負(fù)載均衡器的完成(顧客)》即可用到客戶端負(fù)載均衡,即:開(kāi)發(fā)人員界說(shuō)了本地負(fù)載均衡器來(lái)完成了負(fù)載均衡;

2.3 運(yùn)用帶有 Ribbon 功用的 Spring RestTemplate 調(diào)用服務(wù)

2.3.1 在主程序類上增加注解

@SpringBootApplication //只需要這個(gè)注解即可 public class Application { @LoadBalanced //告訴 Spring Cloud 創(chuàng)建一個(gè)支撐 Ribbon 的 RestTemplate @Bean public RestTemplate getRestTemplate(){ return new RestTemplate();
  } public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
  }
}
  • Spring Cloud 前期版本中,RestTemplate 類默許主動(dòng)支撐 Ribbon;
  • 自從 Spring Cloud 發(fā)布 Angel 版本后,Spring Cloud 中的 RestTemplate 不再支撐 Ribbon;
  • 因而,后續(xù)版本有必要運(yùn)用 @LoadBalanced 注解顯式標(biāo)示,才能將 Ribbon 和 RestTemplate 一同運(yùn)用;
  • *RestTemplate 不一定放在主程序類里;也能夠在 config 包下新建一個(gè) ApplicationContextConfig 裝備類,將 RestTemplate 放在該類里:
@Configuration public class ApplicationContextConfig{ @Bean @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate();
    }
}

2.3.2 運(yùn)用 Ribbon 的 RestTemplate 來(lái)調(diào)用服務(wù)

在服務(wù)顧客的 client 包下;
@Component public class ProviderRestTemplateClient { //主動(dòng)注入即可,不必實(shí)例化 @Autowired RestTemplate restTemplate; public Provider getProvider(String providerId){
        ResponseEntityrestExchange =
                restTemplate.exchange( //運(yùn)用 Eureka 服務(wù) ID 來(lái)構(gòu)建目標(biāo) URL "http://provider-instance-name/providers/{providerId}",
                        HttpMethod.GET, null, Provider.class, providerId); return restExchange.getBody();
    }
}
  • 通過(guò)運(yùn)用 RestTemplate 類,Ribbon 將在一切服務(wù)實(shí)例之間輪詢負(fù)載均衡一切懇求;

2.4 運(yùn)用 Netflix Feign 客戶端調(diào)用服務(wù)

Feign 相關(guān)常識(shí)將在下篇《4.2 根據(jù) Feign 與 OpenFeign 的服務(wù)接口調(diào)用》中說(shuō)明,這兒僅把要點(diǎn)放在與上述兩種調(diào)用供給者服務(wù)的區(qū)別與比照;

2.4.1 在主程序類上增加注解

@EnableFeignClients:表明啟用 Feign 客戶端;

2.4.2 界說(shuō)用于調(diào)用服務(wù)供給者的 Feign 接口

@FeignClient("provider-instance-name") //標(biāo)識(shí)服務(wù)為 feign 的客戶端 public interface ProviderFeignClient { //界說(shuō)端點(diǎn)的路徑和動(dòng)作 @RequestMapping( 
            method= RequestMethod.GET,
            value="/providers/{providerId}",
            consumes="application/json") //界說(shuō)傳入端點(diǎn)的參數(shù),該方法能夠由客戶端調(diào)用以觸發(fā)組織服務(wù)  Provider getProvider(@PathVariable("providerId") String providerId);
}
  • 要是用 ProviderFeignClient 類,開(kāi)發(fā)人員只需要主動(dòng)裝配并運(yùn)用它即可;


3. 通過(guò) java 裝備類自界說(shuō)負(fù)載均衡算法示例(顧客服務(wù))

指切換默許的負(fù)載均衡算法,切換后的仍為現(xiàn)成的(與本地負(fù)載均衡器有所區(qū)別,本地負(fù)載均衡器要自己完成);

3.1 編寫(xiě)裝備類

  • 留意:自界說(shuō)裝備類不能放在 @ComponentScan 所掃描的當(dāng)時(shí)包下以及子包下,否則自界說(shuō)的裝備類會(huì)被一切的Ribbon客戶端所共享,達(dá)不到自界說(shuō)的意圖;
  • @ComponentScan 注解被封裝到主發(fā)動(dòng)類上的 @SpringBootApplication 注解。其默許掃描主發(fā)動(dòng)類所在包及其子包,因而咱們要回來(lái)上一級(jí)目錄新建一個(gè) myRule 目錄寄存咱們自界說(shuō)的負(fù)載均衡裝備類;

自界說(shuō)負(fù)載均衡算法的文件目錄結(jié)構(gòu)

@Configuration public class MySelfRule { @Bean public IRule myRule(){ return new RandomRule();//界說(shuō)為隨機(jī) }
}

3.2 主發(fā)動(dòng)類上增加注解

  • @RibbonClient(name = "provider-instance-name" ,configuration=MySelfRule.class):表明運(yùn)用自界說(shuō)負(fù)載均衡算法;

    • name:指定服務(wù)供給者的實(shí)例名稱;
    • configuration:指定需要運(yùn)用哪個(gè)裝備類的負(fù)載均衡;
    • 表明 provider 服務(wù)運(yùn)用 MySelfRule 對(duì)應(yīng)的 Ribbon 裝備;
  • 相同,需要對(duì) RestTemplate 類用 @LoadBalanced 注解顯現(xiàn)聲明;


4. 通過(guò)裝備自界說(shuō)負(fù)載均衡算法示例(顧客服務(wù))

指切換默許的負(fù)載均衡算法,切換后的仍為現(xiàn)成的(與本地負(fù)載均衡器有所區(qū)別,本地負(fù)載均衡器要自己完成);

4.1 修正 bootstrap.yml 裝備文件

  • 上述 java 裝備類的效果等價(jià)于下面這樣的裝備文件:
#服務(wù)供給者的實(shí)例名稱 provider-instance-name: ribbon: #代表 Ribbon 運(yùn)用的負(fù)載均衡戰(zhàn)略,屬性的值為:IRule 的完成類 NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #其他可用的裝備屬性 # NFLoadBalancerClassName : 裝備 ILoadBalancer 的完成類 # NFLoadBalancerPingClassName : 裝備 IPing 的完成類 # NIWSServerListClassName: 裝備 ServerList 的完成類 # NIWSServerListFilterClassName: 裝備 ServerListtFilter 的完成類

4.2 主程序類

  • 不需要 @RibbonClient 注解;
  • 相同,需要對(duì) RestTemplate 類用 @LoadBalanced 注解顯現(xiàn)聲明;


5. 本地負(fù)載均衡器的完成(顧客)

本地負(fù)載均衡器不同于自界說(shuō)負(fù)載均衡算法;前者的負(fù)載均衡算法需要自己手動(dòng)完成,后者僅僅切換成另一種現(xiàn)成的負(fù)載均衡算法;

5.1 不運(yùn)用 RestTemplate

  • 即主程序類不需要對(duì) RestTemplate 類用 @LoadBalanced 注解顯現(xiàn)聲明;
  • 能夠刪去也能夠注釋 @LoadBalanced 注解;

5.2 界說(shuō)負(fù)載均衡接口

能夠新建一個(gè)包,專門(mén)寄存咱們自己寫(xiě)的負(fù)載均衡算法;
public interface LoadBalancer{ ServiceInstance instances(ListserviceInstances);
}

5.3 完成負(fù)載均衡接口

  • 能夠根據(jù)事務(wù)要求寫(xiě)不同的負(fù)載均衡算法,這兒僅供給一種示例;
  • 該示例完成了一種較為簡(jiǎn)略的原子性的負(fù)載均衡算法;
@Component public class MyLB implements LoadBalancer{ private AtomicInteger atomicInteger = new AtomicInteger(0); public final int getAndIncrement(){ int current; int next; do {
            current = this.atomicInteger.get();
            next = current >= 2147483647 ? 0 : current + 1;
        }while(!this.atomicInteger.compareAndSet(current,next));
        System.out.println("*****第幾次拜訪,次數(shù)next: "+next); return next;
    } //負(fù)載均衡算法:rest接口第幾次懇求數(shù) % 服務(wù)器集群總數(shù)量 = 實(shí)際調(diào)用服務(wù)器方位下標(biāo)  ,每次服務(wù)重發(fā)動(dòng)后rest接口計(jì)數(shù)從1開(kāi)始。 @Override public ServiceInstance instances(ListserviceInstances){ int index = getAndIncrement() % serviceInstances.size(); return serviceInstances.get(index);
    }
}

5.4 在 controller 接口中運(yùn)用本地負(fù)載均衡器

  • 類似于本篇《2.2 運(yùn)用 Spring DiscoveryClient 查找服務(wù)實(shí)例》;
  • 不同之處在于 2.2 沒(méi)有負(fù)載均衡功用,這兒在 2.2 的基礎(chǔ)上,開(kāi)發(fā)人員自己界說(shuō)了本地負(fù)載均衡器,不運(yùn)用 Ribbon 供給的負(fù)載均衡,故《5.1 不運(yùn)用 RestTemplate》中說(shuō)到的不必對(duì) RestTemplate 類運(yùn)用 @LoadBalanced 注解顯現(xiàn)聲明
@RestController public class OrderController{ //服務(wù)供給者示例的名字 public static final String PAYMENT_URL = "http://provider-instance-name"; @Resource private RestTemplate restTemplate; @Resource private LoadBalancer loadBalancer; @Resource private DiscoveryClient discoveryClient; @GetMapping(value = "/provider/mylb") public String getProviderLB(){ //獲取服務(wù)供給者的一切實(shí)例列表 Listinstances = discoveryClient.getInstances("provider-instance-name"); if(instances == null || instances.size() <= 0){ return null;
        } //運(yùn)用本地負(fù)載均衡器選出供給者服務(wù) ServiceInstance serviceInstance = loadBalancer.instances(instances);
        URI uri = serviceInstance.getUri(); return restTemplate.getForObject(uri+"/provider/mylb",String.class);
    }
}