บทความนี้เป็นแนวคิดล่าสุดที่ฉันได้พัฒนาในระหว่างกระบวนการเรียนรู้ Node.js และฉันจะพูดคุยกับคุณ
node.js เซิร์ฟเวอร์ HTTP
การใช้ node.js สามารถใช้ในการใช้บริการ HTTP ได้อย่างง่ายดายมาก ตัวอย่างที่ง่ายที่สุดเป็นเหมือนตัวอย่างของเว็บไซต์ทางการ:
การคัดลอกรหัสมีดังนี้:
var http = ต้องการ ('http');
http.createserver (ฟังก์ชั่น (req, res) {
res.writehead (200, {'content-type': 'text/plain'});
Res.end ('Hello World/N');
}). ฟัง (1337, '127.0.0.1');
สิ่งนี้จะสร้างบริการเว็บอย่างรวดเร็วที่รับฟังคำขอ HTTP ทั้งหมดในพอร์ต 1337
อย่างไรก็ตามในสภาพแวดล้อมการผลิตจริงโดยทั่วไปเราไม่ค่อยใช้ node.js โดยตรงเป็นเว็บเซิร์ฟเวอร์ส่วนหน้าสำหรับผู้ใช้ เหตุผลหลักมีดังนี้:
1. ขึ้นอยู่กับคุณลักษณะแบบเธรดเดี่ยวของ Node.js การรับประกันความทนทานนั้นค่อนข้างสูงสำหรับนักพัฒนา
2. บริการ HTTP อื่น ๆ บนเซิร์ฟเวอร์อาจครอบครองพอร์ต 80 แล้วและบริการเว็บที่ไม่ใช่พอร์ต 80 นั้นไม่ได้ใช้งานง่ายพอสำหรับผู้ใช้
3.node.js ไม่มีข้อได้เปรียบในการประมวลผลไฟล์ io มากนัก ตัวอย่างเช่นเป็นเว็บไซต์ปกติอาจทำให้คุณต้องตอบกลับไปยังแหล่งข้อมูลเช่นรูปภาพในเวลาเดียวกัน
4. สถานการณ์โหลดแบบกระจายก็เป็นสิ่งที่ท้าทายเช่นกัน
ดังนั้นการใช้ node.js เป็นบริการเว็บอาจมีแนวโน้มที่จะเป็นอินเทอร์เฟซเซิร์ฟเวอร์เกมและสถานการณ์ที่คล้ายกันอื่น ๆ ส่วนใหญ่จะจัดการกับบริการที่ไม่ต้องการการเข้าถึงผู้ใช้โดยตรงและดำเนินการแลกเปลี่ยนข้อมูลเท่านั้น
Node.js Web Service ตาม Nginx เป็นเครื่อง front-end
ขึ้นอยู่กับเหตุผลข้างต้นหากเป็นผลิตภัณฑ์ที่มีรูปทรงเว็บไซต์ที่สร้างขึ้นด้วย node.js วิธีการใช้งานทั่วไปคือการวางเซิร์ฟเวอร์ HTTP ที่เป็นผู้ใหญ่อีกครั้งที่ปลายด้านหน้าของบริการเว็บของ Node.js เช่น Nginx เป็นที่ใช้กันมากที่สุด
จากนั้นใช้ Nginx เป็นพร็อกซีย้อนกลับเพื่อเข้าถึงบริการเว็บที่ใช้ Node.js ชอบ:
การคัดลอกรหัสมีดังนี้:
เซิร์ฟเวอร์ {
ฟัง 80;
server_name yekai.me;
รูท/บ้าน/Andy/wwwroot/yekai;
ที่ตั้ง / {
proxy_pass http://127.0.0.1:1337;
-
สถานที่ ~ /.(gif| jpg thar
รูท/โฮม/แอนดี้/wwwroot/yekai/คงที่;
-
-
สิ่งนี้จะดีกว่าการแก้ปัญหาหลายอย่างที่เกิดขึ้นข้างต้น
การสื่อสารโดยใช้โปรโตคอล FastCGI
อย่างไรก็ตามมีบางสิ่งที่ไม่ค่อยดีเกี่ยวกับวิธีพร็อกซีข้างต้น
หนึ่งคือสถานการณ์ที่เป็นไปได้ที่ต้องใช้การเข้าถึง HTTP โดยตรงไปยังบริการเว็บ node.js ที่ต้องมีการควบคุมในภายหลัง อย่างไรก็ตามหากคุณต้องการแก้ปัญหาคุณสามารถใช้บริการของคุณเองหรือพึ่งพาไฟร์วอลล์เพื่อบล็อก
อีกเหตุผลหนึ่งคือวิธีการพร็อกซีเป็นวิธีแก้ปัญหาที่เลเยอร์แอปพลิเคชันเครือข่ายหลังจากทั้งหมดและไม่สะดวกมากที่จะได้รับโดยตรงและประมวลผลข้อมูลที่โต้ตอบกับไคลเอนต์ HTTP เช่นการประมวลผลการรักษาความสัมพันธ์ลำต้นและแม้กระทั่งคุกกี้ แน่นอนว่าสิ่งนี้เกี่ยวข้องกับความสามารถและความสมบูรณ์แบบการทำงานของพร็อกซีเซิร์ฟเวอร์เอง
ดังนั้นฉันกำลังคิดที่จะลองวิธีอื่นในการจัดการกับมัน สิ่งแรกที่ฉันคิดคือวิธี FastCGI ที่ใช้กันทั่วไปในเว็บแอปพลิเคชัน PHP ในขณะนี้
fastcgi คืออะไร
Fast Gateway Interface (FastCGI) เป็นโปรโตคอลที่อนุญาตให้โปรแกรมแบบโต้ตอบสื่อสารกับเว็บเซิร์ฟเวอร์
พื้นหลังที่สร้างโดย FastCGI นั้นใช้เป็นทางเลือกในการใช้งานเว็บแอปพลิเคชัน CGI หนึ่งในคุณสมบัติที่ชัดเจนที่สุดคือกระบวนการบริการ FastCGI สามารถใช้ในการจัดการชุดของคำขอ เว็บเซิร์ฟเวอร์จะเชื่อมต่อตัวแปรสภาพแวดล้อมและคำขอหน้านี้ไปยังเว็บเซิร์ฟเวอร์ผ่านซ็อกเก็ตเช่นกระบวนการ FastCGI การเชื่อมต่อสามารถเชื่อมต่อกับเว็บเซิร์ฟเวอร์โดยซ็อกเก็ตโดเมน Unix หรือการเชื่อมต่อ TCP/IP สำหรับความรู้พื้นฐานเพิ่มเติมโปรดดูที่รายการของ Wikipedia
การใช้งาน fastcgi ของ node.js
ดังนั้นในทางทฤษฎีเราจำเป็นต้องใช้ node.js เพื่อสร้างกระบวนการ FastCGI จากนั้นระบุว่าคำขอการฟังของ Nginx ถูกส่งไปยังกระบวนการนี้ เนื่องจาก nginx และ node.js เป็นทั้งแบบจำลองการบริการที่ขับเคลื่อนด้วยเหตุการณ์พวกเขาควรเป็น "ทฤษฎี" โซลูชั่นเพื่อให้เข้ากับโลก มาทำด้วยตัวเอง
ใน node.js โมดูลสุทธิสามารถใช้เพื่อสร้างบริการซ็อกเก็ต เพื่อความสะดวกเราเลือกวิธี UNIX Socket
ด้วยการปรับเปลี่ยนการกำหนดค่า NGINX เล็กน้อย:
การคัดลอกรหัสมีดังนี้:
-
ที่ตั้ง / {
fastcgi_pass unix: /tmp/node_fcgi.sock;
-
-
สร้างไฟล์ใหม่ node_fcgi.js ด้วยเนื้อหาต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
var net = ต้องการ ('net');
var server = net.createServer ();
Server.Listen ('/tmp/node_fcgi.sock');
Server.on ('การเชื่อมต่อ', ฟังก์ชั่น (ถุงเท้า) {
console.log ('การเชื่อมต่อ');
sock.on ('data', function (data) {
console.log (ข้อมูล);
-
-
จากนั้นเรียกใช้ (เนื่องจากการอนุญาตโปรดตรวจสอบให้แน่ใจว่าสคริปต์ Nginx และโหนดทำงานกับผู้ใช้หรือบัญชีเดียวกันที่มีสิทธิ์ร่วมกันมิฉะนั้นคุณจะพบปัญหาการอนุญาตเมื่ออ่านและเขียนไฟล์ถุงเท้า):
โหนด node_fcgi.js
เมื่อเข้าถึงเบราว์เซอร์เราจะเห็นว่าเทอร์มินัลที่ใช้งานสคริปต์โหนดปกติจะได้รับเนื้อหาข้อมูลเช่นนี้:
การคัดลอกรหัสมีดังนี้:
การเชื่อมต่อ
<บัฟเฟอร์ 01 01 00 01 00 08 00 00 00 01 00 00 00 00 00 00 01 04 00 01 01 87 01 ... >>
สิ่งนี้พิสูจน์ได้ว่ารากฐานทางทฤษฎีของเราได้บรรลุขั้นตอนแรก ต่อไปเราจะต้องหาวิธีการแยกเนื้อหาของบัฟเฟอร์นี้เท่านั้น
มูลนิธิโปรโตคอล FastCGI
บันทึก FastCGI ประกอบด้วยคำนำหน้าความยาวคงที่ตามด้วยจำนวนตัวแปรของเนื้อหาและเบาะเบาะ โครงสร้างบันทึกมีดังนี้:
การคัดลอกรหัสมีดังนี้:
typedef struct {
รุ่นถ่านที่ไม่ได้ลงนาม;
ประเภทถ่านที่ไม่ได้ลงนาม;
Char RequestIdB1 ที่ไม่ได้ลงนาม;
Char RequestIdB0 ที่ไม่ได้ลงนาม;
contentlengthb1 ที่ไม่ได้ลงนาม
contentlengthb0 ที่ไม่ได้ลงนาม
ถ่านถ่านที่ไม่ได้ลงนาม
ถ่านที่ไม่ได้ลงนามสงวนไว้;
Char contentData ที่ไม่ได้ลงนาม [ContentLength];
ถ่านที่ไม่ได้ลงนาม Paddingdata [PaddingLength];
} fcgi_record;
เวอร์ชัน: เวอร์ชันโปรโตคอล FastCGI ตอนนี้ใช้ 1 โดยค่าเริ่มต้น
ประเภท: ประเภทบันทึกสามารถถือได้ว่าเป็นสถานะที่แตกต่างกันและจะมีการหารือในรายละเอียดในภายหลัง
RequestId: ขอรหัสการร้องขอจะต้องสอดคล้องกันเมื่อกลับมา หากไม่ใช่กรณีของการเกิดพร้อมกันหลายครั้งเพียงแค่ใช้ 1 ที่นี่
ContentLength: ความยาวเนื้อหาความยาวสูงสุดที่นี่คือ 65535
PADDINGLENGTH: ความยาวของช่องว่างภายในใช้เพื่อเติมข้อมูลที่ยาวลงในจำนวนเต็มหลายตัวเต็ม 8 ไบต์ ส่วนใหญ่จะใช้ในการประมวลผลข้อมูลที่จัดตำแหน่งได้อย่างมีประสิทธิภาพมากขึ้นส่วนใหญ่สำหรับการพิจารณาประสิทธิภาพ
สงวนไว้: ไบต์ที่สงวนไว้สำหรับการขยายตัวครั้งต่อไป
ContentData: ข้อมูลเนื้อหาจริงมาพูดคุยกันอย่างละเอียดในภายหลัง
PaddingData: กรอกข้อมูลมันเป็น 0 อยู่แล้วเพียงแค่เพิกเฉยโดยตรง
สำหรับโครงสร้างและคำอธิบายเฉพาะโปรดดูเอกสารเว็บไซต์อย่างเป็นทางการ (http://www.fastcgi.com/devkit/doc/fcgi-spec.html#s3.3)
ขอชิ้นส่วน
ดูเหมือนง่ายมากแค่แยกวิเคราะห์และรับข้อมูลในครั้งเดียว อย่างไรก็ตามมีหลุมอยู่ที่นี่นั่นคือสิ่งที่กำหนดไว้ที่นี่คือโครงสร้างของหน่วยข้อมูล (บันทึก) ไม่ใช่โครงสร้างบัฟเฟอร์ทั้งหมด บัฟเฟอร์ทั้งหมดประกอบด้วยหนึ่งระเบียนและหนึ่งระเบียน ในตอนแรกมันอาจไม่ใช่เรื่องง่ายสำหรับนักเรียนที่คุ้นเคยกับการพัฒนาส่วนหน้า แต่นี่เป็นพื้นฐานสำหรับการทำความเข้าใจโปรโตคอล FastCGI และเราจะเห็นตัวอย่างเพิ่มเติมในภายหลัง
ดังนั้นเราจำเป็นต้องแยกวิเคราะห์บันทึกและแยกแยะบันทึกตามประเภทที่เราได้รับมาก่อน นี่คือฟังก์ชั่นง่าย ๆ ที่จะได้รับบันทึกทั้งหมด:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น getRcds (data, cb) {
var rcds = []
เริ่ม = 0,
ความยาว = data.length;
return function () {
if (start> = ความยาว) {
CB && CB (RCDs);
rcds = null;
กลับ;
-
var end = start + 8
header = data.slice (เริ่มต้นจบ)
เวอร์ชัน = ส่วนหัว [0]
type = header [1]
requestId = (ส่วนหัว [2] << 8) + ส่วนหัว [3],
ContentLength = (ส่วนหัว [4] << 8) + ส่วนหัว [5]
paddingLength = ส่วนหัว [6];
start = end + contentLength + paddingLength;
var body = contentLength? data.slice (end, contentLength): null;
rcds.push ([ประเภท, body, requestId]);
return arguments.callee ();
-
-
//ใช้
sock.on ('data', function (data) {
getRCDS (ข้อมูล, ฟังก์ชั่น (RCDs) {
-
-
โปรดทราบว่านี่เป็นเพียงกระบวนการง่ายๆ หากมีสถานการณ์ที่ซับซ้อนเช่นการอัปโหลดไฟล์ฟังก์ชั่นนี้ไม่เหมาะสำหรับการสาธิตที่ง่ายที่สุด ในเวลาเดียวกันพารามิเตอร์ RequestID จะถูกละเว้น หากมันเป็นมัลติเพล็กซ์ก็ไม่สามารถเพิกเฉยได้และการประมวลผลจะต้องซับซ้อนมากขึ้น
ถัดไประเบียนที่แตกต่างกันสามารถประมวลผลได้ตามประเภท คำจำกัดความของประเภทมีดังนี้:
การคัดลอกรหัสมีดังนี้:
#Define FCGI_BEGIN_REQUEST 1
#Define FCGI_ABORT_REQUEST 2
#define fcgi_end_request 3
#Define FCGI_PARAMS 4
#define fcgi_stdin 5
#define fcgi_stdout 6
#define fcgi_stderr 7
#define fcgi_data 8
#define fcgi_get_values 9
#define fcgi_get_values_result 10
#Define FCGI_UNKNOWN_TYPE 11
#Define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
ถัดไปคุณสามารถแยกวิเคราะห์ข้อมูลจริงตามประเภทที่บันทึกไว้ ฉันจะใช้ fcgi_params ที่ใช้กันมากที่สุด, fcgi_get_values และ fcgi_get_values_result เพื่อแสดงให้เห็น โชคดีที่วิธีการวิเคราะห์ของพวกเขาสอดคล้องกัน การแยกวิเคราะห์บันทึกประเภทอื่นมีกฎที่แตกต่างกันและคุณสามารถอ้างถึงคำจำกัดความของข้อกำหนดเพื่อนำไปใช้ ฉันจะไม่เข้าไปดูรายละเอียดที่นี่
FCGI_PARAMS, FCGI_GET_VALUES, FCGI_GET_VALUES_RESULT ล้วนเป็นข้อมูลประเภท "เข้ารหัสชื่อ" รูปแบบมาตรฐานคือ: ส่งในรูปแบบของความยาวชื่อตามด้วยความยาวของค่าตามด้วยชื่อตามด้วยค่าที่ 127 ไบต์หรือน้อยกว่าสามารถเข้ารหัสในหนึ่งไบต์ในขณะที่ความยาวที่ยาวกว่าจะถูกเข้ารหัสในสี่ไบต์เสมอ บิตสูงของความยาวไบต์แรกบ่งบอกถึงความยาวของความยาว บิตสูง 0 หมายถึงวิธีการเข้ารหัสไบต์และ 1 หมายถึงวิธีการเข้ารหัสแบบสี่ไบต์ ลองดูตัวอย่างที่ครอบคลุมเช่นกรณีของชื่อยาวและค่าสั้น:
การคัดลอกรหัสมีดังนี้:
typedef struct {
Char NamelengthB3 ที่ไม่ได้ลงนาม; / * namelengthb3 >> 7 == 1 */
Char NamelengthB2 ที่ไม่ได้ลงนาม;
Char NamelengthB1 ที่ไม่ได้ลงนาม;
Char Namelengthb0 ที่ไม่ได้ลงนาม;
Char Valuelengthb0 ที่ไม่ได้ลงนาม; / * valuelengthb0 >> 7 == 0 */
ถ่านที่ไม่ได้ลงชื่อ Namedata [Namelength
((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
Char Valuedata ที่ไม่ได้ลงชื่อ [Valuelength];
} FCGI_NAMEVALUEPAIR41;
ตัวอย่างการใช้งานที่สอดคล้องกัน JS ตัวอย่าง:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น parseparams (ร่างกาย) {
var j = 0
params = {}
ความยาว = body.length;
ในขณะที่ (j <ความยาว) {
ชื่อ var,
ค่า,
ความยาว
ความยาวคลื่น;
if (body [j] >> 7 == 1) {
namelength = ((body [j ++] & 0x7f) << 24)+(body [j ++] << 16)+(body [j ++] << 8)+body [j ++];
} อื่น {
namelength = body [j ++];
-
if (body [j] >> 7 == 1) {
valuelength = ((body [j ++] & 0x7f) << 24)+(body [j ++] << 16)+(body [j ++] << 8)+body [j ++];
} อื่น {
ความยาวคลื่น = body [j ++];
-
var ret = body.asciislice (j, j + namelength + valuelength);
name = ret.substring (0, namelength);
value = ret.substring (namelength);
params [ชื่อ] = ค่า;
j + = (namelength + valuelength);
-
ส่งคืน params;
-
สิ่งนี้ใช้วิธีง่ายๆในการรับพารามิเตอร์และตัวแปรสภาพแวดล้อมต่างๆ ปรับปรุงรหัสก่อนหน้าและแสดงให้เห็นว่าเราจะได้รับ IP ของไคลเอนต์อย่างไร:
การคัดลอกรหัสมีดังนี้:
sock.on ('data', function (data) {
getRCDS (ข้อมูล, ฟังก์ชั่น (RCDs) {
สำหรับ (var i = 0, l = rcds.length; i <l; i ++) {
var bodydata = rcds [i],
type = bodydata [0]
body = bodydata [1];
if (body && (type === types.fcgi_params || type === types.fcgi_get_values || type === types.fcgi_get_values_result)) {
var params = parseparams (ร่างกาย);
console.log (params.remote_addr);
-
-
-
-
จนถึงตอนนี้เราได้เข้าใจพื้นฐานของส่วนคำขอ FASTCGI และจากนั้นเราจะใช้ส่วนการตอบกลับและในที่สุดก็เสร็จสิ้นบริการตอบกลับที่เรียบง่าย
ส่วนตอบสนอง
ส่วนการตอบสนองนั้นค่อนข้างง่าย ในกรณีที่ง่ายที่สุดคุณจะต้องส่งสองระเบียนนั่นคือ FCGI_STDOUT และ FCGI_END_REQUEST
ฉันจะไม่อธิบายเนื้อหาเฉพาะของเอนทิตีเพียงดูที่รหัส:
การคัดลอกรหัสมีดังนี้:
var res = (function () {
var maxlength = math.pow (2, 16);
ฟังก์ชั่น buffer0 (len) {
ส่งคืนบัฟเฟอร์ใหม่ ((อาร์เรย์ใหม่ (LEN + 1)) เข้าร่วม ('/U0000'));
-
Function WritestDout (ข้อมูล) {
var rcdstdouthd = บัฟเฟอร์ใหม่ (8)
contentLength = data.length,
PaddingLength = 8 - ContentLength % 8;
rcdstdouthd [0] = 1;
rcdstdouthd [1] = types.fcgi_stdout;
rcdstdouthd [2] = 0;
rcdstdouthd [3] = 1;
RCDSTDOUTHD [4] = ContendLength >> 8;
RCDSTDOUTHD [5] = ContendLength;
rcdstdouthd [6] = paddingLength;
rcdstdouthd [7] = 0;
return buffer.concat ([rcdstdouthd, ข้อมูล, buffer0 (paddingLength)]);
-
ฟังก์ชั่น writehttphead () {
return writestDout (บัฟเฟอร์ใหม่ ("http/1.1 200 ok/r/ncontent-type: text/html; charset = utf-8/r/nconnection: close/r/n/r/n"));
-
ฟังก์ชั่น writehttpbody (bodystr) {
var bodybuffer = [],
body = บัฟเฟอร์ใหม่ (bodystr);
สำหรับ (var i = 0, l = body.length; i <l; i + = maxlength + 1) {
Bodybuffer.push (writestdout (body.slice (i, i + maxlength)));
-
return buffer.concat (Bodybuffer);
-
ฟังก์ชั่นเขียน () {
var rcdendhd = บัฟเฟอร์ใหม่ (8);
rcdendhd [0] = 1;
rcdendhd [1] = types.fcgi_end_request;
rcdendhd [2] = 0;
rcdendhd [3] = 1;
rcdendhd [4] = 0;
rcdendhd [5] = 8;
rcdendhd [6] = 0;
rcdendhd [7] = 0;
return buffer.concat ([rcdendhd, buffer0 (8)]);
-
ฟังก์ชั่นส่งคืน (ข้อมูล) {
return buffer.concat ([writehttphead (), writehttpbody (ข้อมูล), writeend ()]);
-
-
ในกรณีที่ง่ายที่สุดสิ่งนี้จะช่วยให้คุณสามารถส่งการตอบกลับเต็มรูปแบบ เปลี่ยนรหัสสุดท้ายของเรา:
การคัดลอกรหัสมีดังนี้:
ผู้เยี่ยมชม var = 0;
Server.on ('การเชื่อมต่อ', ฟังก์ชั่น (ถุงเท้า) {
ผู้เข้าชม ++;
sock.on ('data', function (data) {
-
var querys = querystring.parse (params.query_string);
var ret = res ('ยินดีต้อนรับ' + (querys.name || 'เพื่อนรัก') + '! คุณคือหมายเลข' + ผู้เยี่ยมชม + 'เอกสาร ~');
Sock.write (ret);
ret = null;
Sock.end ();
-
-
เปิดเบราว์เซอร์และเยี่ยมชม: http: // domain/? name = yekai และคุณสามารถเห็นบางอย่างเช่น "ยินดีต้อนรับ yekai! คุณเป็นผู้ใช้ที่ 7 ของเว็บไซต์นี้ ~"
ณ จุดนี้เราประสบความสำเร็จในการใช้บริการ FastCGI ที่ง่ายที่สุดโดยใช้ node.js หากจำเป็นต้องใช้เป็นบริการจริงเราจะต้องเปรียบเทียบข้อมูลจำเพาะโปรโตคอลเพื่อปรับปรุงตรรกะของเรา
การทดสอบเปรียบเทียบ
ในที่สุดคำถามที่เราต้องพิจารณาคือการแก้ปัญหานี้เป็นไปได้โดยเฉพาะหรือไม่? นักเรียนบางคนอาจเห็นปัญหาดังนั้นฉันจะใส่ผลการทดสอบความดันอย่างง่ายก่อน:
การคัดลอกรหัสมีดังนี้:
// วิธี fastcgi:
500 ลูกค้าทำงาน 10 วินาที
ความเร็ว = 27678 หน้า/นาที, 63277 ไบต์/วินาที
คำขอ: 3295 SUSCEED, 1318 ล้มเหลว
500 ลูกค้าทำงาน 20 วินาที
ความเร็ว = 22131 หน้า/นาที, 63359 ไบต์/วินาที
คำขอ: 6523 SUSCEED, 854 ล้มเหลว
// วิธีพร็อกซี:
500 ลูกค้าทำงาน 10 วินาที
ความเร็ว = 28752 หน้า/นาที, 73191 ไบต์/วินาที
คำขอ: 3724 SUSCEED, 1068 ล้มเหลว
500 ลูกค้าทำงาน 20 วินาที
ความเร็ว = 26508 หน้า/นาที, 66267 ไบต์/วินาที
คำขอ: 6716 SUSCEED, 2120 ล้มเหลว
// วิธีการบริการโดยตรง node.js:
500 ลูกค้าทำงาน 10 วินาที
ความเร็ว = 101154 หน้า/นาที, 264247 ไบต์/วินาที
คำขอ: 15729 SUSCEED, 1130 ล้มเหลว
500 ลูกค้าทำงาน 20 วินาที
ความเร็ว = 43791 หน้า/นาที, 115962 ไบต์/วินาที
คำขอ: 13898 SUSCEED, 699 ล้มเหลว
เหตุใดวิธีพร็อกซีจึงดีกว่าวิธี FastCGI? นั่นเป็นเพราะภายใต้โครงการพร็อกซีบริการแบ็กเอนด์ดำเนินการโดยตรงโดยโมดูล Node.js Native และโครงการ FastCGI นั้นถูกนำมาใช้โดยตัวเราเองโดยใช้ JavaScript อย่างไรก็ตามจะเห็นได้ว่าไม่มีช่องว่างขนาดใหญ่ในประสิทธิภาพระหว่างสองโซลูชัน (แน่นอนการเปรียบเทียบที่นี่เป็นเพียงสถานการณ์ที่ง่ายหากช่องว่างมีขนาดใหญ่ขึ้นในสถานการณ์ธุรกิจจริง) และหาก node.js สนับสนุนบริการ FastCGI
postscript
หากคุณสนใจที่จะเล่นต่อไปคุณสามารถตรวจสอบซอร์สโค้ดของตัวอย่างที่ฉันนำไปใช้ในบทความนี้ ฉันได้ศึกษาข้อกำหนดของโปรโตคอลในช่วงสองวันที่ผ่านมา แต่ก็ไม่ยาก
ในเวลาเดียวกันฉันจะกลับไปเล่นกับ UWSGI แต่เจ้าหน้าที่บอกว่า V8 พร้อมที่จะสนับสนุนโดยตรงแล้ว
ฉันมีเกมตื้นมาก หากมีข้อผิดพลาดใด ๆ โปรดแก้ไขฉันและสื่อสาร