.Net Core 3.1 -- APISIX2.6 微服务网关入门

前言:

(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/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

posted @ 2021-06-08 09:21  菠萝吹雪—Code  阅读(2269)  评论(0编辑  收藏  举报