ChatGPT解决这个技术问题 Extra ChatGPT

Node.js + Nginx - 现在怎么办?

我已经在我的服务器上设置了 Node.js 和 Nginx。现在我想使用它,但是,在我开始之前有两个问题:

他们应该如何合作?我应该如何处理请求? Node.js 服务器有两个概念,哪个更好:为每个需要它的网站创建一个单独的 HTTP 服务器。然后在程序开始时加载所有 JavaScript 代码,这样代码就会被解释一次。湾。创建一个处理所有 Node.js 请求的 Node.js 服务器。这将读取请求的文件并评估其内容。所以文件在每个请求上都会被解释,但服务器逻辑要简单得多。

我不清楚如何正确使用 Node.js。


S
Stephen Ostermiller

Nginx 用作前端服务器,在这种情况下,它将请求代理到 node.js 服务器。因此,您需要为 node.js 设置一个 Nginx 配置文件。

这就是我在我的 Ubuntu 盒子里所做的:

/etc/nginx/sites-available/ 创建文件 yourdomain.example

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

在其中你应该有类似的东西:

# 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.example www.yourdomain.example;
    access_log /var/log/nginx/yourdomain.example.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.example yourdomain.example

/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

现在您应该在 yourdomain.example 看到“Hello World”

关于启动节点服务器的最后一个注意事项:您应该为节点守护程序使用某种监控系统。有一个很棒的tutorial on node with upstart and monit


感谢您的帖子,nginx 会缓存 node.js 对上面服务器的响应,还是每次都重新运行它们。
你有什么理由不能只做location / { proxy_pass http://127.0.0.1:3000; }?为什么需要整个 upstream 配置位?
+1,对一个常见问题的非常直接和简单的回答;非常适合想要使用 node 和 nginx 设置虚拟主机的人。我认为您错过的唯一一件事是关于为什么 nginx-in-front-of-node 最适合服务多个虚拟主机的定性答案(提问者的第二个问题)。
@Robin Winslow 如果您想为服务器添加更多服务器以进行负载平衡。
应该注意的是,这个(非常有用的)答案是指一种 nginx,默认情况下,在 /etc/nginx 中带有 sites-enabledsites-available 目录。如果您的版本没有这两个目录,则它可能只有一个 conf.d 目录。在这种情况下,除非您修改文件 nginx.conf 中的 include 语句以指向 sites-enabled 而不是默认的 conf.d,否则遵循这些说明将无效。希望这是有道理的。一旦您在 nginx.conf 中看到上述 include 语句,它应该变得不言自明。
S
Stephen Ostermiller

您还可以使用 Nginx 设置多个域,转发到多个 node.js 进程。

例如要实现这些:

domain1.example -> 到本地运行的 Node.js 进程 http://127.0.0.1:4000

domain2.example -> 到本地运行的 Node.js 进程 http://127.0.0.1:5000

这些端口(4000 和 5000)应该用于在您的应用代码中侦听应用请求。

/etc/nginx/sites-enabled/domain1

server {
    listen 80;
    listen [::]:80;
    server_name domain1.example;
    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.example;
    access_log /var/log/nginx/domain2.access.log;
    location / {
        proxy_pass    http://127.0.0.1:5000/;
    }
}

我正在使用您的 proxy_pass 方法,但由于某种原因,http://example.com 会自动302 变为 http://www.example.com。这是为什么?
你有 Cloudflare 或类似的东西吗?上面的配置根本不应该重定向。
@Kristian 您需要添加 proxy_set_header Host $host 以避免 HTTP 302 重定向。
S
Stephen Ostermiller

您还可以在一个服务器配置中为应用程序设置不同的 URL:

yourdomain.example/app1/* -> 到本地运行的 Node.js 进程 http://127.0.0.1:3000

yourdomain.example/app2/* -> 到本地运行的 Node.js 进程 http://127.0.0.1:4000

在 /etc/nginx/sites-enabled/yourdomain 中:

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

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

开源社区版本是免费的,但它们具有其他非免费功能的版本。 nginx.com/products/feature-matrix
对不起我的无知。以这种方式服务的目的和好处是什么?您有任何使用示例或案例吗?提前致谢。
@MauroAguilar 如果您在一台服务器上需要 2 个 node.js 应用程序,您可以使用建议的方式(使用不同的端口)为它们提供服务。在我的情况下,它是两个不同的测试应用程序。
好的,但是运行 2 个应用程序和运行一个应用程序有什么区别?我的意思是,如果它们用于相同目的,有什么好处?
@MauroAguilar,您可以单独运行它们,如果它可以成为一个项目的一部分并且具有相同的目的,则没有任何好处。但是,如果您需要在一台服务器上运行 2 个具有不同目的和不同配置的不同项目,那么您可以使用此配置。
r
randers

我通过 Nginx 代理独立的 Node Express 应用程序。

因此可以轻松安装新应用程序,并且我还可以在不同位置的同一台服务器上运行其他东西。

以下是有关我使用 Nginx 配置示例进行设置的更多详细信息:

使用 Nginx 在一个 Web 服务器上的子文件夹中部署多个 Node 应用程序 当您需要将应用程序从 localhost 移动到 Internet 时,使用 Node 会变得很棘手。 Node 部署没有通用的方法。谷歌可以找到关于这个主题的大量文章,但我一直在努力为我需要的设置找到合适的解决方案。基本上,我有一个 Web 服务器,并且我希望将 Node 应用程序安装到子文件夹(即 http://myhost/demo/pet-project/),而不会给应用程序代码引入任何配置依赖性。同时我希望博客等其他东西在同一个网络服务器上运行。听起来很简单吧?显然不是。在 Web 上的许多示例中,节点应用程序要么在端口 80 上运行,要么由 Nginx 代理到根。尽管这两种方法对某些用例都有效,但它们不符合我的简单但有点异国情调的标准。这就是我创建自己的 Nginx 配置的原因,这里是摘录:upstream pet_project { server localhost:3000; } 服务器 { 听 80;听 [::]:80; server_name 前端;位置 /demo/pet-project { 别名 /opt/demo/pet-project/public/; try_files $uri $uri/ @pet-project; } location @pet-project { 重写 /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 主机 $proxy_host; proxy_set_header X-NginX-Proxy 真; proxy_pass http://pet_project; proxy_redirect http://pet_project/ /demo/pet-project/; } } 从这个例子你可以注意到我将运行在端口 3000 上的 Pet Project Node 应用程序挂载到 http://myhost/demo/pet-project。首先 Nginx 会检查请求的资源是否是 /opt/demo/pet-project/public/ 上可用的静态文件,如果是,则它按原样提供它是高效的,因此我们不需要像 Connect 这样的冗余层静态中间件。然后所有其他请求都被覆盖并代理到 Pet Project Node 应用程序,因此 Node 应用程序不需要知道它实际安装的位置,因此可以纯粹通过配置将其移动到任何地方。 proxy_redirect 是正确处理 Location 标头的必要条件。如果您在 Node 应用程序中使用 res.redirect(),这非常重要。您可以轻松地为在不同端口上运行的多个 Node 应用程序复制此设置,并为其他目的添加更多位置处理程序。

来自:http://skovalyov.blogspot.dk/2012/07/deploy-multiple-node-applications-on.html


为什么以及如何在子域中执行此操作:skovalyov.blogspot.dk/2012/10/…
S
Stephen Ostermiller

带有 Nginx 配置的 Node.js。

$ sudo nano /etc/nginx/sites-available/subdomain.your-domain.example

添加以下配置,以便当我们来自 subdomain.your_domain.example 时,充当代理的 Nginx 从服务器重定向到端口 3000 流量

upstream subdomain.your-domain.example {
  server 127.0.0.1:3000;
}
server {
  listen 80;
  listen [::]:80;
  server_name subdomain.your-domain.example;
  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.example;
    proxy_redirect off;
  }
}

r
randers

我在 Github 中创建了一个存储库,您可以克隆它,vagrant-node-nginx-boilerplate

基本上 /var/www/nodeapp 处的 node.js 应用程序是

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

/etc/nginx/sites-available/ 的 nginx 配置是

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

H
Hugo Mota

回答你的问题2:

我会使用选项 b 只是因为它消耗的资源少得多。使用选项'a',每个客户端都会导致服务器消耗大量内存,加载您需要的所有文件(即使我喜欢 php,这是它的问题之一)。使用选项“b”,您可以加载您的库(可重用代码)并在所有客户端请求中共享它们。

但请注意,如果您有多个内核,您应该调整 node.js 以使用所有内核。


如果资源是您最重要的问题(不太可能),请遵循此建议。 (a) 和 (b) 之间存在不同的折衷。如果您希望站点更加独立,例如站点重新启动或维护、数据库连接、代码库、库依赖关系、在服务器之间移动站点等,选项 (a) 可能会更好。
S
Stephen Ostermiller

Nginx 可以充当反向代理服务器,就像项目经理一样工作。当它收到请求时,它会对其进行分析并将请求转发给上游(项目成员)或自行处理。 Nginx 有两种根据配置方式处理请求的方式。

服务请求

将请求转发到另一个服务器 server{ server_name mydomain.example sub.mydomain.example;位置 /{ proxy_pass http://127.0.0.1:8000; proxy_set_header 主机 $host; proxy_pass_request_headers 开启; } 位置 /static/{ 别名 /my/static/files/path; } }

服务器请求

使用此配置,当请求 URL 为 mydomain.example/static/myjs.js 时,它会返回 /my/static/files/path 文件夹中的 myjs.js 文件。当您将 Nginx 配置为提供静态文件时,它会自行处理请求。

将请求转发到另一台服务器

当请求 URL 为 mydomain.example/dothis 时,Nginx 会将请求转发到 http://127.0.0.1:8000。在 localhost 8000 端口上运行的服务将接收请求并将响应返回给 Nginx,Nginx 将响应返回给客户端。

当您在端口 8000 上运行 node.js 服务器时,Nginx 会将请求转发到 node.js。编写 node.js 逻辑并处理请求。就是这样,您的 nodejs 服务器在 Nginx 服务器后面运行。

如果您希望运行除 nodejs 之外的任何其他服务,只需在不同端口上运行另一个服务(如 Django、flask、PHP)并在 Nginx 中配置它。


M
Matej

您还可以使用 node.js 将静态文件生成到 nginx 服务的目录中。当然,站点的一些动态部分可以由节点提供,而一些由 nginx(静态)提供。

让其中一些由 nginx 提供服务可以提高您的性能..


S
Stephen Ostermiller

我们可以通过 Nginx 作为反向代理轻松设置 Nodejs 应用程序。以下配置假设 NodeJS 应用程序在 127.0.0.1:8080 上运行,

  server{
     server_name domain.example sub.domain.example; # 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 或主管等进程管理器管理,以处理情况/重用套接字或资源等。

设置错误报告服务以获取生产错误,例如哨兵或滚动条

注意:您可以设置处理特定域请求路由的逻辑,为 expressjs 应用程序创建一个 middleware


使用 pm2 的另一个原因是,您可以在退出 shell 后“永远”运行您的应用程序,并在您需要重新启动服务器时自动启动它,请参阅:pm2.keymetrics.io/docs/usage/startup
S
Stephen Ostermiller

使用 Nginx 和 Nodejs 最好和更简单的设置是使用 Nginx 作为启用 proxy_protocol 的 HTTP 和 TCP 负载平衡器。在这种情况下,Nginx 将能够将传入请求代理到 nodejs,并终止与后端 Nginx 服务器而不是代理服务器本身的 SSL 连接。 (SSL 直通)

在我看来,给出非 SSL 示例是没有意义的,因为所有 Web 应用程序都(或应该)使用安全环境。

代理服务器的示例配置,在 /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;
}

现在,让我们在 /etc/nginx/sites-available/example.com-https.conf 使用这个 SSL 和启用 proxy_protocol 的配置来配置虚拟主机:

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

现在一切都应该完美地工作和负载平衡。

不久前,我写了关于 How to set up Nginx as a TCP load balancer in Docker 的文章。如果您使用的是 Docker,请检查一下。


所以上面的设置使用 nginx 作为反向代理和 web 服务器。这样正确吗?
S
Stephen Ostermiller

如果您想管理每个微服务方式并运行它,您可以使用 pm2 运行 nodejs。节点将在一个端口中运行,只需在 Nginx (/etc/nginx/sites-enabled/domain.example) 中配置该端口即可

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

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

使用 ping 检查天气 localhost 是否正在运行。

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.

这是最好的,正如你所说的更容易