提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
搭建Ribbon负载均衡
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、什么是负载均衡?
负载均衡是高可用网络基础架构的一个关键组成部分,有了负载均衡,我们通常可以将我们的应用服务器部署多台,然后通过负载均衡将用户的请求分发到不同的服务器用来提高网站、应用、数据库或其他服务的性能以及可靠性。
负载均衡分为硬件负载均衡和软件负载均衡两种,具体介绍如下:
硬件负载均衡的解决方案就是直接在服务器和外部网络间安装负载均衡设备,通常这种设备称为负载均衡器。由专门的设备完成专门的任务,独立于操作系统,整体性能得到大量提高,加上多样化的负载均衡策略,智能化的流量统计,可达到最佳的负载均衡效果。
软件负载均衡的解决方案是指在一台或多台服务器相应的操作系统上安装一个或多个附加软件来实现负载均衡,如DNS Load Balance,CheckPointFirewall-1 ConnectControl等,它的优点是基于特定环境,配置简单,使用灵活,成本低廉,可以满足一般的负载均衡需求。
使用负载均衡带来的好处
引入负载均衡,可以将负载(工作任务)进行平衡、分摊到多个执行单元上运行。例如,Web服务器、FTP服务器、企业关键应用服务器和其他主要任务服务器等,协同完成工作任务。
二、认识Ribbon
1.什么是Ribbon
Ribbon是Netflix开源的一款用于客户端负载均衡的软件工具,它在集群中为各个客户端的通信提供了支持,有助于控制HTTP和TCP客户端的行为,提供了很多负载均衡的算法,例如轮询,随机等,同时也可以实现自定义的算法。
在Spring Cloud构建的微服务中,Ribbon作为服务消费者的负载均衡器,有两种使用方式,一种是与RestTemplate相结合,另一种是与Feign相结合。
Ribbon包含很多子模块,但很多子模块没有用于生产环境,目前用于生产的Ribbon的子模块具体如下:
**ribbon-core:**定义负载均衡接口、客户端接口、内置的负载均衡实现等API。
**ribbon-eureka 😗*提供eureka客户端实现负载均衡的API。
**ribbon-httpclient:**对Apache的HttpClient进行封装,该模块提供了含有负载均衡功能的REST客户端。
搭建含有Ribbon的服务消费者基本流程∶
-
创建项目,引入依赖
使用Spring Initializr方式创建一个名称为eureka-ribbon-client的Spring Boot项目,这里将Group命名为com.itheima,将 Artifact命名为eureka-ribbon-client ,添加 Eureka Client .Ribbon和Web的依赖。 -
在application.yml文件进行相关配置
在全局配置文件application.yml进行相关配置,包括指定应用名称、端口号、服务注册地址等信息。 -
添加@EnableEurekaClient注解
在项目启动类EurekaRibbonClientApplication上添加@EnableEurekaClient注解开启 Eurekalient功能。 -
创建配置类
新建config包,并在该包下创建RibbonConfig类,该类注入restTemplate的 Bean ,并在这个Bean中加上@LoadBalanced注解。 -
创建Service类
新建service包,并在该包下创建一个RibbonService类,在该类的hi()方法中使用restTemplate调用eureka-client的API接口。 -
创建Controller类
新建controller包,并在该包下创建一个RibbonController类,在该类上添加@RsetController注解,将RibbonController标注为一个Controller类。在类中写一个hi()方法,调用RibbonService的hi()方法。 -
测试运行
启动服务提供者eureka-server和eureka-server-another,服务消费者eureka-ribbon-client,在浏览器上访问http://localhost:7000,界面显示如下图所示。
搭建Ribbon负载均衡
package com.common.instance.gateway.config.ribbon;
import com.log.util.LogUtil;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* @description 自定义Ribbon负载均衡策略
* @author TCM
* @version 1.0
* @date 2021/4/1 10:58
**/
@Configuration
public class MyRibbonBalancerRule extends AbstractLoadBalancerRule {
// 所有服务实例
private volatile int total;
// 实例的索引
private volatile int index;
// 可用的所有实例
List<Server> upList = new ArrayList<>();
public Server choose(ILoadBalancer lb, Object key) {
LogUtil.info(String.format("lb=%s,key=%s", lb, key.toString()));
// 负载均衡器是否为null
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
// 当前线程是否已中断
if (Thread.interrupted()) {
return null;
}
// 获取负载均衡器中的所有服务实例
List<Server> allList = lb.getAllServers();
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
if (total == 0) {
// 可用的所有实例
upList = lb.getReachableServers();
}
// 修改当前索引
chooseIndex(lb.getReachableServers().size());
// 根据索引获取服务
server = upList.get(index);
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
server = null;
Thread.yield();
}
return server;
}
// 修改当前索引
protected void chooseIndex(int reachableCount) {
if (total < 3) {
if (upList.size() != reachableCount) {
index = 0;
}
total ++;
} else {
total = 0;
index ++;
if (index >= reachableCount) {
index = 0;
}
}
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}