前言:
(1)Apache APISIX是一个动态的、实时的、高性能的 API 网关。它提供丰富的流量管理功能,例如负载均衡、动态上游服务、金丝雀发布、断路、身份验证、可观察性等。您可以使用 Apache APISIX 来处理传统的南北流量,以及服务之间的东西流量。它也可以用作 k8s ingress controller。这个作为微服务网关十分重要
它是国人开源,目前已经进入 Apache 进行孵化,社区活跃,文档详细友好,厉害!!!
APISIX地址:https://github.com/apache/apisixDashBoard:https://github.com/apache/apisix-dashboard
文档地址:https://apisix.apache.org/zh/docs/apisix/architecture-design/apisix
(2)APISIX 通过插件机制,提供了动态负载均衡、身份验证、限流限速等等功能,当然我们也可以自己开发插件进行拓展。更多的特性大家可以自行去了解一下
(3)Apache APISIX 的技术架构:
图片来源:APISIX 官网
下面,让我们快速进入APISIX的 极简入门。
1、快速安装
在《APISIX 官方文档 —— 安装》中,介绍了源码包、RPM 包、Docker 三种安装方式。这里我们使用 CentOS 7.9 系统,所以采用 RPM 包。
因为 APISIX 是基于 OpenResty + etcd 来实现,所以需要安装响应的依赖。
1.1 安装相关依赖
# install etcd
wget https://github.com/etcd-io/etcd/releases/download/v3.4.13/etcd-v3.4.13-linux-amd64.tar.gz
tar -xvf etcd-v3.4.13-linux-amd64.tar.gz && \
cd etcd-v3.4.13-linux-amd64 && \
sudo cp -a etcd etcdctl /usr/bin/
# add OpenResty source
sudo yum install yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
# install OpenResty and some compilation tools
sudo yum install -y openresty curl git gcc openresty-openssl111-devel unzip
# install LuaRocks
curl https://raw.githubusercontent.com/apache/apisix/master/utils/linux-install-luarocks.sh -sL | bash -
# start etcd server
nohup etcd &
检查下ETCD 是否启动成功:
1.2 安装APISIX
$ sudo yum install -y https://github.com/apache/apisix/releases/download/2.6/apisix-2.6-0.x86_64.rpm
检查一下APISIX版本:
启动APISIX服务:
默认会安装在/usr/local/apisix路径下,默认端口9080,可通过如下命令检查:
1.3 APISIX dashboard(控制台)安装
参考文档:
https://github.com/apache/apisix-dashboard
(1)git获取源码:
$ git clone https://github.com/apache/incubator-apisix-dashboard.git
$ cd incubator-apisix-dashboard
切换分支版本,需要与apisix版本一致即可
$ git checkout -b release/2.6 origin/release/2.6
(2)构建控制流:manager-api
控制流用于为控制台提供接口,相当于在APISIX与控制台之间的桥梁。手动构建需要如下步骤:1.需要事先装好 Go 1.13+注意:如果你想使用Orchestration的插件功能,需要安装Lua 5.1+已上版本。
$ wget https://dl.google.com/go/go1.16.5.linux-amd64.tar.gz
$ tar -C /usr/local -xzvf go1.16.5.linux-amd64.tar.gz
--
$ export PATH=$PATH:/usr/local/go/bin
$ source /etc/profile
检查环境变量:
-- enable Go MODULE
$ go env -w GO111MODULE=on
-- 对于我们国内用户,可以设置Goproxy代理加速下载模块
$ go env -w GOPROXY=https://goproxy.cn,direct
(3)构建
执行下面的命令:
$ ./api/build.sh
注意:如果执行上面的命令 会超时,可以单独把wget + 后面的链接复制出来,独立执行就可以了。
(3)构建web
确保机器上的Node.js版本在10.0.0+已上,执行下面的命令
$ curl -sL https://rpm.nodesource.com/setup_16.x | sudo bash -
$ sudo yum install nodejs
$ node --version
$ npm --version
安装yarn:
$ curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
$ sudo yum install yarn
$ sudo yum build
安装依赖:
接下来就是漫长的等待。。。
(4)运行控制流 manager-api
[root@iZhp33yk3z4ttlhta3t5tkZ incubator-apisix-dashboard]# ./api/run.sh &
根据提示,创建对应的文件夹:logs
重新执行上面的命令:./api/run.sh &
然后,我们直接:公网IP:9000,就可以访问 Dashboard,显示这样的界面时,解决方案:
https://github.com/apache/apisix-dashboard/blob/master/docs/en/latest/FAQ.md
修改:/root/incubator-apisix-dashboard/output/conf/
注意:生产环境不能这样设置!!!
杀掉 manager-api 进程后
再重新启动一下:
./api/run.sh &
账号密码都是 admin
2、快速实践
创建2个netcore 3.1 的项目(注意:需要安装对应的.net core sdk)
启动 5000端口的app:
启动 5001端口的app:
2.1 动态负载均衡
(1)创建 APISIX Upstream
在 APISIX 控制台的「上游」菜单中,创建一个 APISIX Upstream。如下图所示:
点击下一步,最后点击 提交,即可。
(2)创建 APISIX Route
APISIX Route,字面意思就是路由,通过定义一些规则来匹配客户端的请求,然后根据匹配结果加载并执行相应的 插件,并把请求转发给到指定 Upstream。
点击下一步,选择上游服务:
点击下一步,关于插件部门后面的问题后续会陆续更新。
最后点击提交即可:
(3)简单测试:
现在,我们来请求 APISIX 网关,转发请求到后端服务。
浏览器中输入:
从结果可以看出,APISIX 网关使用带权轮询算法(Round Robin),将请求轮流转发到后端服务。博客已搬家到Infoq, 欢迎大家关注!
2.2 限流限速
2.2.1 原理
在大规模微服务架构的场景下,避免服务出现雪崩,要减少停机时间,要尽可能的提高服务可用性。
提高服务可用性,可以从很多方向入手,比如缓存、池化、异步化、负载均衡、队列和降级熔断等手段。
缓存以及队列等手段,增加系统的容量。限流和降级则是关心在到达系统瓶颈时系统的响应,更看重稳定性。
限流顾名思义,提前对各个类型的请求设置最高的 QPS 阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。
限流需要结合压测等,了解系统的最高水位,也是在实际开发中应用最多的一种稳定性保障手段。
降级则是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。
从降级配置方式上,降级一般可以分为主动降级和自动降级。主动降级是提前配置,自动降级则是系统发生故障时,如超时或者频繁失败,自动降级。
本小结,我们来聊聊目前常见的限流算法。
(1)计数器
假设一个接口限制一分钟内的访问次数不能超过 100 个,维护一个计数器,每次有新的请求过来,计数器加一。
这时候判断,如果计数器的值小于限流值,并且与上一次请求的时间间隔还在一分钟内,允许请求通过,否则拒绝请求,如果超出了时间间隔,要将计数器清零。
计数器限流可以比较容易的应用在分布式环境中,用一个单点的存储来保存计数值,比如用 Redis,并且设置自动过期时间,这时候就可以统计整个集群的流量,并且进行限流。
计数器方式的缺点是不能处理临界问题,或者说限流策略不够平滑。
假设在限流临界点的前后,分别发送 100 个请求,实际上在计数器置 0 前后的极短时间里,处理了 200 个请求,这是一个瞬时的高峰,可能会超过系统的限制。
计数器限流允许出现 2*permitsPerSecond 的突发流量,可以使用滑动窗口算法去优化,具体不展开。
(2)漏桶算法
假设我们有一个固定容量的桶,桶底部可以漏水(忽略气压等,不是物理问题),并且这个漏水的速率可控的,那么我们可以通过这个桶来控制请求速度,也就是漏水的速度。
我们不关心流进来的水,也就是外部请求有多少,桶满了之后,多余的水会溢出。如下图所示:
将算法中的水换成实际应用中的请求,可以看到漏桶算法从入口限制了请求的速度。
使用漏桶算法,我们可以保证接口会以一个常速速率来处理请求,所以漏桶算法不会出现临界问题。
(3)令牌桶算法
漏桶是控制水流入的速度,令牌桶则是控制留出,通过控制 Token,调节流量。
假设一个大小恒定的桶,桶里存放着令牌(Token)。桶一开始是空的,现在以一个固定的速率往桶里填充,直到达到桶的容量,多余的令牌将会被丢弃。
如果令牌不被消耗,或者被消耗的速度小于产生的速度,令牌就会不断地增多,直到把桶填满。后面再产生的令牌就会从桶中溢出。
最后桶中可以保存的最大令牌数永远不会超过桶的大小,每当一个请求过来时,就会尝试从桶里移除一个令牌,如果没有令牌的话,请求无法通过。
C# 代码实现
public class TokenBucketLimiter
{
private long Capacity;//桶的容量,也就是令牌的数量
private long WindowTimeInSeconds;
private long LastRefillTimeStamp;
private long RefillCountPerSecond;
private long AvailableTokens;
public TokenBucketLimiter(long capacity, long windowTimeInSeconds)
{
this.Capacity = capacity;//200
this.WindowTimeInSeconds = windowTimeInSeconds;//60
this.LastRefillTimeStamp = DateTime.Now.Ticks / 10000; //63751161398349
this.RefillCountPerSecond = capacity / windowTimeInSeconds; //200 / 60
this.AvailableTokens = 0;
}
public long GetAvailableTokens()
{
return this.AvailableTokens;
}
public bool TryAcquire()
{
//更新令牌桶
Refill();
if (AvailableTokens > 0)
{
--AvailableTokens;
return true;
}
else
{
return false;
}
}
private void Refill()
{
long now = DateTime.Now.Ticks / 10000;
if (now > LastRefillTimeStamp)
{
long elapsedTime = now - LastRefillTimeStamp;
int tokensToBeAdded = (int)((elapsedTime / 1000) * RefillCountPerSecond);
if (tokensToBeAdded > 0)
{
AvailableTokens = Math.Min(Capacity, AvailableTokens + tokensToBeAdded);
LastRefillTimeStamp = now;
}
}
//
}
}
这两种算法的主要区别在于漏桶算法能够强行限制数据的传输速率,而令牌桶算法在能够限制数据的平均传输速率外,还允许某种程度的突发传输。
在令牌桶算法中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。
总结:漏通和令牌通算法比较
漏桶和令牌桶算法实现可以一样,但是方向是相反的,对于相同的参数得到的限流效果是一样的。
主要区别在于令牌桶允许一定程度的突发,漏桶主要目的是平滑流入速率,考虑一个临界场景,令牌桶内积累了 100 个 Token,可以在一瞬间通过。
但是因为下一秒产生 Token 的速度是固定的,所以令牌桶允许出现瞬间出现 permitsPerSecond 的流量,但是不会出现 2*permitsPerSecond 的流量,漏桶的速度则始终是平滑的。
2.2.2 APISIX 使用
注意:上述配置限制了每秒请求速率为 1,大于 1 小于 3 的会被加上延时,速率超过 3 就会被拒绝,返回503。
只要你手速够快,就可以看到这样的返回结果,说明,成功被APISIX限流。
官网中对参数的介绍:
好了,暂时先了解到这里,后面还会陆续更新APISIX 相关的实战经验,想要详细了解的朋友,可以到官网深入学习,因为是国产开源APISIX网关,文档非常友好!
参考资料:
(1)https://apisix.apache.org/docs/apisix/FAQ/
(2)https://github.com/apache/apisix
(3)https://github.com/apache/apisix-dashboard
作者:郭峥
出处:http://www.cnblogs.com/runningsmallguo/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。