日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
可以在Nginx中運行JavaScript,厲害了!

 引言

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

10年積累的成都網(wǎng)站制作、網(wǎng)站建設(shè)經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有廣河免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

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

圖片

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

圖片

NGINX JavaScript 簡介

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

njs 與 Node.js、JavaScript 的區(qū)別

一、運行時不同

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

二、語言規(guī)范差異

JavaScript 的規(guī)范是由 ECMAScript 標(biāo)準(zhǔn)定義,隨著標(biāo)準(zhǔn)版本的更新迭代,會支持更多的語言功能;njs 自研的服務(wù)端運行時,更多的優(yōu)先支撐服務(wù)于 Nginx,只實現(xiàn)了 ECMAScript 5.1 和部分 ECMAScript 6,實現(xiàn)更多標(biāo)準(zhǔn)規(guī)范的同時,更多會考慮是否是 Nginx 所需要的。

njs 安裝&配置

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

 
 
 
 
  1. yum install nginx-module-njs 

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

 
 
 
 
  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 : 導(dǎo)入一個 njs 模塊,沒有指定模塊名稱則默認(rèn)為文件名稱。

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

HTTP Proxying

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

nginx.conf:

 
 
 
 
  1. js_import http.js;  
  2. location /start {  
  3.     js_content http.content;  
  4. }  
  5. location /foo {  
  6.     proxy_pass ;  
  7. }  
  8. location /bar {  
  9.     proxy_pass ;  

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 : 可以去請求內(nèi)部的其他 API ,headers 和該請求相同,并且可以在 location 塊里使用 proxy_set_header 來設(shè)置或覆蓋原來的 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 方法執(zhí)行后,執(zhí)行結(jié)果放到 $access_log_headers 變量中。但如果只被引用在 log_format 中,則只會在日志記錄階段被執(zhí)行。

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

訪問數(shù)據(jù)庫

一、訪問 Redis

使用 redis2-nginx-module 動態(tài)模塊,結(jié)合 subrequest 來訪問 Redis 數(shù)據(jù)。

nginx.conf:

 
 
 
 
  1. js_import http.js;# GET /redis_get?key=some_keylocation = /redis_get {     # 解碼 uri 中的參數(shù) 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 中參數(shù)的 %XX 編碼。

redis2_query : 執(zhí)行的 Redis 命令。

redis2_pass : Redis 后端服務(wù)。

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

二、訪問 MySQL

使用 drizzle-nginx-module 動態(tài)模塊,結(jié)合 subrequest 來訪問 MySQL 數(shù)據(jù)。

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 來設(shè)置 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 注入攻擊,來設(shè)置 sql 語句中的變量。

drizzle_query : 執(zhí)行的 SQL 語句。

drizzle_pass : Drizzle 或 MySQL 服務(wù)的 upstream。

結(jié)語

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


當(dāng)前文章:可以在Nginx中運行JavaScript,厲害了!
網(wǎng)站網(wǎng)址:http://m.5511xx.com/article/djsssis.html