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

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM