成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

可以在 Nginx 中運行 JavaScript,厲害了!

開發 前端
Nginx 作為市場占有率最高的Web服務器,主打高性能、可擴展。自帶了很多核心功能模塊,并且也有大量的第三方模塊。

 引言

Nginx 作為市場占有率最高的Web服務器,主打高性能、可擴展。自帶了很多核心功能模塊,并且也有大量的第三方模塊。

Web 服務中灰度方案的實現,很多會采用 Nginx + Lua + Redis 方案。Lua 是一個輕量級的腳本語言,體積小、啟動速度快、性能高。通過 lua-nginx-module 模塊將 Lua 語言嵌入到 Nginx 中,可以使用 Lua 腳本擴展 Nginx 功能,并可以訪問 MySQL、Redis 等數據庫。

圖片

Lua 雖然是個強大的腳本語言,但過于小眾。Nginx 團隊選擇非常流行的 JavaScript 研發 NGINX JavaScript 模塊 (njs),讓更多工程師可以使用 JavaScript 來擴展 Nginx 功能,從而更好的發展 Nginx 社區生態。

圖片

NGINX JavaScript 簡介

NGINX JavaScript 簡稱 njs,是 JavaScript 語言的子集,實現了部分 ECMAScript 5.1(strict mode)規范和 ECMAScript 6 規范,可以使用 njs 來擴展 Nginx 功能。

njs 與 Node.js、JavaScript 的區別

一、運行時不同

Node.js 使用 V8 引擎,njs 是專門為 Nginx 定制設計的運行時。Node.js 使用 V8 引擎在內存中有一個持久化的 JavaScript 虛擬機 (VM) 并執行垃圾收集以進行內存管理;而 njs 是專門為 Nginx 設計,非常輕量,會為每個請求初始化一個新的 JavaScript VM 和必要的內存,并在請求完成時釋放內存。

二、語言規范差異

JavaScript 的規范是由 ECMAScript 標準定義,隨著標準版本的更新迭代,會支持更多的語言功能;njs 自研的服務端運行時,更多的優先支撐服務于 Nginx,只實現了 ECMAScript 5.1 和部分 ECMAScript 6,實現更多標準規范的同時,更多會考慮是否是 Nginx 所需要的。

njs 安裝&配置

安裝 nginx-module-njs 動態模塊,需要 Nginx 版本為 1.9.11 之后支持動態模塊的載入。 

  1. yum install nginx-module-njs 

安裝后,在配置文件 nginx.conf 中需要使用 load_module 指令加載 njs 動態模塊。 

  1. load_module modules/ngx_http_js_module.so; 

njs 基本使用

Hello World

nginx.conf: 

  1. http {  
  2.     js_import http.js;  
  3.     # or js_import http from http.js;  
  4.     server {  
  5.         listen 8000;  
  6.         location / {  
  7.             js_content http.hello;  
  8.         }  
  9.     }  

http.js: 

  1. function hello(r) {  
  2.     r.return(200, "Hello world!");  
  3.  
  4. export default { hello }; 

js_import : 導入一個 njs 模塊,沒有指定模塊名稱則默認為文件名稱。

js_content : 使用 njs 模塊里導出的方法處理這個請求。

HTTP Proxying

使用 njs 模塊處理 HTTP 請求,并使用 subrequest 發起子請求。

nginx.conf: 

  1. js_import http.js;  
  2. location /start {  
  3.     js_content http.content;  
  4.  
  5. location /foo {  
  6.     proxy_pass <http://backend1> 
  7.  
  8. location /bar {  
  9.     proxy_pass <http://backend2> 

http.js: 

  1. function content(r) {  
  2.     r.subrequest('/api/5/foo', {  
  3.           method: 'POST',  
  4.           body: JSON.stringify({ foo: 'foo', bar: "bar" })  
  5.     }, function(res) {  
  6.             if (res.status != 200) {  
  7.                 r.return(res.status, res.responseBody);  
  8.                 return;  
  9.             }  
  10.             var json = JSON.parse(res.responseBody);  
  11.             r.return(200, json.content);  
  12.     });  
  13.  
  14. export default { content }; 

r.subrequest : 可以去請求內部的其他 API ,headers 和該請求相同,并且可以在 location 塊里使用 proxy_set_header 來設置或覆蓋原來的 header。

自定義日志輸出格式

使用 njs 定制 Nginx 日志的輸出格式。

nginx.js: 

  1. js_import  logging.js;  
  2. js_set     $access_log_headers logging.kvAccess;  
  3. log_format kvpairs $access_log_headers;  
  4. server {  
  5.     listen 80;  
  6.     root /usr/share/nginx/html;  
  7.     access_log /var/log/nginx/access.log kvpairs;  

logging.js: 

  1. function kvAccess(r) {  
  2.     var log = `${r.variables.time_iso8601} client=${r.remoteAddress} method=${r.method} uri=${r.uri} status=${r.status}`;  
  3.     r.rawHeadersIn.forEach(h => log += ` in.${h[0]}=${h[1]}`);  
  4.     r.rawHeadersOut.forEach(h => log += ` out.${h[0]}=${h[1]}`);  
  5.     return log;  
  6.  
  7. export default { kvAccess } 

js_set : 將 njs 模塊里的 kvAccess 方法執行后,執行結果放到 $access_log_headers 變量中。但如果只被引用在 log_format 中,則只會在日志記錄階段被執行。

r : HTTP request 對象。屬性列表:http://nginx.org/en/docs/njs/reference.html#http

訪問數據庫

一、訪問 Redis

使用 redis2-nginx-module 動態模塊,結合 subrequest 來訪問 Redis 數據。

nginx.conf: 

  1. js_import http.js;# GET /redis_get?key=some_keylocation = /redis_get {     # 解碼 uri 中的參數 key,賦值到變量 $key     set_unescape_uri $key $arg_key;     redis2_query get $key;     redis2_pass 127.0.0.1:6379;}# GET /redis_set?key=one&val=first%20valuelocation = /redis_set {     set_unescape_uri $key $arg_key;     set_unescape_uri $val $arg_val;     redis2_query set $key $val;     redis2_pass 127.0.0.1:6379;}# GET /get_redis_data?key=some_keylocation /get_redis_data {    js_content http.get_redis_data;} 

http.js: 

  1. function serialize(obj) {    var str = [];    for (var p in obj) {        if (obj.hasOwnProperty(p)) {            str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));        }    }    return str.join("&");};function get_redis_data(r) {    r.subrequest('/redis_get', {          args: serialize(r.args),          method: 'GET'    }, function(res) {            if (res.status != 200) {                r.return(res.status, res.responseBody);                return;            }            r.return(200, res.responseBody);    });    return log;}export default { get_redis_data } 

set_unescape_uri :解碼 uri 中參數的 %XX 編碼。

redis2_query : 執行的 Redis 命令。

redis2_pass : Redis 后端服務。

redis2_pass 返回值為類似 redis-cli 執行后的返回值,需要有一個 parser 來解析是否執行成。

二、訪問 MySQL

使用 drizzle-nginx-module 動態模塊,結合 subrequest 來訪問 MySQL 數據。

nginx.conf: 

  1. upstream backend {  
  2.     drizzle_server 127.0.0.1:3306 dbname=test  
  3.         password=some_pass user=monty protocol=mysql 
  4.  
  5. server {  
  6.     js_import http.js;  
  7.     location /mysql {  
  8.          set_unescape_uri $name $arg_name;  
  9.          # 為防止 SQL 注入攻擊,使用 set_quote_sql_str 來設置 sql 語句中的變量  
  10.          set_quote_sql_str $quoted_name $name;  
  11.          drizzle_query "select * from cats where name = $quoted_name";  
  12.          drizzle_pass backend;  
  13.          drizzle_connect_timeout    500ms; # default 60s  
  14.          drizzle_send_query_timeout 2s;    # default 60s  
  15.          drizzle_recv_cols_timeout  1s;    # default 60s  
  16.          drizzle_recv_rows_timeout  1s;    # default 60s  
  17.     }  
  18.     # GET /get_mysql_data?name=cat_name  
  19.     location /get_mysql_data {  
  20.         js_content http.get_mysql_data;  
  21.     }  

http.js: 

  1. function serialize(obj) {  
  2.     var str = [];  
  3.     for (var p in obj) {  
  4.         if (obj.hasOwnProperty(p)) {  
  5.             str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));  
  6.         }  
  7.     }  
  8.     return str.join("&");  
  9. };  
  10. function get_mysql_data(r) {  
  11.     r.subrequest('/mysql', {  
  12.           args: serialize(r.args),  
  13.           method: 'GET'  
  14.     }, function(res) {  
  15.             if (res.status != 200) {  
  16.                 r.return(res.status, res.responseBody);  
  17.                 return;  
  18.             }  
  19.             r.return(200, res.responseBody);  
  20.     });  
  21.     return log; 
  22.   
  23. export default { get_mysql_data } 

set_quote_sql_str : 為防止 SQL 注入攻擊,來設置 sql 語句中的變量。

drizzle_query : 執行的 SQL 語句。

drizzle_pass : Drizzle 或 MySQL 服務的 upstream。

結語

在 njs 之前,Nginx+Lua 生態雖然已日趨成熟,但 Nginx 畢竟是一個 Web 服務器,JavaScript 作為 Web 開發的最流行的語言,可以使用 JavaScript 生態來擴展 Nginx 的功能,可能會更加的有一些想象力做更多的事情。 

 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2021-03-01 12:06:12

Nginx命令Linux

2022-01-11 12:13:33

JavaScript編程語言

2018-04-11 14:30:33

2017-02-23 08:00:04

智能語音Click

2018-05-14 22:58:14

戴爾

2023-05-06 06:47:46

Bing聊天機器人

2021-03-29 13:06:25

開源工具開源

2021-12-27 07:59:50

ECMAScript JSON模塊Node.js

2021-11-01 07:50:44

TomcatWeb應用

2021-04-19 11:22:24

人工智能人臉識別科學

2020-06-08 17:35:27

Redis集群互聯網

2020-03-10 13:35:23

Gihub搜索開源

2022-04-08 08:11:28

Python代碼

2021-06-03 09:30:30

Python操作注冊表regedit

2022-01-25 08:36:29

array.flat映射函數數組

2017-10-20 11:50:39

2024-02-26 12:42:40

2019-11-25 21:53:48

代碼算法BUG

2017-07-27 16:51:19

數字化環衛信息化

2022-05-03 23:44:21

Python動態鏈接庫Ctypes
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 99久久精品国产一区二区三区 | 欧美性另类 | 草久视频 | 欧美影院 | 欧美久久免费观看 | 很黄很污的网站 | 国产精品爱久久久久久久 | 精产国产伦理一二三区 | 色又黄又爽网站www久久 | 欧美一区二区三区视频在线观看 | 国产一区精品在线 | 色视频在线播放 | 亚洲精品视频一区二区三区 | 国产中文字幕网 | 91精品久久久久久久久久小网站 | 国产精品美女在线观看 | 91久久精品日日躁夜夜躁国产 | 91精品久久久久久久 | 免费看大片bbbb欧美 | 亚洲人成人一区二区在线观看 | 精品欧美一区二区三区久久久 | 午夜影院网站 | 久久国产精品一区 | 国产精品美女久久久久久不卡 | 日韩中文字幕在线视频观看 | 国产午夜精品一区二区 | 欧美亚洲一区二区三区 | 免费激情av | 久久男人 | 欧美在线a| 成人 在线 | 一级黄片一级毛片 | 日韩一区三区 | 国产精品免费小视频 | 色综合天天网 | 91福利网址| 91在线第一页 | 日韩欧美国产一区二区三区 | 国产一区二区黑人欧美xxxx | 特黄小视频| 色欧美综合|