Sử dụng MemoryStore trong sản xuất


116

Hôm nay, lần đầu tiên tôi chạy ứng dụng Node.js của mình ở chế độ "sản xuất" và nhận được cảnh báo này:

Warning: connection.session() MemoryStore is not
designed for a production environment, as it will leak
memory, and obviously only work within a single process.

Tôi chỉ cần chạy một quy trình duy nhất, nhưng thay vào đó tôi nên sử dụng cái gì? Tôi muốn các phiên của mình nằm trong RAM để truy cập nhanh. Tôi cũng muốn có thể loại bỏ tất cả các phiên bằng cách tắt ứng dụng Node.

Có vẻ như quá mức cần thiết để cài đặt Redis, MongoDB hoặc cơ sở dữ liệu khác chỉ cho nhiệm vụ đơn giản này. Tôi cũng không hiểu tại sao MemoryStore lại được đưa vào Node khi nó thực sự không nên được sử dụng?

Câu trả lời:


29

MemoryStore chỉ dành cho chế độ phát triển (nhanh), vì nếu ứng dụng của bạn khởi động lại (quá trình chết), bạn sẽ mất tất cả dữ liệu phiên (nằm trong bộ nhớ của quá trình đó).

Nếu bạn không muốn sử dụng cơ sở dữ liệu, hãy sử dụng lưu trữ cookie được mã hóa.

http://www.senchalabs.org/connect/cookieSession.html


80

Được rồi, sau khi nói chuyện với các nhà phát triển Connect, tôi đã có thêm thông tin. Có hai điều được coi là rò rỉ bộ nhớ ở đây:

  1. sự cố với phân tích cú pháp JSON đã được khắc phục trong các phiên bản gần đây
  2. thực tế là không có quá trình dọn dẹp các phiên đã hết hạn nếu người dùng không bao giờ truy cập chúng (tức là lần dọn dẹp duy nhất là khi truy cập)

Giải pháp có vẻ khá đơn giản, ít nhất đây là những gì tôi định làm: sử dụng setInterval để dọn dẹp định kỳ các phiên đã hết hạn. MemoryStore cung cấp all () để lấy danh sách, và chúng ta có thể sử dụng get () để buộc đọc và do đó, chúng sẽ hết hạn. Mã giả:

function sessionCleanup() {
    sessionStore.all(function(err, sessions) {
        for (var i = 0; i < sessions.length; i++) {
            sessionStore.get(sessions[i], function() {} );
        }
    });
}

Bây giờ chỉ cần gọi sessionCleanup theo định kỳ thông qua setInterval () và bạn có bộ sưu tập rác tự động cho các phiên đã hết hạn. Không còn rò rỉ bộ nhớ.


3
Tôi phát hiện ra rằng bạn cũng có thể sử dụng Redis và Mongo như một kho lưu trữ hỗ trợ và yêu cầu db dọn dẹp nó. Trong trường hợp của Mongo, bạn có thể đặt ngày hết hạn mà vẫn đảm bảo lập chỉ mục.
huggie

57
Đó thực sự là một điều ngu ngốc mà họ đã làm khi đặt thông điệp này ở đó. Nó giống như "chúng tôi có thể làm đúng nhưng thay vào đó chúng tôi sẽ chỉ làm sai và bạn chơi trò chơi đoán trên internets. Ha ha! Thua!"
catamphetamine

2
giá trị của var sessionStore là gì?
Dimitri Kopriwa

4
sessionStore? Đó có phải là một biến toàn cục của node.js không? Nếu không, làm cách nào tôi có thể lấy tham chiếu đến Phiên lưu trữ trong node.js?
windchime

1
@MilanBabuskov - bạn có đưa cái này vào app.jstệp của mình không? Có tùy chọn nào để đưa ra cuộc gọi lại bên trong phiên cấp tốc không? Thêm một chút chi tiết về cách xâm phạm điều này sẽ rất tuyệt.
Jonathan Bechtel

46

Vì vậy, câu trả lời được chấp nhận cho điều này là [sửa: đã] bị hack khá nhiều và những người khác chỉ đang khuyến nghị sử dụng cơ sở dữ liệu mà tôi nghĩ là quá mức cần thiết.

Tôi gặp vấn đề tương tự và vừa thay thế express-session bằng cookie-session .

Để làm điều này, chỉ cần cài đặt cookie-session:

npm install cookie-session

Sau đó app.js, tìm nơi express-sessionđang được sử dụng và thay thế bằng cookie-session.

app.use(require('cookie-session')({
    // Cookie config, take a look at the docs...
}));

Bạn có thể cần phải thay đổi một số thứ khác, đối với tôi là một sự hoán đổi đơn giản-ra-bobs-của-chú-bạn-không-hại-được-thực hiện.


2
Cậu đã làm thế nào vậy.
Sid

2
Đây thực sự là một câu trả lời hữu ích. Thanx.
smonff

5
sự khác biệt là cookie-sessionlưu trữ dữ liệu trên máy khách, trong khi express-sessionlưu trữ dữ liệu trên máy chủ.
George

11

Mô-đun này được thiết kế để giải quyết vấn đề rò rỉ bộ nhớ. https://www.npmjs.com/package/session-memory-store

Câu trả lời được chấp nhận có thể ổn. Tuy nhiên, vì câu hỏi này hiển thị cao trong danh sách kết quả tìm kiếm, tôi đã nghĩ rằng tôi sẽ bao gồm câu hỏi này trong trường hợp nó giúp ích cho bất kỳ ai khác.


Chưa thử điều này nhưng có vẻ như một cách khắc phục tuyệt vời cho tình huống (nếu OP vẫn ổn với các phiên bị mất khi khởi động lại ứng dụng)
stujo

Từ liên kết của bạn: "Bạn không nên sử dụng nó trong sản xuất!". Câu hỏi là về "Sử dụng MemoryStore trong sản xuất".
Damien

Đúng, nhưng chỉ vì "bạn không thể chia sẻ phiên với những người khác quy trình hoặc dịch vụ khác." Có nghĩa là, có những giải pháp khác thiết thực hơn. Nhưng điều này giải quyết được vấn đề rò rỉ bộ nhớ, vì vậy nếu đó không phải là mối quan tâm của bạn thì bạn có thể sử dụng và giải quyết mối lo ngại trong câu hỏi.
Dovev Hefetz

7

Tôi nghĩ rằng sự đồng thuận trên web là cách đúng đắn sẽ thực sự là sử dụng DB cho việc đó, nhưng nếu bạn khẳng định rằng bạn không muốn làm điều đó, thì hãy loại bỏ cảnh báo - cảnh báo không phải là luật.

Tuy nhiên, vì bạn và tôi đều đồng ý rằng rò rỉ bộ nhớ là một vấn đề thực sự, nên thật khó để biện minh cho việc redis là quá mức cần thiết, vì nó sẽ giải quyết được vấn đề của bạn.

Tôi cũng không hiểu tại sao MemoryStore lại được đưa vào Node khi nó không thực sự được sử dụng

đó là một điểm tuyệt vời - nhưng tôi muốn nói rằng bản thân nút chỉ mới gần đây đã sẵn sàng sản xuất . Một số người sẽ không đồng ý với quan điểm rằng nó là gì cả.


2
Việc ngăn chặn cảnh báo sẽ không làm mất bộ nhớ.
Milan Babuškov

lol đây là lý do tại sao họ khuyên bạn không nên sử dụng nó trong sản xuất. vì vậy cách thay thế là sử dụng một phương pháp lưu trữ thay thế, phải không?
Kristian

1
Tôi đoán tôi chỉ không thích các lựa chọn thay thế mà tôi đã tìm thấy cho đến nay. Tôi đang tìm kiếm một giải pháp thay thế javascript trong bộ nhớ đơn giản, không phải hệ thống cơ sở dữ liệu. Tôi thực sự không hiểu tại sao họ không sửa nó. Ý tôi là, một Kho lưu trữ bộ nhớ đơn giản có thể khó đến mức nào ... Tôi chỉ hy vọng ai đó đã làm được điều đó, vì vậy tôi không cần phải phát minh lại bánh xe.
Milan Babuškov

2
Tôi cảm thấy nỗi đau của bạn, nhưng nút hiện đang chảy máu khá nhiều .. nó gần như đi kèm với lãnh thổ
Kristian

7
MemoryStore không có trong Node, nó có trong Express / Connect
Mustafa

6

Cách thay thế là sử dụng Redis hoặc Mongo làm cửa hàng. Với Mongo, bạn sử dụng mô-đun express-session-mongo .

Có một lời khuyên là loại bỏ các phiên cũ bằng tùy chọn lập chỉ mục:

var MongoStore = require('express-session-mongo');
app.use(express.session({ store: new MongoStore() }));

db.sessions.ensureIndex( { "lastAccess": 1 }, { expireAfterSeconds: 3600 } )

Vì các phiên cũ bị chính cơ sở dữ liệu loại bỏ, phiên Express không cần tự xử lý việc dọn dẹp.

CHỈNH SỬA : Có vẻ như bạn cần có trường "lastAccess" của riêng mình. Khi bạn truy cập nó, bạn tự cập nhật trường đó. Kiểm tra dữ liệu hết hạn của tài liệu MongoDB http://docs.mongodb.org/manual/tutorial/expire-data/

EDIT2 :

Bây giờ trở thành db.sessions.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

Chuỗi nền Mongo để kiểm tra trường này chạy cứ sau 60 giây. Vì vậy thời điểm gỡ tài liệu không được chính xác.


2

Đối với những ai đang gặp sự cố với Redis, hãy thử cách sau - hy vọng điều này sẽ hữu ích.

Tôi đang sử dụng Redis cho DEV và PROD và nhắm mục tiêu Express v4. Trên Windows, tôi đang sử dụng bộ công cụ MSOpenTech Redis v3.0 nhẹ, nếu không, tôi chỉ sử dụng Heroku Redis Addon. Để làm cho nó hoạt động thông qua Node không quá khó - cho đến nay ...

var session = require('express-session');

. . .

var RedisStore = require('connect-redis')(session);

var redisClient = require('redis').createClient(process.env.REDIS_URL);

var redisOptions = { 
        client: redisClient, 
        no_ready_check: true,
        ttl: 600,
        logErrors: true
};

var redisSessionStore = new RedisStore(redisOptions);

app.use(session({
    store: redisSessionStore,
    secret: 'Some.Long.Series.of.Crazy.Words.and.Jumbled.letter.etc',
    resave: true,       
    saveUninitialized: true 
}));

Chúc may mắn!

ps. Tôi chỉ đọc lại truy vấn ban đầu và nhận thấy điều này - xin lỗi!

Có vẻ như quá mức cần thiết để cài đặt Redis, MongoDB hoặc cơ sở dữ liệu khác chỉ cho nhiệm vụ đơn giản này.


0

Nếu bạn sử dụng OSX sử dụng

brew install memcached

nếu linux

apt install memcached

giải quyết thông báo phiên, ứng dụng becose de có thể kết nối với dịch vụ memcache 127.0.0.1:11211.

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.