飞道的博客

Spring Cloud微服务之loadbalancer负载平衡

329人阅读  评论(0)

Spring Cloud微服务之loadbalancer负载平衡

小学时候,曾经做过这样的数学题。

说有一个水池子,上面有一个排水管,下面有一个进水管,开一个进水管,6个小时灌满水池,开一个排水管,10个小时放光整个水池的水。现在同时打开排水管和进水管,多少个小时能灌满整个池子。

 

带来的问题是:为什么不节约用水,浪费多少水费,现在水费这么贵。

不过问题就是一个问题,现在问题在升级,如果有上面还是那个进水管,只不过有两个出水管,一个排水管还是6个小时灌满水池,一个排水管还是10个小时放光整个水池的水,同时打开这个进水管和两个排水管,多少时间灌满整个水池。

 

带来的问题是:这会更浪费水,因为灌不满这个水池了。

当然也带来了负载平衡的道理。

一、负载平衡的概念

负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行。

同样是进水,利用负载平衡的道理,不能让每一个进水管歇着,你工作所以我工作。

某些工作出现的早中晚三班导,采用了不固定的方式,每个人都不会固定,说不定你上早班,说不定你上中班,说不定你上晚班,下次就进行轮值了。负载平衡的良好写照。

听说有皇帝的时候,皇帝是后宫佳丽三千,每天晚上靠“翻牌子”来决定谁是被宠爱的。如果当时有懂“负载平衡”道理的太监就会发现,三千佳丽就会协调安排,皇帝也会照顾到每一位佳丽,但也有一个问题,一个佳丽要想重复被庞幸,大概需要十年。就是怕,一首歌唱的“十年之后,我们是朋友,还可以问候,只是那种温柔,再也找不到拥抱的理由”。

 

还是谈回负载平衡。

负载均衡,是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行。

你讨厌的领导下发一个超级变态的任务,工作量大到交给一个人无法完成,于是就需要几个天选的打工人过来一起处理,把大任务分解成多个小任务分配给不同的人,完成分配任务的就叫负载均衡。

负载平衡表现有微服务中,当用户访问一个请求,需要获取服务器上的资源及相关信息,有很多服务器有这样的资源和相关信息,具体由哪个服务器来提供服务,就由负载平衡来决定,如下图所示。

 

二、负载平衡的算法

谈完负载平衡的概念。来谈一下负载平衡的算法。

还是从一个数学问题谈起吧。

一个飞机上乘载了20个人,结果在飞行过程中出现了故障,需要20个人跳伞求生,只有一个舱门,然后就会一个一个从舱门跳下去。

上面是一个简单的处理负载平衡的方法,一个用户访问资源,每个服务器轮流服务。

现在数学问题升级。

飞机上乘载了20个人,只有19个降落伞,飞机上有前端工程师,有后端工程师,有前台,有项目经理,有产品经理,有UI设计师,有测试人员,你觉得跳伞的顺序是什么,或者说谁是哪个没有降落伞的人。

问题也来了,好像不是一个数学问题,是一个逻辑的问题。

还有,就是必须对这些人的重要性做一些对比,还是一个舱门,还是一个一个打开降落伞下落,只不过需要把下落的人一个一个按照重要性站好队,然后一个一个轮流跳下去。

这里就是负载平衡的算法思维。

负载均衡的算法有多种分类,这里介绍为大家介绍三种常见的,分别是轮询、加权轮询、最小连接。

轮询

简单的轮询,就是把来自用户的请求轮流分配给内部的服务器:从服务器1开始,直到服务器N,然后重新开始循环。

这就是飞机上的降落伞够数,一个一个从舱门中跳下去。

也就是说,从第一个服务器开始分配用户,到每个服务器都能分到一位用户,等到全部服务器都有被分到用户后,就开始第二轮分配,以此类推。

加权轮询

这里需要给服务器设置权重并遵循轮询的模式,根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。

假设这里有服务器A、B、C、D,分别设置2、2、1、1的权重,当有一个用户访问时,首先有A或B来服务,这两个服务器权重相同,如有4个用户来访问,就需要每个服务器进行工作,如果有100位用户分配给这四个服务器时,分配顺序会根据处理的速度及权重来决定,不过最开始服务的应该是A或B。

这就是前面数学问题中飞机上降落伞不够数你要让谁先跳伞去逃生。

最小连接

指每次有用户访问时,看当前哪个服务器的连接数最少就分配给哪个服务器。最小连接法是动态负载均衡算法,适用于各个服务器处理的性能相似的时候。

最小连接数法是根据服务器当前的连接情况进行负载均衡的,当请求到来时,会选取当前连接数最少的一台服务器来处理请求。

这个算法相当于飞机故障,还是要完成跳伞,只不过谁系好了伞包,谁做好了心理准备,谁就走到舱门去跳下去。

三、微服务EurekaServer的建立

1、点击File--->New---->Project.....,如下图。

 

2、在弹出的地话框中,左边点击Spring Initializr,表示Spring的初始程序,右边在默认的地方可能会初始化失败,需要选择自定义的地址:http://start.aliyun.com。如下图所示。

 

3、在接下来的弹出框中输入spring cloud项目名称的Group和artifactId。如下图所示。

 

4、点击Next进入下一步,左边先点击Web,右边点击Spring web可以建立Web应用程序。如下图。

 

5、继续在这个对话框中,左边点击Spring Cloud Discovery,右边点击Eureka Server,如下图所示。

 

6、然后点击Next进入到“下一步”,会出现对话框。如下图所示。

 

7、在出现的对话框中,点击Finish后完成项目的构建向导。

项目框架建立后,修改主程序中的主类,如下图所示。

 

8、在打开的主程序中,加入注解@EnableEurekaServer。如下图所示。

 

最终,eurekaserver的程序代码如下。


  
  1. package com. myfirsteurekabalance. myfirsteurekabalance;
  2. import org. springframework. boot. SpringApplication;
  3. import org. springframework. boot. autoconfigure. SpringBootApplication;
  4. import org. springframework. cloud. netflix. eureka. server. EnableEurekaServer;
  5. @SpringBootApplication
  6. @EnableEurekaServer
  7. public class MyfirsteurekabalanceApplication {
  8. public static void main( String[] args) {
  9. SpringApplication. run( MyfirsteurekabalanceApplication. class, args);
  10. }
  11. }

9、下面需要编辑resources下面的application.yml文件,在原来的resouces目录下只有application.properties,需要把application.properties改成application.yml。然后编辑该文件。

 

10、application.yml的文件内容如下。


  
  1. # 应用名称
  2. spring:
  3. application:
  4. name: myfirsteurekabalance
  5. # 应用服务 WEB 访问端口
  6. server:
  7. port: 8011
  8. eureka:
  9. client:
  10. register- with- eureka: true
  11. fetch- registry: false
  12. service- url:
  13. defaultZone: http:/ /localhost:8011/eureka
  14. instance:
  15. hostname: myprovider1

其文件内容的解释如下 。

 

四、Eureka客户端的搭建

1、同样点击File--->New----->Project....,如下图所示。

 

2、在打开的对话框中,左边继续点击Spring Initializr,表示Spring的初始程序,右边在默认的地方可能会初始化失败,需要选择自定义的地址:http://start.aliyun.com。如下图所示。

 

3、点击Next,然后在出现的对话框中输入项目名称。如下图所示。

 

4、在接下来出现的对话框中,左边选择Web,右边选择Spring Web。如下图所示。

 

5、继续在这个对话框中,左边选择Spring Cloud Discovery,右边选择Eureka Discovery Client。如下图所示。

 

6、然后点击下一步即Next,在出现的对话框中直接点击Finish完成项目建立的向导。如下图所示。

 

7、在主程序中输入EnableEurekeClient或者是@EnableDiscoveryClient都可以实现Eureka客户端的发现。

 

客户端的代码如下。


  
  1. import org. springframework. boot. SpringApplication;
  2. import org. springframework. boot. autoconfigure. SpringBootApplication;
  3. import org. springframework. cloud. netflix. eureka. EnableEurekaClient;
  4. @SpringBootApplication
  5. @EnableEurekaClient
  6. public class Myfirsteurekaclient01Application {
  7. public static void main( String[] args) {
  8. SpringApplication. run( Myfirsteurekaclient01Application. class, args);
  9. }
  10. }

然后在客户端的package包下面建立一个config,并在config下面建立RestTemplateConfig的类文件,然后也要建立一个controller的包,在controller的包下面建立controller的类文件ConsumerController。结构如下图。

 

编辑config包下面的RestTemplateConfig文件,具体内容需要使用RestTemplate模板,然后重写RestTemplate模板。

代码如下。


  
  1. package com.myeurekaclientexample01.myeurekaclientexample01.config;
  2. import org.springframework.context. annotation.Configuration;
  3. import org.springframework.context. annotation.Bean;
  4. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  5. import org.springframework.web.client.RestTemplate;
  6. @Configuration
  7. public class RestTemplateConfig {
  8. @Bean
  9. @LoadBalanced
  10. public RestTemplate restTemplate(){
  11. return new RestTemplate();
  12. }
  13. }

这里指出LoadBalanced,其实就是做负载平衡。Bean需要指出java bean,此java bean主要是把RestTemplate转成Bean。

在Controller的类方法中把RestTemplate做为Autowired的注入,然后通过restTemplate的getForObject获取服务器的地址,这里设置负载平衡。


  
  1. package com.myeurekaclientexample01.myeurekaclientexample01.controller;
  2. import org.springframework.web.bind. annotation.RestController;
  3. import org.springframework.web.bind. annotation.RequestMapping;
  4. import org.springframework.web.bind. annotation.PathVariable;
  5. import org.springframework.beans.factory. annotation.Autowired;
  6. import org.springframework.web.client.RestTemplate;
  7. import java.util.Map;
  8. @RestController
  9. @RequestMapping("/consumer")
  10. public class ConsumerController {
  11. @Autowired
  12. private RestTemplate restTemplate;
  13. @RequestMapping("/getall/{id}")
  14. public Map getall( @PathVariable("id")int id){
  15. String url= "http://myproviderexample/provider/getdata/"+id;
  16. return restTemplate.getForObject(url,Map. class);
  17. }
  18. }

这里做的负载平衡,意思是服务器有很多都具备provider的controller地址映射,请求url地址中的myproviderexample是在服务器中注册的controller服务地址。需要服务器中的application.yml中的application中的name是一致的。

这里可以实现多个客户端来提供provider生产者的控制器服务,application.yml中的instance中的name不同,但是application中的name选项一致。

具体其中一个客户端的controller服务下面描述。

五、loadbalance实现负载平衡的服务客户端设置

其建立方法仍然是客户端的设置方法,项目结构图如下。

 

其controller控制器的具体代码如下。


  
  1. import java.util.Map;
  2. import java.util.HashMap;
  3. import java.util.UUID;
  4. @RestController
  5. @RequestMapping("/provider")
  6. public class ProviderController {
  7. @Autowired
  8. private Environment env;
  9. @RequestMapping("/getdata/{id}")
  10. public Map getdata (@PathVariable("id")int id){
  11. String providerName=env.getProperty( "eureka.instance.hostname")+ ":"+env.getProperty( "server.port");
  12. Map result= new HashMap();
  13. result.put( "status", 0);
  14. result.put( "msg", "success");
  15. result.put( "provider",providerName);
  16. result.put( "get_id_value",id);
  17. result.put( "version",UUID.randomUUID().toString());
  18. return result;
  19. }
  20. }

在请求的地址中获取环境的主机,并构建json数据,json数据中可以提供微服务中服务的服务器名称及服务器端口号。

在客户端的yml文件设置如下。


  
  1. # 应用名称
  2. spring:
  3. application:
  4. name: myprovider
  5. # 应用服务 WEB 访问端口
  6. server:
  7. port: 8094
  8. eureka:
  9. client:
  10. service-url:
  11. defaultZone: http://localhost:8088/eureka
  12. instance:
  13. hostname: myprovider1

其设置的说明如下图所示。

 

关于windows中hosts的路径如下图所示。

 

图中所示的路径是: C:\windows\system32\drivers\etc。

在etc目录下有一个hosts文件,打开后,标明服务器名字的映射方式。如下图。

 

依照第五个主题的方式可以继续产生下一个提供provider服务的客户端,代码是一致的,只是application.yml中的instance选项下的hostname名字不同而已。

六、运行服务器

分别运行注册服务器,提供provider服务的若干服务端,负载平衡的服务端。

运行后,可以先从浏览器中请求地址,访问第一次。如下图所示。

 

再从浏览器中输入地址,访问第二次。如下图所示。

 

提供的服务器地址不同,采用了轮询的负载平衡的技术实现。


转载:https://blog.csdn.net/play_big_knife/article/details/128293728
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场