Làm cách nào để lưu trữ nhiều trang web Node.js trên cùng một IP / máy chủ với các miền khác nhau?


92

Tôi có một máy chủ linux với một IP duy nhất được liên kết với nó. Tôi muốn lưu trữ nhiều trang web Node.js trên máy chủ này trên IP này, mỗi trang (rõ ràng) có một miền hoặc miền phụ duy nhất. Tôi muốn tất cả chúng trên cổng 80.

Tôi có những lựa chọn nào để làm điều này?

Một giải pháp rõ ràng dường như là có tất cả các miền được phục vụ bởi một ứng dụng web node.js hoạt động như một proxy và thực hiện chuyển qua các ứng dụng node.js khác đang chạy trên các cổng duy nhất.


4
Tôi làm điều này và ngược dòng với nginx, lưu trữ ảo dựa trên tên. Như một phần thưởng nginx có thể được cấu hình để phục vụ các tập tin tĩnh, làm đổi hướng perm vv
— numbers1311407

Câu trả lời:


83

Chọn một trong số:

  • Sử dụng một số máy chủ khác ( như nginx ) làm proxy ngược.
  • Sử dụng node-http-proxy làm proxy ngược.
  • Sử dụng phần mềm trung gian vhost nếu mỗi miền có thể được phân phát từ cùng một cơ sở mã Connect / Express và phiên bản node.js.

3
đó là một danh sách rất hay và ngắn gọn về các tùy chọn mà tôi đã đọc ở những nơi khác. Bạn có tình cờ biết đối với mỗi giải pháp này, quy trình nào sẽ cần phải được khởi động lại khi một miền mới được thêm vào không? Đối với 1) không có. Đối với 2) chỉ nút-http-proxy. Đối với 3) toàn bộ chuỗi của tất cả các trang web sẽ cần được khởi động lại. Điều này có chính xác?
— Flion

1
@Flion: Bạn có thể viết các proxy dựa trên nút theo cách mà bạn có thể tải lại cấu hình miền mà không yêu cầu khởi động lại quy trình. Nó thực sự phụ thuộc vào yêu cầu chính xác của ứng dụng của bạn.
— josh3736

Không phải những gì đã được hỏi.
— Patrick Sturm

52

Diet.js có một cách rất hay và đơn giản để lưu trữ nhiều tên miền với cùng một phiên bản máy chủ. Bạn chỉ có thể gọi mộtserver()tên miềnmớicho mỗi tên miền của mình.

Một ví dụ đơn giản

// Require diet
var server = require('diet');

// Main domain
var app = server()
app.listen('http://example.com/')
app.get('/', function($){
    $.end('hello world ')
})

// Sub domain
var sub = server()
sub.listen('http://subdomain.example.com/')
sub.get('/', function($){
    $.end('hello world at sub domain!')
})

// Other domain
var other = server()
other.listen('http://other.com/')
other.get('/', function($){
    $.end('hello world at other domain')
})

Tách các ứng dụng của bạn

Nếu bạn muốn có các thư mục khác nhau cho các ứng dụng của mình thì bạn có thể có cấu trúc thư mục như sau:

/server
   /yourApp
       /node_modules
       index.js
   /yourOtherApp
       /node_modules
       index.js
   /node_modules
   index.js

Trong /server/index.jsbạn sẽ yêu cầu mỗi ứng dụng theo thư mục của nó:

require('./yourApp')
require('./yourOtherApp')

Trong /server/yourApp/index.jsbạn sẽ thiết lập miền đầu tiên của mình chẳng hạn như:

// Require diet
var server = require('diet')

// Create app
var app = server()
app.listen('http://example.com/')
app.get('/', function($){
    $.end('hello world ')
})

Và trong /server/yourOtherApp/index.jsbạn sẽ thiết lập miền thứ hai của mình chẳng hạn như:

// Require diet
var server = require('diet')

// Create app
var app = server()
app.listen('http://other.com/')
app.get('/', function($){
    $.end('hello world at other.com ')
});

Đọc thêm:


Nhận xét này lưu tất cả các vấn đề của tôi :) ... thậm chí vào năm 2016
— myTerminal

Điều này sẽ tự động tải lại? Tôi đã bắt đầu sử dụng PM2 nhưng nó không cho phép tôi lưu trữ nhiều miền và proxy ngược
— Pini Cheyni

Điều này có thay thế express, hoặc làm việc cùng với nó? Tôi đoán là một trong hai. Nhưng tôi muốn chắc chắn trước khi tạo frankenstein.
— Mardok

1
FYI Kể từ tháng 7 năm 2019 - dietjs.com không còn hoạt động nữa và không có bản cập nhật nào cho cơ sở mã github trong ~ 2 năm.
— sirclesam

20

Hm ... tại sao bạn nghĩ rằng nodejs nên hoạt động như một proxy. Tôi sẽ đề xuất chạy một số ứng dụng nút đang lắng nghe trên các cổng khác nhau. Sau đó, sử dụng nginx để chuyển tiếp yêu cầu đến đúng cổng. Nếu sử dụng một nodejs duy nhất, bạn cũng sẽ có một điểm thất bại duy nhất. Nếu ứng dụng đó bị lỗi thì tất cả các trang web sẽ ngừng hoạt động.



12

Tôi có một API tôi sử dụng trên một trang web và bên dưới là cấu hình của tôi. Tôi cũng có nó với SSL và GZIP, nếu ai đó cần thì cứ comment cho tôi biết.

var http = require('http'),
    httpProxy = require('http-proxy');

var proxy_web = new httpProxy.createProxyServer({
        target: {
            host: 'localhost',
            port: 8080
        }
    });

    var proxy_api = new httpProxy.createProxyServer({
        target: {
            host: 'localhost',
            port: 8081
        }
    });

    http.createServer(function(req, res) {
        if (req.headers.host === 'http://www.domain.com') {
            proxy_web.proxyRequest(req, res);
            proxy_web.on('error', function(err, req, res) {
                if (err) console.log(err);
                res.writeHead(500);
                res.end('Oops, something went very wrong...');
            });
        } else if (req.headers.host === 'http://api.domain.com') {
            proxy_api.proxyRequest(req, res);
            proxy_api.on('error', function(err, req, res) {
                if (err) console.log(err);
                res.writeHead(500);
                res.end('Oops, something went very wrong...');
            });
        }
    }).listen(80);

7

Nếu bạn đang sử dụng máy chủ kết nối / express, bạn có thể thấy vhostphần mềm trung gian. Nó sẽ cho phép nhiều tên miền (tên miền phụ) được sử dụng cho địa chỉ máy chủ.

Bạn có thể làm theo ví dụ được đưa ra ở đây , giống như những gì bạn cần.



3

Đây là dự án demo đơn giản nhất của tôi mà không có bất kỳ phần mềm trung gian hoặc proxy nào.
Điều này chỉ cần một vài mã là đủ.

https://github.com/hitokun-s/node-express-multiapp-demo

Với cấu trúc này, bạn có thể dễ dàng thiết lập và duy trì từng ứng dụng một cách độc lập.
Tôi hy vọng đây sẽ là một sự giúp đỡ cho bạn.


3

Đầu tiên cài đặt vĩnh viễn và bouncy .

Sau đó viết một kịch bản khởi động. Trong tập lệnh này, hãy thêm quy tắc vào tiện ích tường lửa iptables để yêu cầu nó chuyển tiếp lưu lượng trên cổng 80 đến cổng 8000 (hoặc bất kỳ thứ gì khác mà bạn chọn). Trong ví dụ của tôi, 8000 là nơi tôi chạy bouncy

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8000

Sử dụng mãi mãi, hãy yêu cầu script chạy bouncy trên cổng 8000

forever start --spinSleepTime 10000 /path/to/bouncy /path/to/bouncy/routes.json 8000

Các tuyến đường.json sẽ giống như

{
    “subdomain1.domain.com" : 5000,
    “subdomain2.domain.com" : 5001,
    “subdomain3.domain.com" : 5002
}

NodeJS application1, application2 và application3 lần lượt chạy trên cổng 5000, 5001 và 5002.

Tập lệnh tôi sử dụng trong trường hợp của mình có thể được tìm thấy tại đây và bạn có thể phải thay đổi một chút để phù hợp với môi trường của mình.

Tôi cũng đã viết về điều này chi tiết hơn và bạn có thể tìm thấy nó ở đây .


Bạn nên kiểm tra PM2
— Pini Cheyni

Được rồi, điều này thật tuyệt, nhưng làm thế nào tôi có thể buộc http-> https trong bouncy ??

2

Đây là cách thực hiện bằng cách sử dụng vanilla Node.js:

const http = require('http')
const url = require('url')
const port = 5555
const sites = {
  exampleSite1: 544,
  exampleSite2: 543
}

const proxy = http.createServer( (req, res) => {
  const { pathname:path } = url.parse(req.url)
  const { method, headers } = req
  const hostname = headers.host.split(':')[0].replace('www.', '')
  if (!sites.hasOwnProperty(hostname)) throw new Error(`invalid hostname ${hostname}`)

  const proxiedRequest = http.request({
    hostname,
    path,
    port: sites[hostname],
    method,
    headers 
  })

  proxiedRequest.on('response', remoteRes => {
    res.writeHead(remoteRes.statusCode, remoteRes.headers)  
    remoteRes.pipe(res)
  })
  proxiedRequest.on('error', () => {
    res.writeHead(500)
    res.end()
  })

  req.pipe(proxiedRequest)
})

proxy.listen(port, () => {
  console.log(`reverse proxy listening on port ${port}`)
})

Khá đơn giản phải không?


1

đôi khi bạn nhận được đối tượng yêu cầu và phản hồi, bạn có thể lấy miền thông qua "request.headers.host" ... (không phải ip, thực sự là miền)


0

Hướng dẫn này từ đại dương kỹ thuật số là một cách tuyệt vời. Nó sử dụng mô-đun pm2 để tạo ứng dụng của bạn (chạy chúng như một dịch vụ). Không cần các mô-đun bổ sung như Forever, vì nó sẽ tự động khởi động lại ứng dụng của bạn nếu nó gặp sự cố. Nó có nhiều tính năng giúp bạn giám sát các ứng dụng khác nhau đang chạy trên máy chủ của bạn. Nó khá tuyệt vời!

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 cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.