01 . OpenResty簡介部署,優缺點,壓測,適用場景及用Lua實現服務灰度發布


簡介

OpenResty® 是一個基於 Nginx 與 Lua 的高性能 Web 平台,其內部集成了大量精良的 Lua 庫、第三方模塊以及大多數的依賴項。用於方便地搭建能夠處理超高並發、擴展性極高的動態 Web 應用、Web 服務和動態網關。

OpenResty® 通過匯聚各種設計精良的 Nginx 模塊(主要由 OpenResty 團隊自主開發),從而將 Nginx 有效地變成一個強大的通用 Web 應用平台。這樣,Web 開發人員和系統工程師可以使用 Lua 腳本語言調動 Nginx 支持的各種 C 以及 Lua 模塊,快速構造出足以勝任 10K 乃至 1000K 以上單機並發連接的高性能 Web 應用系統。

OpenResty® 的目標是讓你的Web服務直接跑在 Nginx 服務內部,充分利用 Nginx 的非阻塞 I/O 模型,不僅僅對 HTTP 客戶端請求,甚至於對遠程后端諸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都進行一致的高性能響應。

下載部署

wget https://openresty.org/download/openresty-1.13.6.2.tar.gz
cd openresty-1.13.6.2
./configure 
make && make install

目錄結構

[root@server openresty]# ls
bin  COPYRIGHT  luajit  lualib  nginx  pod  resty.index  site


# 分析目錄結構
# 相比Nginx源代碼目錄相比少了很多東西,少了的東西在bundle目錄下。build是編譯后生成的目標中間文件
# 在bundle目錄中有很多模塊,最核心的是Nginx源代碼,nginx-相應的版本中,當前的openresty基於nginx-1.13.6.2這個版本進行二次開發。


/root/openresty-1.13.6.2/configure --help
# 查看configure腳本幫助文件
# 和nginx幫助文件基本沒有太大的不同,只不過openresty集成了很多第三方模塊
# 前綴帶有without是默認是內置在編譯版本中的
# 前綴帶有with是默認是沒有在編譯版本中的

添加Lua代碼啟動

添加lua注意
/*
		在nginx.conf 中實際是可以直接添加Lua代碼,但是不能把Lua的語法Lua的源代碼直接放在conf中,因為nginx的解析器它的配置語法是跟Lua代碼是不相同的。
		在openresty的nginx lua模塊中,它提供了幾條指令,其中有一條指令是content_by_lua
		content_by_lua是在http請求處理的內容生成階段,我們用Lua代碼來處理。
*/


/*
		openresty的Lua模塊中提供了一些API 如ngx.say,會去生成http響應,瀏覽器在發起http請求中,它會在User-Agent這樣的head中,
		去添加當前瀏覽器的類型,我是xxx,我用了什么樣的內核,用ngx.req.ge_headers把用戶請求中的頭部取出來,然后找出User-Agent,把User-Agent值通過這樣一種文本方式返回給瀏覽器中.
		通過openresty的nginx lua模塊,我們可以用它提供給我們的API完成很多功能,我們可以利用Lua本身的一些工具庫把Lua語言添加進來參加我們生成響應的這樣一個過程中。
		直接使用openresty提供的API或者Lua代碼生成響應,為瀏覽器客戶端提供服務。
		我們可以使用Lua語言以及提供的相應的API庫直接去訪問Redis,Mysql,Tomcat等這樣的服務,然后把不同的響應通過程序邏輯組成相應的http響應返回給用戶
*/
修改配置文件
[root@server nginx]# cat /usr/local/openresty/nginx/conf/nginx.conf

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;

				location /lua {
	    		 default_type text/html;
	    		 content_by_lua '
	    		 ngx.say("User-Agent: ", ngx.req.get_headers()["User-Agent"])
	    		 ';
				}

        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

# 啟動
[root@server nginx]# cat /usr/local/openresty/nginx/sbin/nginx
訪問

Linux下ab性能測試

下載配置ab
[root@server openresty]# yum -y install httpd-tools
[root@server openresty]# ab -V
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
1W並發壓力測試
[root@server openresty]# ab -c 10000 -n 100000 127.0.0.1/lua
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests


Server Software:        openresty/1.13.6.2   # 服務器信息和版本
Server Hostname:        127.0.0.1		# 服務器的域名
Server Port:            80		# 端口

Document Path:          /lua  # 訪問的路徑
Document Length:        28 bytes   # 文檔大小

Concurrency Level:      10000   # 並發請求數
Time taken for tests:   5.978 seconds   # 整個測試持續的時間
Complete requests:      100000  # 完成的請求數
Failed requests:        196008  # 失敗的請求數
   (Connect: 0, Receive: 0, Length: 98912, Exceptions: 97096)
Write errors:           0        # 網絡連接寫入錯誤數
Total transferred:      511104 bytes   # 傳輸的總數據量
HTML transferred:       81312 bytes    # 傳輸的HTML內容量
Requests per second:    16729.18 [#/sec] (mean)   # 平均每秒請求數
Time per request:       597.758 [ms] (mean)   # 所有用戶請求一次的平均時間
Time per request:       0.060 [ms] (mean, across all concurrent requests)  # 單個用戶請求一次的時間
Transfer rate:          83.50 [Kbytes/sec] received  # 傳輸速率

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  323 302.4    256    3359
Processing:    64  246  62.9    247     525
Waiting:        0    8  48.8      0     342
Total:        283  570 304.2    512    3566


# 所有服務請求的百分比占用時間,這里50%的請求用時512ms, 一般看90%的部分
Percentage of the requests served within a certain time (ms)
  50%    512
  66%    541
  75%    545
  80%    547
  90%    556
  95%   1463
  98%   1524
  99%   1555
 100%   3566 (longest request)
1.5W並發壓力測試
[root@server openresty]# ab -c 15000 -n 100000 127.0.0.1/lua
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests


Server Software:        openresty/1.13.6.2
Server Hostname:        127.0.0.1
Server Port:            80

Document Path:          /lua
Document Length:        28 bytes

Concurrency Level:      15000
Time taken for tests:   6.128 seconds
Complete requests:      100000
Failed requests:        201164
   (Connect: 0, Receive: 0, Length: 102820, Exceptions: 98344)
Write errors:           0
Total transferred:      291456 bytes
HTML transferred:       46368 bytes
Requests per second:    16317.62 [#/sec] (mean)
Time per request:       919.252 [ms] (mean)
Time per request:       0.061 [ms] (mean, across all concurrent requests)
Transfer rate:          46.44 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  471 296.5    409    3498
Processing:    74  380 100.9    383     878
Waiting:        0    7  57.5      0     573
Total:        494  851 303.4    808    4077

Percentage of the requests served within a certain time (ms)
  50%    808
  66%    818
  75%    832
  80%    856
  90%    888
  95%   1750
  98%   1812
  99%   1832
 100%   4077 (longest request)
2W並發壓力測試
[root@server openresty]# ab -c 20000 -n 100000 127.0.0.1/lua
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests


Server Software:        openresty/1.13.6.2
Server Hostname:        127.0.0.1
Server Port:            80

Document Path:          /lua
Document Length:        28 bytes

Concurrency Level:      20000
Time taken for tests:   6.101 seconds
Complete requests:      100000
Failed requests:        194710
   (Connect: 0, Receive: 0, Length: 97430, Exceptions: 97280)
Write errors:           0
Total transferred:      478720 bytes
HTML transferred:       76160 bytes
Requests per second:    16389.97 [#/sec] (mean)
Time per request:       1220.258 [ms] (mean)
Time per request:       0.061 [ms] (mean, across all concurrent requests)
Transfer rate:          76.62 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  625 432.2    507    3665
Processing:   107  474 149.2    441    1024
Waiting:        0   15  94.3      0     714
Total:        521 1099 443.9    984    4362

Percentage of the requests served within a certain time (ms)
  50%    984
  66%   1005
  75%   1010
  80%   1019
  90%   1949
  95%   1997
  98%   2131
  99%   2421
 100%   4362 (longest request)

通過lua實現灰度發布

nginx.conf

[root@server conf]# cat nginx.conf
user  root;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream up1{
	server 127.0.0.1:8081;
    }
    upstream up2{
	server 127.0.0.1:8082;
    }
    upstream all{
	ip_hash;
        serever 127.0.0.1:8081;
        serever 127.0.0.1:8082;
    }
    server {
        listen       80;
        server_name  localhost;

    		# 請求交給lua腳本處理
				location / {
	    		lua_code_cache off;
        	content_by_lua_file /usr/local/nginx/lua/proxy.lua;
				}

				# location @ 用於nginx內部跳轉
				location @up1 {
	    		proxy_pass http://up1;
				}


				location @up2 {
	 		   proxy_pass http://up2;
				}

				location @all {
	   			 proxy_pass http://all;
				}
   }
}

proxy.lua

ngx.header.content_type="text/html;charset=utf8"
redis = require('resty.redis')
redis = redis.new()
redis:set_timeout(1000)
 
ok,err =  redis:connect('127.0.0.1', 6379)
 
if not ok then
    ngx.say('connect to redis failed ! reason: ' .. err)
end
 
-- 從redis中檢查是否存在即將更新的upstream主機
check_up1 = redis:get('update1') --(up1)
check_up2 = redis:get('update2') --(up2)
redis:close()
-- 注意返回的數據類型來判斷
if check_up1 == "1" then
    ngx.exec("@up2")
elseif check_up2 == "1" then
    ngx.exec("@up1")
else
    ngx.exec("@all")
end

-- 原理就是利用redis中設置指定key,比如要更新主機1,則redis中添加key=update1,value=1,當瀏覽器請求進入nginx的content階段后執行lua腳本,
-- 腳本中檢查redis中是否存在要更新的主機,如果發現某個主機要更新則通過Nginx API for Lua中的ngx.exec接口內部跳轉到另一台主機。
-- 如果兩個都不更新,則根據nginx自己的方式(默認輪詢)分發請求。
-- nginx里使用了ip_hash保持會話,主要是為了用戶的請求在后端記錄的日志中保持完整。

優點

高並發

根據以上的測試來看,一台1核700兆的linux虛擬機即可跑出2W的並發,足以說明OpenResty處理高並發的能力,由於ab工具的限制,只能測試上限2W的並發,因此,這里也只做到了2W的測試。

熱更新

Lua屬於腳本語言,編譯之后即可運行;Nginx具備優雅重啟的功能;因此,線上業務如果出現問題需要及時修復的,更新修改Lua腳本之后,重啟Nginx即可完成更新發布;如果沒有配置Lua緩存功能的話,只要更新Lua腳本即可更新修復線上問題,不重啟Nginx也可以。

缺點

不適合處理復雜的業務邏輯

由於功能性的東西主要使用Lua進行開發,受Lua語言特性的影響,不太適合做業務比較復雜的功能。

互聯網上資料少

互聯網上可以找的資料比較少;不過,本身Lua的學習過程不是特別的復雜,所以,這基本不會成為你學習它的障礙

適用場景

高仿問下應用及官網主頁

如商城,咨詢類的應用首頁,會存在大量的請求,由於涉及到的內容比較多;所以可是私用預載入的形式,將主頁的數據放置在redis中;使用OpenResty+redis實現首頁,官網主頁的高並發加載.

商城類的秒殺功能

秒殺功能會存在短時間的請求洪峰,如果處理不當可能會造成down機的風險,可以結合OpenResty+redis實現秒殺的功能.

ip限流

互聯網系統可能存在非法用戶惡意暴力請求,導致正常的用戶無法使用,可以通過OpenResty+redis實現ip的白名單機制,去攔截非法的用戶ip

APP灰度升級發布

可以根據系統的數據及條件實現APP的灰度升級測試


免責聲明!

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



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