Node.js + Nginx - เกิดอะไรขึ้นตอนนี้


1003

ฉันตั้งค่า Node.js และ Nginx บนเซิร์ฟเวอร์ของฉันแล้ว ตอนนี้ฉันต้องการใช้ แต่ก่อนที่ฉันจะเริ่มมีคำถาม 2 ข้อ:

  1. พวกเขาควรทำงานร่วมกันอย่างไร ฉันจะจัดการคำขอได้อย่างไร
  2. มี 2 ​​แนวคิดสำหรับเซิร์ฟเวอร์ Node.js ซึ่งเป็นแนวคิดที่ดีกว่า:

    สร้างเซิร์ฟเวอร์ HTTP แยกสำหรับแต่ละเว็บไซต์ที่ต้องการ จากนั้นโหลดโค้ด JavaScript ทั้งหมดเมื่อเริ่มต้นโปรแกรมดังนั้นโค้ดจะถูกตีความหนึ่งครั้ง

    ข สร้างเซิร์ฟเวอร์ Node.js หนึ่งเซิร์ฟเวอร์ซึ่งจัดการคำขอ Node.js ทั้งหมด สิ่งนี้จะอ่านไฟล์ที่ร้องขอและประเมินเนื้อหาของไฟล์นั้น ดังนั้นไฟล์จะถูกตีความในแต่ละคำขอ แต่ตรรกะของเซิร์ฟเวอร์นั้นง่ายกว่ามาก

มันไม่ชัดเจนสำหรับฉันเกี่ยวกับวิธีการใช้ Node.js อย่างถูกต้อง

คำตอบ:


1306

Nginx ทำงานเป็นเซิร์ฟเวอร์ส่วนหน้าซึ่งในกรณีนี้จะทำการร้องขอไปยังเซิร์ฟเวอร์ node.js ดังนั้นคุณต้องตั้งค่าไฟล์กำหนดค่า nginx สำหรับโหนด

นี่คือสิ่งที่ฉันทำในกล่อง Ubuntu ของฉัน:

สร้างไฟล์yourdomain.comที่/etc/nginx/sites-available/:

vim /etc/nginx/sites-available/yourdomain.com

ในนั้นคุณควรจะมีสิ่งที่ชอบ:

# the IP(s) on which your node server is running. I chose port 3000.
upstream app_yourdomain {
    server 127.0.0.1:3000;
    keepalive 8;
}

# the nginx server instance
server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com www.yourdomain.com;
    access_log /var/log/nginx/yourdomain.com.log;

    # pass the request to the node.js server with the correct headers
    # and much more can be added, see nginx config options
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;

      proxy_pass http://app_yourdomain/;
      proxy_redirect off;
    }
 }

หากคุณต้องการให้ nginx (> = 1.3.13) จัดการคำขอ websocket ด้วยให้เพิ่มบรรทัดต่อไปนี้ในlocation /ส่วน:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

เมื่อคุณมีการตั้งค่านี้คุณต้องเปิดใช้งานไซต์ที่กำหนดไว้ในไฟล์กำหนดค่าด้านบน:

cd /etc/nginx/sites-enabled/ 
ln -s /etc/nginx/sites-available/yourdomain.com yourdomain.com

สร้างแอปโหนดเซิร์ฟเวอร์ของคุณที่/var/www/yourdomain/app.jsและเรียกใช้ที่localhost:3000

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(3000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');

ทดสอบข้อผิดพลาดทางไวยากรณ์:

nginx -t

รีสตาร์ท nginx:

sudo /etc/init.d/nginx restart

เริ่มต้นโหนดเซิร์ฟเวอร์ครั้งสุดท้าย:

cd /var/www/yourdomain/ && node app.js

ตอนนี้คุณควรเห็น "Hello World" ที่ yourdomain.com

หมายเหตุสุดท้ายหนึ่งเกี่ยวกับการเริ่มต้นโหนดเซิร์ฟเวอร์: คุณควรใช้ระบบการตรวจสอบบางอย่างสำหรับ node daemon มีความน่ากลัวคือการสอนเกี่ยวกับโหนดพุ่งพรวดและ monit


11
ขอบคุณสำหรับการโพสต์ nginx cache node.js จะตอบสนองต่อเซิร์ฟเวอร์ดังกล่าวข้างต้นหรือเรียกใช้ซ้ำในแต่ละครั้ง
Lime

79
มีเหตุผลใดที่คุณไม่สามารถทำได้location / { proxy_pass http://127.0.0.1:3000; }? ทำไมคุณต้องupstreamบิตการตั้งค่าทั้งหมด?
Robin Winslow

20
+1, คำตอบที่ตรงไปตรงมาและเรียบง่ายสำหรับคำถามทั่วไป; เหมาะสำหรับผู้ที่ต้องการตั้งค่าโฮสต์เสมือนโดยใช้โหนดและ nginx สิ่งเดียวที่ฉันคิดว่าคุณพลาดคือคำตอบเชิงคุณภาพว่าทำไม nginx-in-front-of-node ดีที่สุดสำหรับการให้บริการหลายโฮสต์ (คำถามที่สองของผู้ถาม)
Paul d'Aoust

34
@Robin Winslow ในกรณีที่คุณต้องการเพิ่มเซิร์ฟเวอร์เพิ่มเติมสำหรับเซิร์ฟเวอร์สำหรับการทำ load balance
Joao Da Silva

76
มันควรจะตั้งข้อสังเกตว่านี้ (ที่เป็นประโยชน์มาก) คำตอบที่หมายถึงหนึ่งรสชาติของ Nginx ว่าโดยค่าเริ่มต้นมาพร้อมกับsites-enabledและไดเรกทอรีภายในsites-available /etc/nginxหากเวอร์ชันของคุณมาโดยไม่มีสองไดเรกทอรีอาจเป็นไปได้ว่ามีconf.dไดเรกทอรีเดียวแทน ในกรณีที่ทำตามคำแนะนำเหล่านี้จะไม่มีผลจนกว่าคุณจะแก้ไขincludeคำสั่งภายในแฟ้มnginx.confให้ชี้ไปที่แทนการเริ่มต้นsites-enabled conf.dหวังว่ามันสมเหตุสมผล มันควรจะเป็นตัวอธิบายเมื่อคุณเห็นกล่าวว่าคำสั่งภายในinclude nginx.conf
meetamit

167

คุณยังสามารถตั้งค่าหลายโดเมนด้วย nginx ส่งต่อไปยังกระบวนการหลายโหนด

ตัวอย่างเช่นเพื่อให้บรรลุเหล่านี้:

  • domain1.com -> ถึง Node.js กระบวนการทำงานในท้องถิ่นhttp://127.0.0.1:4000
  • domain2.com -> ถึง Node.js กระบวนการทำงานในท้องถิ่นhttp://127.0.0.1,5000

ควรใช้พอร์ตเหล่านี้ (4000 และ 5,000) เพื่อรับฟังคำขอแอพในรหัสแอปของคุณ

/ etc / Nginx / เว็บไซต์ที่เปิดใช้งาน / domain1

server {
    listen 80;
    listen [::]:80;
    server_name domain1.com;
    access_log /var/log/nginx/domain1.access.log;
    location / {
        proxy_pass    http://127.0.0.1:4000/;
    }
}

ใน / etc / nginx / sites-enabled / domain2

server {
    listen 80;
    listen [::]:80;
    server_name domain2.com;
    access_log /var/log/nginx/domain2.access.log;
    location / {
        proxy_pass    http://127.0.0.1:5000/;
    }
}

5
ผมใช้วิธีการของคุณ proxy_pass แต่ด้วยเหตุผลบางอย่างhttp://example.comได้รับโดยอัตโนมัติ302'd http://www.example.comเพื่อ ทำไมถึงเป็นอย่างนั้น?
Kristian

คุณมี Cloudflare หรืออะไรที่คล้ายกัน? การกำหนดค่าข้างต้นไม่ควรเปลี่ยนเส้นทางเลย
ozzieisaacs

1
@Kristian คุณจะต้องเพิ่มproxy_set_header Host $hostเพื่อหลีกเลี่ยงการเปลี่ยนเส้นทาง HTTP 302
Ivan Shatsky

@IvanShatsky - คุณสามารถให้ความช่วยเหลือวิธีการกำหนดค่าหลายพอร์ตด้วยหลายโดเมนย่อยและป้องกันพอร์ตอื่น ๆ ที่ทำงานในโดเมนอื่นได้หรือไม่ nginx v 1.14.1
151291

59

คุณสามารถมี URL ที่แตกต่างกันสำหรับแอพในการกำหนดค่าเซิร์ฟเวอร์เดียว:

  • yourdomain.com/app1/* -> ไปยัง Node.js กระบวนการทำงานในท้องถิ่น http://127.0.0.1:3000
  • yourdomain.com/app2/* -> ถึงกระบวนการ Node.js ที่ทำงานในท้องถิ่นhttp://127.0.0.1:4000

ใน/ etc / nginx / sites-enabled / yourdomain :

server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com;

    location ^~ /app1/{
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass    http://127.0.0.1:3000/;
    }

    location ^~ /app2/{
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass    http://127.0.0.1:4000/;
    }
}

รีสตาร์ท nginx:

sudo service nginx restart

เริ่มต้นแอปพลิเคชัน

โหนด app1.js

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello from app1!\n');
}).listen(3000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');

โหนด app2.js

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello from app2!\n');
}).listen(4000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:4000/');

3
เวอร์ชันชุมชนโอเพนซอร์สนั้นฟรี แต่มีเวอร์ชั่นพร้อมคุณสมบัติอื่น ๆ ซึ่งไม่ฟรี nginx.com/products/feature-matrix
0x8BADF00D

ขอโทษด้วยที่ฉันไม่รู้ จุดประสงค์ประโยชน์ของการให้บริการในลักษณะนี้คืออะไร? คุณมีตัวอย่างหรือกรณีการใช้งานหรือไม่? ขอบคุณล่วงหน้า.
Mauro Aguilar

2
@MauroAguilar หากคุณต้องการแอป 2 node.js บนเซิร์ฟเวอร์เดียวคุณสามารถให้บริการได้โดยใช้วิธีที่แนะนำ (ใช้พอร์ตต่าง ๆ ) ในกรณีของฉันมันเป็นแอพทดสอบสองแบบที่ต่างกัน
0x8BADF00D

ตกลง แต่อะไรคือความแตกต่างระหว่างการรัน 2 แอพกับแอพเดียว? ฉันหมายความว่าอะไรจะเป็นประโยชน์หากพวกเขามีจุดประสงค์เพื่อจุดประสงค์เดียวกัน?
Mauro Aguilar

2
@MauroAguilar คุณสามารถเรียกใช้พวกเขาในหนึ่งเดียวและไม่มีประโยชน์ถ้ามันอาจเป็นส่วนหนึ่งของโครงการเดียวและมีวัตถุประสงค์เดียวกัน แต่ถ้าคุณต้องการรัน 2 โปรเจ็กต์ที่แตกต่างกันโดยมีวัตถุประสงค์ที่แตกต่างกันและด้วยการกำหนดค่าที่แตกต่างกันบนเซิร์ฟเวอร์เดียวคุณจะได้รับประโยชน์จากการใช้การกำหนดค่านี้
0x8BADF00D

35

ฉันพร็อกซีแอพพลิเคชัน Node Express ที่เป็นอิสระผ่าน Nginx

ดังนั้นแอปพลิเคชั่นใหม่สามารถติดตั้งได้อย่างง่ายดายและฉันยังสามารถเรียกใช้สิ่งอื่น ๆ บนเซิร์ฟเวอร์เดียวกันในตำแหน่งที่ตั้งอื่น

นี่คือรายละเอียดเพิ่มเติมเกี่ยวกับการตั้งค่าของฉันด้วยตัวอย่างการกำหนดค่า Nginx:

ปรับใช้หลายแอปพลิเคชันโหนดบนเว็บเซิร์ฟเวอร์เดียวในโฟลเดอร์ย่อยด้วย Nginx

สิ่งต่าง ๆ มีความยุ่งยากกับ Node เมื่อคุณต้องการย้ายแอปพลิเคชันของคุณจาก localhost ไปยังอินเทอร์เน็ต

ไม่มีวิธีการทั่วไปสำหรับการปรับใช้โหนด

Google สามารถค้นหาบทความจำนวนมากในหัวข้อนี้ แต่ฉันพยายามหาวิธีแก้ไขปัญหาที่เหมาะสมสำหรับการตั้งค่าที่ฉันต้องการ

โดยทั่วไปฉันมีเว็บเซิร์ฟเวอร์และฉันต้องการให้ติดตั้งแอปพลิเคชัน Node ไปยังโฟลเดอร์ย่อย (เช่นhttp: // myhost / demo / pet-project / ) โดยไม่ต้องแนะนำการพึ่งพาการกำหนดค่าใด ๆ กับรหัสแอปพลิเคชัน

ในเวลาเดียวกันฉันต้องการให้สิ่งอื่น ๆ เช่นบล็อกทำงานบนเว็บเซิร์ฟเวอร์เดียวกัน

ฟังดูง่ายเหรอ? ชัดเจนว่าไม่.

ในหลายตัวอย่างบนเว็บแอ็พพลิเคชันโหนดจะรันบนพอร์ต 80 หรือพร็อกซีโดย Nginx ไปยังรูท

แม้ว่าวิธีการทั้งสองจะใช้ได้ในบางกรณี แต่ก็ไม่ตรงตามเกณฑ์ที่เรียบง่ายของฉัน

นั่นคือเหตุผลที่ฉันสร้างการกำหนดค่า Nginx ของตัวเองและนี่คือสารสกัด:

upstream pet_project {
  server localhost:3000;
}

server {
  listen 80;
  listen [::]:80;
  server_name frontend;

  location /demo/pet-project {
    alias /opt/demo/pet-project/public/;
    try_files $uri $uri/ @pet-project;
  }

  location @pet-project {
    rewrite /demo/pet-project(.*) $1 break;

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $proxy_host;
    proxy_set_header X-NginX-Proxy true;

    proxy_pass http://pet_project;
    proxy_redirect http://pet_project/ /demo/pet-project/;
  }
}

จากตัวอย่างนี้คุณสามารถสังเกตเห็นว่าผมติดแอพลิเคชันโครงการสัตว์เลี้ยงโหนดของฉันทำงานบนพอร์ต 3000 http: // MyHost / สาธิต / สัตว์เลี้ยงโครงการ

Nginx แรกตรวจสอบว่าทรัพยากรที่ร้องขอเป็นไฟล์สแตติกพร้อมใช้งานที่/ opt / demo / pet-project / public /และถ้าเป็นเช่นนั้นมันให้บริการตามที่มีประสิทธิภาพสูงหรือไม่ดังนั้นเราไม่จำเป็นต้องมีเลเยอร์ซ้ำซ้อนเช่น Connect มิดเดิลแวร์แบบคงที่

จากนั้นคำขออื่น ๆ ทั้งหมดจะถูกเขียนทับและพร็อกซีกับแอปพลิเคชันPet Project Nodeดังนั้นแอปพลิเคชัน Node จึงไม่จำเป็นต้องทราบว่าติดตั้งจริงที่ไหนและสามารถย้ายไปที่ใดก็ได้โดยการกำหนดค่า

proxy_redirectเป็นสิ่งที่ต้องจัดการส่วนหัว Location อย่างถูกต้อง สิ่งนี้มีความสำคัญอย่างยิ่งหากคุณใช้res.redirect ()ในแอปพลิเคชันโหนดของคุณ

คุณสามารถทำซ้ำการตั้งค่านี้ได้อย่างง่ายดายสำหรับแอปพลิเคชั่น Node หลายตัวที่ทำงานบนพอร์ตที่ต่างกันและเพิ่มตัวจัดการตำแหน่งเพิ่มเติมเพื่อวัตถุประสงค์อื่น

จาก: http://skovalyov.blogspot.dk/2012/07/deploy-multiple-node-applications-on.html


1
ทำไมและวิธีการที่คุณควรทำในโดเมนย่อยแทน: skovalyov.blogspot.dk/2012/10/…
skovalyov

ลิงก์คำตอบเท่านั้น ... คุณช่วยสรุปส่วนที่เกี่ยวข้องในคำตอบของคุณได้ไหมถ้าบล็อกของคุณหายไป?
ไกเซอร์

11

Node.js พร้อมการกำหนดค่า Nginx

$ sudo nano /etc/nginx/sites-available/subdomain.your_domain.com

เพิ่มการกำหนดค่าต่อไปนี้เพื่อให้ Nginx ทำหน้าที่เป็นพร็อกซีเปลี่ยนเส้นทางไปยังพอร์ต 3000 ปริมาณการใช้งานจากเซิร์ฟเวอร์เมื่อเรามาจาก“ subdomain.your_domain.com”

upstream subdomain.your_domain.com {
  server 127.0.0.1:3000;
}
server {
  listen 80;
  listen [::]:80;
  server_name subdomain.your_domain.com;
  access_log /var/log/nginx/subdomain.your_domain.access.log;
  error_log /var/log/nginx/subdomain.your_domain.error.log debug;
  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://subdomain.your_domain.com;
    proxy_redirect off;
  }
}

9

ตอบคำถามของคุณ 2:

ฉันจะใช้ตัวเลือกbเพียงเพราะมันใช้ทรัพยากรน้อยกว่ามาก ด้วยตัวเลือก 'a' ไคลเอนต์ทุกตัวจะทำให้เซิร์ฟเวอร์ใช้หน่วยความจำจำนวนมากโหลดไฟล์ทั้งหมดที่คุณต้องการ (แม้ว่าฉันจะชอบ php นี่เป็นหนึ่งในปัญหาที่เกิดขึ้นกับมัน) ด้วยตัวเลือก 'b' คุณสามารถโหลดไลบรารีของคุณ (รหัสที่ใช้ซ้ำได้) และแบ่งปันให้กับคำขอของลูกค้าทั้งหมด

แต่เป็นเครื่องที่ถ้าคุณมีหลายแกนคุณควรปรับแต่ง node.js เพื่อใช้ทั้งหมด


2
ทำตามคำแนะนำนี้หากทรัพยากรเป็นปัญหาที่สำคัญที่สุดของคุณ (ไม่น่าเป็นไปได้) มีการประนีประนอมที่แตกต่างกันระหว่าง (a) และ (b) ตัวเลือก (a) น่าจะดีกว่าถ้าคุณต้องการให้เว็บไซต์มีความเป็นอิสระมากขึ้นเช่นการรีสตาร์ทไซต์หรือการบำรุงรักษาการเชื่อมต่อฐานข้อมูลรหัสฐานอ้างอิงไลบรารีการย้ายเว็บไซต์ระหว่างเซิร์ฟเวอร์ ฯลฯ
robocat

8

ฉันสร้างที่เก็บใน Github ซึ่งคุณสามารถโคลน, คนจรจัด-node-nginx-boilerplate

โดยทั่วไปแล้วแอป node.js ที่/var/www/nodeappเป็น

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(4570, '127.0.0.1');

console.log('Node Server running at 127.0.0.1:4570/');

และการกำหนดค่า nginx ที่/etc/nginx/sites-available/เป็น

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/nodeapp;
        index index.html index.htm;

        server_name localhost;

        location / {
          proxy_pass http://127.0.0.1:4570;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
        }
}

5

คุณยังสามารถใช้ node.js เพื่อสร้างไฟล์สแตติกในไดเรกทอรีที่ให้บริการโดย nginx แน่นอนบางส่วนแบบไดนามิกของเว็บไซต์ของคุณสามารถให้บริการโดยโหนดและบางส่วนโดย nginx (คงที่)

การให้บริการบางอย่างโดย nginx จะช่วยเพิ่มประสิทธิภาพของคุณ ..


5

เราสามารถติดตั้งแอพ Nodejs ได้อย่างง่ายดายโดย Nginx ซึ่งทำหน้าที่เป็น reverse proxy
การกำหนดค่าต่อไปนี้จะถือว่าแอปพลิเคชัน NodeJS ทำงานบน 127.0.0.1:8080

  server{
     server_name domain.com sub.domain.com; # multiple domains

     location /{ 
      proxy_pass http://127.0.0.1:8080;  
      proxy_set_header Host $host;
      proxy_pass_request_headers on;  
     }

     location /static/{
       alias /absolute/path/to/static/files; # nginx will handle js/css
     }
   } 

ในการตั้งค่าข้างต้นแอพ Nodejs ของคุณจะ

  • รับHTTP_HOSTส่วนหัวที่คุณสามารถใช้ตรรกะเฉพาะโดเมนเพื่อตอบสนอง '
  • แอปพลิเคชันของคุณต้องได้รับการจัดการโดยผู้จัดการกระบวนการเช่นPM2หรือหัวหน้างานเพื่อจัดการสถานการณ์ / นำซ็อกเก็ตหรือทรัพยากรมาใช้ซ้ำเป็นต้น

  • ตั้งค่าบริการรายงานข้อผิดพลาดเพื่อรับข้อผิดพลาดการผลิตเช่นยามหรือrollbar

หมายเหตุ: คุณสามารถตั้งค่าลอจิกสำหรับการส่งคำขอเส้นทางเฉพาะโดเมนสร้างมิดเดิลแวร์สำหรับแอปพลิเคชัน expressjs


1
อีกเหตุผลในการใช้ pm2 คือเพื่อให้คุณสามารถเรียกใช้แอปของคุณ 'ถาวร' หลังจากออกจากเชลล์และเริ่มต้นโดยอัตโนมัติหากคุณต้องการรีบูตเซิร์ฟเวอร์ของคุณดูที่: pm2.keymetrics.io/docs/usage/startup
SeanQuinn781

3

Nginx สามารถทำหน้าที่เป็นพร็อกซีเซิร์ฟเวอร์ย้อนกลับซึ่งทำงานได้เหมือนผู้จัดการโครงการ เมื่อได้รับคำขอก็จะทำการวิเคราะห์และส่งต่อคำขอไปยัง upstream (สมาชิกโครงการ) หรือจัดการเอง Nginx มีสองวิธีในการจัดการคำขอตามวิธีการกำหนดค่า

  • ให้บริการตามคำขอ
  • ส่งต่อคำขอไปยังเซิร์ฟเวอร์อื่น

    server{
     server_name mydomain.com sub.mydomain.com;
    
     location /{ 
      proxy_pass http://127.0.0.1:8000;  
      proxy_set_header Host $host;
      proxy_pass_request_headers on;  
     }
    
     location /static/{
       alias /my/static/files/path;
     }

    }

เซิร์ฟเวอร์ตามคำขอ

ด้วยการกำหนดค่านี้เมื่อมีการร้องขอ URL ก็ mydomain.com/static/myjs.jsจะส่งคืนmyjs.jsไฟล์ใน /my/static/files/pathโฟลเดอร์ เมื่อคุณกำหนดค่า nginx ให้บริการไฟล์สแตติกมันจะจัดการกับคำร้องขอเอง

ส่งต่อคำขอไปยังเซิร์ฟเวอร์อื่น

เมื่อ URL ขอเป็น mydomain.com/dothisNginx จะส่งต่อการร้องขอไปยัง http://127.0.0.1:8000 บริการที่ทำงานบนพอร์ต localhost 8000 จะได้รับการร้องขอและส่งคืนการตอบกลับไปยัง nginx และ nginx จะส่งคืนการตอบกลับไปยังไคลเอ็นต์

เมื่อคุณรันเซิร์ฟเวอร์ node.js บนพอร์ต 8000 nginx จะส่งต่อการร้องขอไปยัง node.js เขียน node.js ลอจิกและจัดการการร้องขอ นั่นคือคุณมีเซิร์ฟเวอร์ nodejs ของคุณทำงานอยู่หลังเซิร์ฟเวอร์ nginx

หากคุณต้องการรันเซอร์วิสอื่นนอกเหนือจาก nodejs ให้รันเซอร์วิสอื่นเช่น Django, flask, php บนพอร์ตที่ต่างกันและตั้งค่าใน nginx


1

คุณสามารถรัน nodejs โดยใช้ pm2 หากคุณต้องการจัดการ microservice แต่ละวิธีและรัน โหนดจะทำงานในพอร์ตที่ถูกต้องเพียงกำหนดค่าพอร์ตนั้นใน nginx (/etc/nginx/sites-enabled/domain.com)

server{
    listen 80;
    server_name domain.com www.domain.com;

  location / {
     return 403;
  }
    location /url {
        proxy_pass http://localhost:51967/info;
    }
}

ตรวจสอบว่า localhost กำลังทำงานอยู่หรือไม่โดยใช้ ping

และ

Create one single Node.js server which handles all Node.js requests. This reads the requested files and evals their contents. So the files are interpreted on each request, but the server logic is much simpler.

สิ่งนี้ดีที่สุดและตามที่คุณพูดง่ายขึ้นเช่นกัน


1

การตั้งค่าที่ดีและง่ายที่สุดด้วย Nginx และ Nodejs คือการใช้ Nginx เป็น HTTP และ TCP load balancer ที่เปิดใช้งาน proxy_protocol ในบริบทนี้ Nginx จะสามารถร้องขอการรับขาเข้ากับ nodejs และยกเลิกการเชื่อมต่อ SSL กับเซิร์ฟเวอร์ Nginx แบ็กเอนด์และไม่ไปที่พร็อกซีเซิร์ฟเวอร์เอง (SSL-PassThrough)

ในความคิดของฉันไม่มีจุดในการให้ตัวอย่างที่ไม่ใช่ SSL เนื่องจากเว็บแอปทั้งหมด (หรือควร) โดยใช้สภาพแวดล้อมที่ปลอดภัย

ตัวอย่าง config สำหรับพร็อกซีเซิร์ฟเวอร์ใน/etc/nginx/nginx.conf

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
  upstream webserver-http {
    server 192.168.1.4; #use a host port instead if using docker
    server 192.168.1.5; #use a host port instead if using docker
  }
  upstream nodejs-http {
    server 192.168.1.4:8080; #nodejs listening port
    server 192.168.1.5:8080; #nodejs listening port
  }
  server {
    server_name example.com;
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $server_name;
      proxy_set_header Connection "";
      add_header       X-Upstream $upstream_addr;
      proxy_redirect     off;
      proxy_connect_timeout  300;
      proxy_http_version 1.1;
      proxy_buffers 16 16k;
      proxy_buffer_size 16k;
      proxy_cache_background_update on;
      proxy_pass http://webserver-http$request_uri;
    }
  }
  server {
    server_name node.example.com;
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $server_name;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      add_header       X-Upstream $upstream_addr;
      proxy_redirect     off;
      proxy_connect_timeout  300;
      proxy_http_version 1.1;
      proxy_buffers 16 16k;
      proxy_buffer_size 16k;
      proxy_cache_background_update on;
      proxy_pass http://nodejs-http$request_uri;
    }
  }
}
stream {
  upstream webserver-https {
    server 192.168.1.4:443; #use a host port instead if using docker
    server 192.168.1.5:443; #use a host port instead if using docker
  }

  server {
    proxy_protocol on;
    tcp_nodelay on;
    listen 443;
    proxy_pass webserver-https;
  }
  log_format proxy 'Protocol: $protocol - $status $bytes_sent $bytes_received $session_time';
  access_log  /var/log/nginx/access.log proxy;
  error_log /var/log/nginx/error.log debug;
}

ตอนนี้มาจัดการกับเว็บเซิร์ฟเวอร์แบ็กเอนด์ /etc/nginx/nginx.conf :

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
load_module /etc/nginx/modules/ngx_http_geoip2_module.so; # GeoIP2
events {
    worker_connections  1024;
}
http {
    variables_hash_bucket_size 64;
    variables_hash_max_size 2048;
    server_tokens off;
    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;
    autoindex off;
    keepalive_timeout  30;
    types_hash_bucket_size 256;
    client_max_body_size 100m;
    server_names_hash_bucket_size 256;
    include         mime.types;
    default_type    application/octet-stream;
    index  index.php index.html index.htm;
    # GeoIP2
    log_format  main    'Proxy Protocol Address: [$proxy_protocol_addr] '
                        '"$request" $remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';

    # GeoIP2
    log_format  main_geo    'Original Client Address: [$realip_remote_addr]- Proxy Protocol Address: [$proxy_protocol_addr] '
                            'Proxy Protocol Server Address:$proxy_protocol_server_addr - '
                            '"$request" $remote_addr - $remote_user [$time_local] "$request" '
                            '$status $body_bytes_sent "$http_referer" '
                            '$geoip2_data_country_iso $geoip2_data_country_name';

    access_log  /var/log/nginx/access.log  main_geo; # GeoIP2
#===================== GEOIP2 =====================#
    geoip2 /usr/share/geoip/GeoLite2-Country.mmdb {
        $geoip2_metadata_country_build  metadata build_epoch;
        $geoip2_data_country_geonameid  country geoname_id;
        $geoip2_data_country_iso        country iso_code;
        $geoip2_data_country_name       country names en;
        $geoip2_data_country_is_eu      country is_in_european_union;
    }
    #geoip2 /usr/share/geoip/GeoLite2-City.mmdb {
    #   $geoip2_data_city_name city names en;
    #   $geoip2_data_city_geonameid city geoname_id;
    #   $geoip2_data_continent_code continent code;
    #   $geoip2_data_continent_geonameid continent geoname_id;
    #   $geoip2_data_continent_name continent names en;
    #   $geoip2_data_location_accuracyradius location accuracy_radius;
    #   $geoip2_data_location_latitude location latitude;
    #   $geoip2_data_location_longitude location longitude;
    #   $geoip2_data_location_metrocode location metro_code;
    #   $geoip2_data_location_timezone location time_zone;
    #   $geoip2_data_postal_code postal code;
    #   $geoip2_data_rcountry_geonameid registered_country geoname_id;
    #   $geoip2_data_rcountry_iso registered_country iso_code;
    #   $geoip2_data_rcountry_name registered_country names en;
    #   $geoip2_data_rcountry_is_eu registered_country is_in_european_union;
    #   $geoip2_data_region_geonameid subdivisions 0 geoname_id;
    #   $geoip2_data_region_iso subdivisions 0 iso_code;
    #   $geoip2_data_region_name subdivisions 0 names en;
   #}

#=================Basic Compression=================#
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/css text/xml text/plain application/javascript image/jpeg image/png image/gif image/x-icon image/svg+xml image/webp application/font-woff application/json application/vnd.ms-fontobject application/vnd.ms-powerpoint;
    gzip_static on;

    include /etc/nginx/sites-enabled/example.com-https.conf;
}

ตอนนี้ขอกำหนดค่าโฮสต์เสมือนด้วย SSL นี้และ proxy_protocol เปิดการใช้งานปรับแต่งที่/etc/nginx/sites-available/example.com-https.conf :

server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name 192.168.1.4; #Your current server ip address. It will redirect to the domain name.
    listen 80;
    listen 443 ssl http2;
    listen [::]:80;
    listen [::]:443 ssl http2;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    return 301 https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name  example.com;
    listen       *:80;
    return 301   https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name www.example.com;
    listen 80;
    listen 443 http2;
    listen [::]:80;
    listen [::]:443 ssl http2 ;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    return 301 https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name example.com;
    listen 443 proxy_protocol ssl http2;
    listen [::]:443 proxy_protocol ssl http2;
    root /var/www/html;
    charset UTF-8;
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy no-referrer;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;
    keepalive_timeout   70;
    ssl_buffer_size 1400;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=86400;
    resolver_timeout 10;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_trusted_certificate /etc/nginx/certs/example.com.crt;
location ~* \.(jpg|jpe?g|gif|png|ico|cur|gz|svgz|mp4|ogg|ogv|webm|htc|css|js|otf|eot|svg|ttf|woff|woff2)(\?ver=[0-9.]+)?$ {
    expires modified 1M;
    add_header Access-Control-Allow-Origin '*';
    add_header Pragma public;
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    access_log off;
    }
    location ~ /.well-known { #For issuing LetsEncrypt Certificates
        allow all;
    }
location / {
    index index.php;
    try_files $uri $uri/ /index.php?$args;
    }
error_page  404    /404.php;

location ~ \.php$ {
    try_files       $uri =404;
    fastcgi_index   index.php;
    fastcgi_pass    unix:/tmp/php7-fpm.sock;
    #fastcgi_pass    php-container-hostname:9000; (if using docker)
    fastcgi_pass_request_headers on;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_intercept_errors on;
    fastcgi_ignore_client_abort off;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_request_buffering on;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    include fastcgi_params;
}
location = /robots.txt {
    access_log off;
    log_not_found off;
    }
location ~ /\. {
    deny  all;
    access_log off;
    log_not_found off;
    }
}

และสุดท้ายตัวอย่างของเว็บเซิร์ฟเวอร์ 2 nodejs : เซิร์ฟเวอร์แรก:

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello From Nodejs\n');
}).listen(8080, "192.168.1.4");
console.log('Server running at http://192.168.1.4:8080/');

เซิร์ฟเวอร์ตัวที่สอง:

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello From Nodejs\n');
}).listen(8080, "192.168.1.5");
console.log('Server running at http://192.168.1.5:8080/');

ตอนนี้ทุกอย่างควรจะทำงานอย่างสมบูรณ์และสมดุล

ในขณะที่กลับผมเขียนเกี่ยวกับวิธีการตั้งค่า Nginx เป็น balancer โหลด TCP ในหาง ตรวจสอบว่าคุณใช้ Docker หรือไม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.