網關技術選型,爲什麼選擇 Openresty ?事件驅動、協程---

大家好,我是 Tom 哥~

今天跟大家聊下關於網關的話題

互聯網公司,不論體量大小如何,其內部的技術架構基本都是相似的,體現在以下幾個方面:

麻雀雖小五臟俱全,今天要講的網關,就是其中的關鍵一環,不論公司規模大小如何,基本都要有這個系統。

那麼網關是幹什麼用的?

什麼是網關

網關是連接客戶端與服務端的中間橋樑,將很多通用地非業務邏輯抽離,前置到網關係統,減少了很多重複性開發工作,是整個網站的唯一流量入口。

爲了提高系統的擴展性,網關通常採用組件式架構,高內聚低耦合。

常用的組件功能:

系統設計上一般採用責任鏈設計模式,定義好抽象接口,每個組件實現自己的專屬功能,職責單一。並且根據不同的業務請求 API,添加、刪除一些節點,動態構建新的節點鏈,從而滿足多樣化的業務需求。

網關選型

1、Tomcat/Jetty+NIO+Servlet3

2、Nginx

3、Spring WebFlux

4、Soul

5、Spring cloud Gateway

6、Zuul

7、OpenResty

8、Kong

9、Netty 自建

各個框架的資料網上基本都有,考慮到篇幅限制,這裏就不展開分析每個框架的優缺點(如果感興趣,可以給我留言,人多的話我後面就單啓一篇文章來講一講)。

我們計劃選型 OpenResty,主要有以下幾個原因:

翻牌 OpenResty

下圖是 Netcraft 最新統計的 2021 年 10 月 Web 服務器排行榜

Netcraft 是一家總部位於英國巴斯始於 1995 年的互聯網服務公司。該公司官網每月發佈的調研數據報告:Web Server Survey 系列 已成爲當今人們瞭解全球網站的服務器市場份額

來源:https://news.netcraft.com/archives/2021/10/15/october-2021-web-server-survey.html

OpenResty 現在全球排名第三,由於將 Nginx 擴展成動態服務器,發展勢頭很猛。

我們常用的 12306 的餘票查詢功能,京東的商品詳情頁,這些高流量的背後,其實都是 OpenResty 在提供服務。

OpenResty 最擅長的是部署在流量入口處,處理各種高併發流量。

接下來,我們來深入瞭解下這個框架

OpenResty 誕生起因

nginx 採用 master-worker 進程模型,分工明確,職責單一,也是其具備高性能的原因之一。

1、master 進程

管理進程,處理指令如:-s reload-s stop,通過進程間通信,將管理指令發送給 worker 進程,從而實現對 worker 進程的控制。

2、worker 進程

工作進程,不斷接收客戶端的連接請求,處理請求。數量通常設置爲與 CPU 核數一致,nginx 也會將每個進程與每個 CPU 進行綁定,充分利用其多核特性。

多個 worker 進程會競爭一個共享鎖,只有搶到鎖的進程才能處理客戶端的請求。如果請求是 accept 事件,則會將其添加到 accept 隊列中;如果是 read 或者 write 事件,則會將其添加到 read-write 隊列。

可能有人問,OpenResty 爲什麼要基於 Nginx 框架?

主要還是看重了 Nginx 的高併發能力,反向代理服務器通常流量很大,本身不涉及複雜計算,屬於 I/O 密集型服務。Nginx 採用基於 epoll 機制的事件驅動,異步非阻塞,大大提高併發處理能力。

但是 Nginx 採用 C 語言 開發,二次開發門檻較高。市場應用廣泛,更多是基於 nginx.conf 預留配置參數,如:反向代理、負載均衡、靜態 web 服務器,等

如果想讓 Nginx 訪問 MySQL ,定製化開發一些業務邏輯,難度很高。OpenResty 通過 嫁接方式,將 Nginx 和 Lua 腳本相結合,既保留 Nginx 高併發優勢,也擁有腳本語言的開發效率,也大大降低了開發門檻。

Lua 是最快的、動態腳本語言,接近 C 語言運行速度。LuaJIT 將一些常用的 lua 函數和工具庫預編譯並緩存,下次調用時直接使用緩存的字節碼,速度很快。

另外,Lua 支持協程,這個很重要。

協程是用戶態的操作,上下文切換不用涉及內核態,系統資源開銷小;另外協程佔用內存很小,初始 2KB

OpenResty 核心架構

OpenResty 是一個基於 Nginx 的 Web 平臺,內部嵌入LuaJIT虛擬機運行 Lua 腳本。使用 Lua 編程語言對 Nginx 核心以及各種 Nginx C 模塊進行腳本編程。

注意:不同的 lua 協程之間數據隔離,從而保證了不同的客戶端請求不會相互影響。另外,一個 worker 中同一時刻,只會有一個協程在運行。

cosocket 將 Lua 協程 + Nginx 事件通知兩個重要特性組合。

cosocket 是 OpenResty 世界中技術、實用價值最高部分。讓我們可以用非常低廉的成本,優雅的姿勢,比傳統 socket 編程效率高好幾倍的方式進行網絡編程。無論資源佔用、執行效率、併發能力都非常出色。

爲了方便開發,OpenResty 將一個 HTTP 請求劃分爲 11 個階段,每個階段有自己的專屬職責。

函數功能說明:

OpenResty 提供了大量的 Lua API 接口,用於操作 Nginx 。只要熟悉 lua 語法,同時對 Nginx 的運行流程有較清楚理解,那麼就可以輕鬆的在 nginx 上做二次開發。

無論是作爲應用網關,還是高性能的 web 應用,支持連接各種豐富的後端存儲,如:MySQL、Redis、Memcache、PostgreSQL 等,周邊生態非常豐富。

https://github.com/openresty/lua-nginx-module/#accessbylua

注意:OpenResty 的 API 有使用範圍限制,每個 API 都有與之對應的使用階段列表,如果你超範圍使用就會報錯。

部署安裝

本文以 CentOS 系統中爲例

1、添加 openresty 倉庫,這樣以後可以通過 yum updata 命令安裝或更新我們的軟件包

yum install yum-utils -y
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo

2、安裝軟件

yum install openresty -y

3、安裝命令行工具 resty

yum install openresty-resty -y

項目實戰

1、修改 nginx.conf 配置文件

worker_processes  auto;
worker_rlimit_nofile 1000000;
events {
    use epoll;
    worker_connections  150000;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $content_length $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" "$upstream_response_time" "$request_time"';

    access_log  logs/access.log  main;
    
    server {
        listen 8080;
        location / {
            access_by_lua_block {
                local headers = ngx.req.get_headers(0)
                local trace_id= headers["X-Trace-Id"]
                ngx.log(ngx.ERR, trace_id)
            }
            #  ngx.say("<p>hello !</p>")
            proxy_pass http://168.12.8.10:8080;
        }
    }

    server {
        listen 8082;
        location / {
            default_type text/html;
            content_by_lua_block {
                ngx.say("<p>Hello Openresty!</p>")
            }
        }
    }
}

nginx.conf 內部分爲三層嵌套:

2、添加環境變量

echo "export PATH=$PATH:/usr/local/openresty/nginx/sbin" >> /etc/profile
source /etc/profile

3、啓動 openresty,啓動命令和 nginx 一致

nginx -c /usr/local/openresty/nginx/conf/nginx.conf

4、訪問 Web 服務

curl http://localhost:8082/

如果正常,瀏覽器頁面會輸出 Hello Openresty!

5、如果 nginx.conf 配置項做了修改,我們可以重新啓動

nginx  -s reload

關於我:Tom 哥,前阿里 P7 技術專家,多年大廠實戰經驗。歡迎關注,我會持續輸出更多經典原創文章,爲你大廠助力。

歡迎小夥伴找 Tom 哥嘮嗑聊天, 技術交流,圍觀朋友圈,打怪人生不再寂寞。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/jL0GiOH9jpod7DVGa1fQBw