Node.js + Nginx - Bây giờ thì sao?


1003

Tôi đã thiết lập Node.js và Nginx trên máy chủ của mình. Bây giờ tôi muốn sử dụng nó, nhưng, trước khi tôi bắt đầu có 2 câu hỏi:

  1. Họ nên làm việc với nhau như thế nào? Tôi nên xử lý các yêu cầu như thế nào?
  2. Có 2 khái niệm cho máy chủ Node.js, cái nào tốt hơn:

    a. Tạo một máy chủ HTTP riêng cho mỗi trang web cần nó. Sau đó tải tất cả mã JavaScript khi bắt đầu chương trình, do đó mã được diễn giải một lần.

    b. Tạo một máy chủ Node.js duy nhất xử lý tất cả các yêu cầu Node.js. Điều này đọc các tập tin được yêu cầu và tránh nội dung của chúng. Vì vậy, các tệp được giải thích theo từng yêu cầu, nhưng logic máy chủ đơn giản hơn nhiều.

Tôi không rõ cách sử dụng Node.js một cách chính xác.

Câu trả lời:


1306

Nginx hoạt động như một máy chủ ngoại vi, trong trường hợp này sẽ ủy quyền các yêu cầu đến máy chủ node.js. Do đó, bạn cần thiết lập một tập tin cấu hình nginx cho nút.

Đây là những gì tôi đã làm trong hộp Ubuntu của mình:

Tạo tệp yourdomain.comtại /etc/nginx/sites-available/:

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

Trong đó bạn nên có một cái gì đó như:

# 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;
    }
 }

Nếu bạn muốn nginx (> = 1.3.13) cũng xử lý các yêu cầu websocket, hãy thêm các dòng sau vào location /phần:

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

Khi bạn có thiết lập này, bạn phải kích hoạt trang được xác định trong tệp cấu hình ở trên:

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

Tạo ứng dụng máy chủ nút của bạn tại /var/www/yourdomain/app.jsvà chạy nó tạilocalhost: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/');

Kiểm tra lỗi cú pháp:

nginx -t

Khởi động lại nginx:

sudo /etc/init.d/nginx restart

Cuối cùng khởi động máy chủ nút:

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

Bây giờ bạn sẽ thấy "Hello World" tại yourdomain.com

Một lưu ý cuối cùng liên quan đến việc khởi động máy chủ nút: bạn nên sử dụng một số loại hệ thống giám sát cho trình nền nút. Có một hướng dẫn tuyệt vời về nút với upstart và monit .


11
Cảm ơn bài đăng, sẽ nginx lưu trữ các phản hồi node.js cho máy chủ ở trên hoặc chạy lại chúng mỗi lần.
Vôi

79
Có bất kỳ lý do tại sao bạn không thể làm location / { proxy_pass http://127.0.0.1:3000; }? Tại sao bạn cần toàn bộ upstreambit cấu hình?
Robin Winslow

20
+1, Câu trả lời rất đơn giản và đơn giản cho một câu hỏi phổ biến; tuyệt vời cho những người muốn thiết lập máy chủ ảo bằng nút và nginx. Điều duy nhất tôi nghĩ bạn đã bỏ lỡ là một câu trả lời định tính về lý do tại sao nginx-in-front-of-node là tốt nhất để phục vụ nhiều vhost (câu hỏi thứ hai của người hỏi).
Paulizedoust

34
@Robin Winslow trong trường hợp bạn muốn thêm nhiều máy chủ cho các máy chủ để cân bằng tải.
Joao Da Silva

76
Cần lưu ý rằng câu trả lời (rất hữu ích) này đề cập đến một hương vị của nginx, theo mặc định, đi kèm sites-enabledvà các sites-availablethư mục bên trong /etc/nginx. Nếu phiên bản của bạn không có hai thư mục này, nó có thể có một conf.dthư mục thay thế. Trong trường hợp đó, làm theo các hướng dẫn này sẽ không có hiệu lực, KHÔNG GIỚI HẠN bạn sửa đổi includecâu lệnh bên trong tệp nginx.confđể trỏ đến sites-enabledthay vì mặc định conf.d. Hy vọng rằng có ý nghĩa. Nó sẽ trở nên tự giải thích một khi bạn thấy câu nói includebên trong nginx.conf.
đáp ứng

167

Bạn cũng có thể thiết lập nhiều tên miền với nginx, chuyển tiếp đến nhiều quy trình node.js.

Ví dụ để đạt được những điều này:

Các cổng này (4000 và 5000) nên được sử dụng để lắng nghe các yêu cầu ứng dụng trong mã ứng dụng của bạn.

/ etc / nginx / site-enable / 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/;
    }
}

Trong / etc / nginx / site-enable / 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
Tôi đang sử dụng phương thức proxy_pass của bạn, nhưng vì một số lý do http://example.comsẽ tự động 302'đến http://www.example.com. Tại sao vậy?
Kristian

Bạn có Cloudflare hoặc một cái gì đó tương tự? Các cấu hình trên không nên chuyển hướng ở tất cả.
ozzieisaacs

1
@Kristian Bạn sẽ cần thêm proxy_set_header Host $hostđể tránh chuyển hướng HTTP 302.
Ivan Shatsky

@IvanShatsky - Bạn có thể cung cấp bất kỳ trợ giúp nào về cách định cấu hình nhiều cổng với nhiều tên miền phụ và ngăn các cổng khác chạy trong một tên miền khác không? Nginx v 1.14.1
151291

59

Bạn cũng có thể có các url khác nhau cho các ứng dụng trong một cấu hình máy chủ:

Trong / etc / nginx / sites-enable / 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/;
    }
}

Khởi động lại nginx:

sudo service nginx restart

Bắt đầu ứng dụng.

nút 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/');

nút 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
Phiên bản cộng đồng nguồn mở là miễn phí nhưng chúng có phiên bản với các tính năng khác không miễn phí. nginx.com/products/feature-matrix
0x8BADF00D

Xin lỗi vì sự thiếu hiểu biết của tôi. Mục đích, lợi ích của việc phục vụ nó theo cách này là gì? Bạn có bất kỳ ví dụ hoặc trường hợp sử dụng? Cảm ơn trước.
Mauro Aguilar

2
@MauroAguilar Nếu bạn cần 2 ứng dụng node.js trên một máy chủ, bạn có thể phục vụ họ bằng cách được đề xuất (sử dụng các cổng khác nhau). Trong trường hợp của tôi, đó là hai ứng dụng thử nghiệm khác nhau.
0x8BADF00D

Ok, nhưng sự khác biệt giữa chạy 2 ứng dụng và một ứng dụng là gì? Ý tôi là, những lợi ích nếu chúng được dự định cho cùng một mục đích là gì?
Mauro Aguilar

2
@MauroAguilar, bạn có thể chạy chúng trong một lần duy nhất và không có lợi ích gì nếu nó có thể là một phần của một dự án và có cùng mục đích. Nhưng nếu bạn cần chạy 2 dự án khác nhau với các mục đích khác nhau và với các cấu hình khác nhau trên một máy chủ thì bạn có lợi khi sử dụng cấu hình này.
0x8BADF00D

35

Tôi ủy quyền các ứng dụng Node Express độc lập thông qua Nginx.

Do đó, các ứng dụng mới có thể dễ dàng được gắn kết và tôi cũng có thể chạy các công cụ khác trên cùng một máy chủ tại các vị trí khác nhau.

Dưới đây là chi tiết về thiết lập của tôi với ví dụ cấu hình Nginx:

Triển khai nhiều ứng dụng Node trên một máy chủ web trong các thư mục con với Nginx

Mọi thứ trở nên khó khăn với Node khi bạn cần chuyển ứng dụng của mình từ localhost sang internet.

Không có cách tiếp cận chung để triển khai Node.

Google có thể tìm thấy vô số bài viết về chủ đề này, nhưng tôi đã phải vật lộn để tìm giải pháp thích hợp cho việc thiết lập mà tôi cần.

Về cơ bản, tôi có một máy chủ web và tôi muốn các ứng dụng Node được gắn vào các thư mục con (tức là http: // myhost / demo / pet-project / ) mà không đưa ra bất kỳ phụ thuộc cấu hình nào vào mã ứng dụng.

Đồng thời tôi muốn các công cụ khác như blog chạy trên cùng một máy chủ web.

Nghe có vẻ đơn giản nhỉ? Rõ ràng là không.

Trong nhiều ví dụ trên các ứng dụng Node web chạy trên cổng 80 hoặc được Nginx ủy quyền vào thư mục gốc.

Mặc dù cả hai cách tiếp cận đều hợp lệ đối với một số trường hợp sử dụng nhất định, chúng không đáp ứng các tiêu chí đơn giản nhưng hơi kỳ lạ của tôi.

Đó là lý do tại sao tôi tạo cấu hình Nginx của riêng mình và đây là một trích xuất:

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/;
  }
}

Từ ví dụ này, bạn có thể nhận thấy rằng tôi gắn ứng dụng Pet Project Node của mình chạy trên cổng 3000 đến http: // myhost / demo / pet-project .

Nginx đầu tiên kiểm tra xem liệu tài nguyên được yêu cầu có phải là tệp tĩnh có sẵn tại / opt / demo / pet-project / public / hay không và nếu nó phục vụ nó như là nó có hiệu quả cao hay không, vì vậy chúng ta không cần phải có một lớp dự phòng như Connect phần mềm trung gian tĩnh.

Sau đó, tất cả các yêu cầu khác được ghi đè và ủy quyền cho ứng dụng Pet Project Node , vì vậy ứng dụng Node không cần biết nó thực sự được gắn ở đâu và do đó có thể được di chuyển bất cứ nơi nào hoàn toàn bằng cấu hình.

proxy_redirect là phải xử lý đúng tiêu đề Vị trí. Điều này cực kỳ quan trọng nếu bạn sử dụng res.redirect () trong ứng dụng Node của mình.

Bạn có thể dễ dàng sao chép thiết lập này cho nhiều ứng dụng Node chạy trên các cổng khác nhau và thêm nhiều trình xử lý vị trí cho các mục đích khác.

Từ: http://skovalyov.blogspot.dk/2012/07/deploy-multipl-node-appluggest-on.html


1
Tại sao và làm thế nào bạn nên làm điều đó trong các tên miền phụ thay thế: skovalyov.blogspot.dk/2012/10/ mẹo
skovalyov

Liên kết chỉ trả lời, bạn có thể vui lòng tóm tắt các phần có liên quan trong câu trả lời của bạn trong trường hợp blog của bạn không còn nữa không?
kaiser

11

Node.js với cấu hình Nginx.

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

thêm cấu hình sau để Nginx hoạt động như một chuyển hướng proxy đến cổng 3000 lưu lượng truy cập từ máy chủ khi chúng tôi đến từ tên miền phụ tên miền.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

trả lời câu hỏi của bạn 2:

Tôi sẽ sử dụng tùy chọn bđơn giản vì nó tiêu tốn ít tài nguyên hơn. với tùy chọn 'a', mọi máy khách sẽ khiến máy chủ tiêu tốn rất nhiều bộ nhớ, tải tất cả các tệp bạn cần (mặc dù tôi thích php, đây là một trong những vấn đề với nó). Với tùy chọn 'b', bạn có thể tải thư viện của mình (mã có thể sử dụng lại) và chia sẻ chúng trong số tất cả các yêu cầu của khách hàng.

Nhưng hãy lưu ý rằng nếu bạn có nhiều lõi, bạn nên điều chỉnh node.js để sử dụng tất cả chúng.


2
Thực hiện theo lời khuyên này nếu tài nguyên là vấn đề quan trọng nhất của bạn (không có khả năng). Có những thỏa hiệp khác nhau giữa (a) và (b). Tùy chọn (a) có thể tốt hơn nếu bạn muốn các trang web độc lập hơn, ví dụ: khởi động lại hoặc bảo trì trang web, kết nối db, cơ sở mã, phụ thuộc thư viện, di chuyển các trang web giữa các máy chủ, v.v.
robocat 8/2/2016

8

Tôi đã tạo một kho lưu trữ trong Github mà bạn có thể sao chép, vagrant-node-nginx-cái nồi

về cơ bản, ứng dụng node.js tại /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/');

và cấu hình nginx tại /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

Bạn cũng có thể sử dụng node.js để tạo các tệp tĩnh vào một thư mục được cung cấp bởi nginx. Tất nhiên, một số phần động của trang web của bạn có thể được phục vụ bởi nút và một số bởi nginx (tĩnh).

Có một số trong số họ được phục vụ bởi nginx làm tăng hiệu suất của bạn ..


5

Chúng ta có thể dễ dàng thiết lập ứng dụng Nodejs bởi Nginx hoạt động như một proxy ngược.
Cấu hình sau đây giả sử ứng dụng NodeJS đang chạy trên 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
     }
   } 

ở trên thiết lập ứng dụng Nodejs của bạn sẽ,

  • nhận HTTP_HOSTtiêu đề nơi bạn có thể áp dụng logic cụ thể của miền để phục vụ phản hồi. '
  • Ứng dụng của bạn phải được quản lý bởi người quản lý quy trình như pm2 hoặc người giám sát để xử lý các tình huống / tái sử dụng ổ cắm hoặc tài nguyên, v.v.

  • Thiết lập dịch vụ báo cáo lỗi để nhận lỗi sản xuất như sentry hoặc rollbar

LƯU Ý: bạn có thể thiết lập logic để xử lý các tuyến yêu cầu cụ thể của miền, tạo phần mềm trung gian cho ứng dụng expressjs


1
Một lý do khác để sử dụng pm2 là để bạn có thể chạy ứng dụng của mình 'mãi mãi' sau khi thoát khỏi trình bao và tự động khởi động nó nếu bạn cần khởi động lại máy chủ của mình, xem: pm2.keymetrics.io/docs/usage/startup
SeanQuinn781

3

Nginx có thể hoạt động như một máy chủ proxy ngược hoạt động giống như người quản lý dự án. Khi nhận được yêu cầu, nó sẽ phân tích và chuyển tiếp yêu cầu ngược dòng (thành viên dự án) hoặc tự xử lý. Nginx có hai cách xử lý yêu cầu dựa trên cách cấu hình của nó.

  • phục vụ yêu cầu
  • chuyển tiếp yêu cầu đến một máy chủ khác

    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;
     }

    }

Yêu cầu máy chủ

Với cấu hình này, khi url yêu cầu là mydomain.com/static/myjs.jsnó sẽ trả về myjs.jstệp trong /my/static/files/paththư mục. Khi bạn định cấu hình nginx để phục vụ các tệp tĩnh, nó sẽ tự xử lý yêu cầu.

chuyển tiếp yêu cầu đến một máy chủ khác

Khi url yêu cầu là mydomain.com/dothisnginx sẽ chuyển tiếp yêu cầu đến http://127.0.0.1:8000 . Dịch vụ đang chạy trên cổng localhost 8000 sẽ nhận được yêu cầu và trả về phản hồi cho nginx và nginx trả về phản hồi cho khách hàng.

Khi bạn chạy máy chủ node.js trên cổng 8000 nginx sẽ chuyển tiếp yêu cầu đến node.js. Viết logic node.js và xử lý yêu cầu. Đó là bạn có máy chủ nodejs của bạn chạy phía sau máy chủ nginx.

Nếu bạn muốn chạy bất kỳ dịch vụ nào khác ngoài nodejs, chỉ cần chạy một dịch vụ khác như Django, jar, php trên các cổng khác nhau và định cấu hình nó trong nginx.


1

Bạn có thể chạy nodejs bằng pm2 nếu bạn muốn quản lý từng phương tiện microservice và chạy nó. Nút sẽ được chạy trong một cổng bên phải, chỉ cần định cấu hình cổng đó trong nginx (/etc/nginx/sites-enables/domain.com)

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

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

Kiểm tra xem localhost có chạy hay không bằng cách sử dụng 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.

Điều này là tốt nhất và như bạn đã nói dễ dàng hơn


1

Thiết lập tốt nhất và đơn giản hơn với Nginx và Nodejs là sử dụng Nginx làm bộ cân bằng tải HTTP và TCP với proxy_protatio được bật. Trong ngữ cảnh này, Nginx sẽ có thể ủy quyền các yêu cầu đến tới nodejs, đồng thời chấm dứt các kết nối SSL đến (các) máy chủ Nginx phụ trợ chứ không phải cho chính máy chủ proxy. (SSL-PassTh khóa)

Theo tôi, không có điểm nào trong việc đưa ra các ví dụ không phải SSL, vì tất cả các ứng dụng web đều (hoặc nên) sử dụng các môi trường an toàn.

Cấu hình ví dụ cho máy chủ proxy, trong /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;
}

Bây giờ, hãy xử lý máy chủ web phụ trợ. /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;
}

Bây giờ, chúng ta hãy cấu hình các máy chủ ảo với SSL này và proxy_protocol kích hoạt cấu hình tại /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;
    }
}

Và cuối cùng, một mẫu gồm 2 máy chủ web nodejs : Máy chủ đầu tiên:

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/');

Máy chủ thứ hai:

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/');

Bây giờ mọi thứ nên được làm việc hoàn hảo và cân bằng tải.

Một thời gian trước tôi đã viết về Cách thiết lập Nginx làm bộ cân bằng tải TCP trong Docker . Kiểm tra xem nếu bạn đang sử dụng Docker.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.