吉林省軟環(huán)境建設(shè)辦公室網(wǎng)站百度快速排名點(diǎn)擊器
目錄
1.負(fù)載均衡介紹
1.1問(wèn)題描述
1.2什么是負(fù)載均衡
1.3負(fù)載均衡的一些實(shí)現(xiàn)
服務(wù)端負(fù)載均衡
客戶端負(fù)載均衡
2.Spring Cloud LoadBalancer
2.1快速上手實(shí)現(xiàn)負(fù)載均衡
2.2負(fù)載均衡策略
自定義負(fù)載均衡策略
3.服務(wù)部署(Linux)
3.1服務(wù)構(gòu)建打包
3.2啟動(dòng)服務(wù)
承接上文服務(wù)注冊(cè)/服務(wù)發(fā)現(xiàn)-Eureka
1.負(fù)載均衡介紹
1.1問(wèn)題描述
觀察上個(gè)章節(jié)遠(yuǎn)程調(diào)用的代碼
List<ServiceInstance> instances = discoveryClient.getInstances("product-service");//服務(wù)可能有多個(gè), 獲取第?個(gè)EurekaServiceInstance instance = (EurekaServiceInstance) instances.get(0);
1.根據(jù)應(yīng)用名稱獲取了服務(wù)實(shí)例列表
2.從列表中選擇了一個(gè)服務(wù)實(shí)例
思考:如果一個(gè)服務(wù)對(duì)應(yīng)多個(gè)實(shí)例呢?流量是否可以合理的分配到多個(gè)實(shí)例
現(xiàn)象觀察:
我們?cè)賳?dòng)2個(gè)product-service實(shí)例
選中要啟動(dòng)的服務(wù),右鍵選擇Copy Configuration
在彈出的框中選擇 Configuration -> VM options
?添加VM options: -Dserver.port=9091
9091為服務(wù)啟動(dòng)的端口號(hào),根據(jù)自己的情況進(jìn)行修改
11:46:05.684+08:00 INFO 23128 --- [nio-8080-exec-1]
com.bite.order.service.OrderService : LUCF:product-service:909011:46:06.435+08:00 INFO 23128 --- [nio-8080-exec-2]
com.bite.order.service.OrderService : LUCF:product-service:909011:46:07.081+08:00 INFO 23128 --- [nio-8080-exec-3]
com.bite.order.service.OrderService : LUCF:product-service:9090
先啟動(dòng)Eureka后啟動(dòng)所有實(shí)例
觀察Eureka,可以看到product-service下有三個(gè)實(shí)例
訪問(wèn):http://127.0.0.1:8080/order/1
訪問(wèn)結(jié)果:
11:46:05.684+08:00 INFO 23128 --- [nio-8080-exec-1]
com.bite.order.service.OrderService : LUCF:product-service:909011:46:06.435+08:00 INFO 23128 --- [nio-8080-exec-2]
com.bite.order.service.OrderService : LUCF:product-service:909011:46:07.081+08:00 INFO 23128 --- [nio-8080-exec-3]
com.bite.order.service.OrderService : LUCF:product-service:9090
通過(guò)日志可以觀察到,請(qǐng)求多次訪問(wèn),都是同一臺(tái)機(jī)器。
這肯定不是我們想要的結(jié)果,啟動(dòng)多個(gè)實(shí)例,是希望可以分擔(dān)其他機(jī)器的負(fù)荷,那么如何實(shí)現(xiàn)呢?
解決方案:
我們可以對(duì)上述代碼進(jìn)行簡(jiǎn)單修改:
import com.example.orderservice.mapper.OrderMapper;
import com.example.orderservice.model.OrderInfo;
import com.example.orderservice.model.ProductInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;private static AtomicInteger atomicInteger = new AtomicInteger(1);public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
// String url = "http://127.0.0.1:9090/product/"+orderInfo.getProductId();//從Eureka中獲取服務(wù)列表List<ServiceInstance> instances = discoveryClient.getInstances("product-service");String uri = instances.get(atomicInteger.getAndIncrement() % instances.size()).getUri().toString();String url = uri+"/product/"+orderInfo.getProductId();log.info("遠(yuǎn)程調(diào)用url:{}", url);ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;}
}
觀察日志:
12:02:13.245+08:00 INFO 1800 --- [nio-8080-exec-1]
com.bite.order.service.OrderService : LUCF:product-service:909112:02:15.723+08:00 INFO 1800 --- [nio-8080-exec-2]
com.bite.order.service.OrderService : LUCF:product-service:909012:02:16.534+08:00 INFO 1800 --- [nio-8080-exec-3]
com.bite.order.service.OrderService : LUCF:product-service:909212:02:16.864+08:00 INFO 1800 --- [nio-8080-exec-4]
com.bite.order.service.OrderService : LUCF:product-service:909112:02:17.078+08:00 INFO 1800 --- [nio-8080-exec-5]
com.bite.order.service.OrderService : LUCF:product-service:909012:02:17.260+08:00 INFO 1800 --- [nio-8080-exec-6]
com.bite.order.service.OrderService : LUCF:product-service:909212:02:17.431+08:00 INFO 1800 --- [nio-8080-exec-7]
com.bite.order.service.OrderService : LUCF:product-service:9091
通過(guò)日志可以看到,請(qǐng)求被均衡的分配在不同的實(shí)例上,這就是負(fù)載均衡
1.2什么是負(fù)載均衡
負(fù)載均衡(Load Balance,簡(jiǎn)稱LB),是高并發(fā),高可用系統(tǒng)必不可少的關(guān)鍵組件.
當(dāng)服務(wù)流量增大時(shí),通常會(huì)采用增加機(jī)器的方式進(jìn)行擴(kuò)容,負(fù)載均衡就是用來(lái)在多個(gè)機(jī)器或者其他資源中,按照一定的規(guī)則合理分配負(fù)載.
?一個(gè)團(tuán)隊(duì)最開(kāi)始只有一個(gè)人,后來(lái)隨著工作量的增加,公司又招聘了幾個(gè)人.負(fù)載均衡就是:如何把工作量均衡的分配到這幾個(gè)人身上,以提高整個(gè)團(tuán)隊(duì)的效率
1.3負(fù)載均衡的一些實(shí)現(xiàn)
上面的例子中,我們只是簡(jiǎn)單的對(duì)實(shí)例進(jìn)行了輪詢,但真實(shí)的業(yè)務(wù)場(chǎng)景會(huì)更加復(fù)雜.比如根據(jù)機(jī)器的配置進(jìn)行負(fù)載分配,配置高的分配的流量高,配置低的分配流量低等. 類似企業(yè)員工:能力強(qiáng)的員工可以多承擔(dān)一些工作。
服務(wù)多機(jī)部署時(shí),開(kāi)發(fā)人員都需要考慮負(fù)載均衡的實(shí)現(xiàn),所以也出現(xiàn)了一些負(fù)載均衡器,來(lái)幫助我們實(shí)現(xiàn)負(fù)載均衡.
負(fù)載均衡分為服務(wù)端負(fù)載均衡和客戶端負(fù)載均衡.
服務(wù)端負(fù)載均衡
在服務(wù)端進(jìn)行負(fù)載均衡的算法分配
比較有名的服務(wù)端負(fù)載均衡器是Nginx.
請(qǐng)求先到達(dá)Nginx負(fù)載均衡器,然后通過(guò)負(fù)載均衡算法,在多個(gè)服務(wù)器之間選擇一個(gè)進(jìn)行訪問(wèn).
客戶端負(fù)載均衡
在客戶端進(jìn)行負(fù)載均衡的算法分配.
把負(fù)載均衡的功能以庫(kù)的方式集成到客戶端,而不再是由一臺(tái)指定的負(fù)載均衡設(shè)備集中提供.
?

2.Spring Cloud LoadBalancer
2.1快速上手實(shí)現(xiàn)負(fù)載均衡
1.給RestTemplate這個(gè)Bean添加@LoadBalanced注解
@Configuration
public class BeanConfig {@LoadBalanced@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}
2.修改IP端口號(hào)為服務(wù)名稱
public OrderInfo selectOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectOrderById(orderId);//String url = "http://127.0.0.1:9090/product/"+ orderInfo.getProductId();String url = "http://product-service/product/" + orderInfo.getProductId();ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;}
?3.啟動(dòng)多個(gè)product-service實(shí)例

2.2負(fù)載均衡策略
?負(fù)載均衡策略是一種思想,無(wú)論是哪種負(fù)載均衡器,它們的負(fù)載均衡策略都是相似的.
Spring Cloud LoadBalancer僅支持兩種負(fù)載均衡策略:輪詢策略和隨機(jī)策略
- 輪詢(Round Robin):輪詢策略是指服務(wù)器輪流處理用戶的請(qǐng)求.這是一種實(shí)現(xiàn)最簡(jiǎn)單,也最常用的 策略.生活中也有類似的場(chǎng)景,比如學(xué)校輪流值日,或者輪流打掃衛(wèi)生.
- 隨機(jī)選擇(Random):隨機(jī)選擇策略是指隨機(jī)選擇一個(gè)后端服務(wù)器來(lái)處理新的請(qǐng)求.
?
自定義負(fù)載均衡策略
Spring Cloud LoadBalancer默認(rèn)負(fù)載均衡策略是輪詢策略,實(shí)現(xiàn)是RoundRobinLoadBalancer,如果服務(wù)的消費(fèi)者如果想采用隨機(jī)的負(fù)載均衡策略,也非常簡(jiǎn)單.
參考官網(wǎng):Spring Cloud LoadBalancer :: Spring Cloud Commons
此處使?Spring Cloud LoadBalancer提供的 RandomLoadBalancer
public class CustomLoadBalancerConfiguration {@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),name);}}
注意:該類需要滿足
- 不用@Configuration注釋
- 在組件掃描范圍內(nèi)
?
@LoadBalancerClient(name = "product-service",configuration = CustomLoadBalancerConfiguration.class)
@Configuration
public class BeanConfig {@LoadBalanced@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}
@LoadBalancerClient注解說(shuō)明:
- name:該負(fù)載均衡策略對(duì)哪個(gè)服務(wù)生效(服務(wù)提供方)
- configuration:該負(fù)載均衡策略用哪個(gè)負(fù)載均衡策略實(shí)現(xiàn).
?
3.服務(wù)部署(Linux)
3.1服務(wù)構(gòu)建打包
?采用Maven打包,需要對(duì)3個(gè)服務(wù)分別打包:
?eureka-server,order-service,product-service
?1.打包方式和SpringBoot項(xiàng)目一致,依次對(duì)三個(gè)項(xiàng)目打包即可.
3.2啟動(dòng)服務(wù)
#后臺(tái)啟動(dòng)eureka-server, 并設(shè)置輸出?志到logs/eureka.lognohup java -jar eureka-server.jar >logs/eureka.log &#后臺(tái)啟動(dòng)order-service, 并設(shè)置輸出?志到logs/order.lognohup java -jar order-service.jar >logs/order.log &#后臺(tái)啟動(dòng)product-service, 并設(shè)置輸出?志到logs/order.lognohup java -jar product-service.jar >logs/product-9090.log &
#啟動(dòng)實(shí)例, 指定端?號(hào)為9091nohup java -jar product-service.jar --server.port=9091 >logs/product-9091.log &#啟動(dòng)實(shí)例, 指定端?號(hào)為9092nohup java -jar product-service.jar --server.port=9092 >logs/product-9092.log &