Nodejs的整个HTTP机制,问题儿童又来了,请教以便整理编程思维

Nodejs的整个HTTP机制,问题儿童又来了,请教以便整理编程思维

研究了Session的源码,之前对Node.js完全理解错误了,现在估摸着新的思路

Session源码里写得很清楚,Session自己的MemoryStore,不建议用于成品环境,只建议用于开发环境,至于为什么,下面详细道来.

我先只了解了MemoryStore的原理,如果用户在调用connect.session()的时候,option里没有store参数,session会把store指定为自己的MemoryStore,而这个MemoryStore其实就是在req这个对象下新建一个sessionStore的对象储存用户cookie数据,当用户不断增加时,sessionStore这个对象也会不断增大,所以Linkedln的建议是不要用内置的MemoryStore,这样浪费内存.

而Node.js是单线程的,在server.on(触发后?)req和res并不会销毁一直挂在内存里,我之前理解不了是因为忽略了单线程的特性,每一个用户进来都会新建一个req.session,如果用户的header有sid并能在sessionStore里找到,那么对应sid的内容就会合并到新的session里.如果两个用户同时并发进来,Node.js其实也是按循环事件的调用形式res.end给每个用户,而session中间件早已接管了res.end,使得每次结束连接之前都会把session的内容存进sessionStore.

这里需要注意的是,session不但接管了res.end,而且还在res.on注册了新的’header’事件,这个事件在调用<code>res._renderHeader()</code>的时候触发,用户无论res.write还是res.end都会调用<code>res._renderHeader()</code>,详细可参考Node.js源码.

so,下面的思路是错的! and,严重不建议使用内置的MemoryStore!

##错的:

因为水平低,源码看不懂,都是估摸出来的,所以希望各位指出错误

建立一个异步事件,就是createServer,一个用户连接进来后事件触发

触发后Node会为这个用户建立两个新的对象,分别是req和res

res.end后就是连接断开后,销毁为这个用户建立的两个对象

所以session都是req的属性,在连接断开后session也会跟着被销毁

所以当有N个用户并发进来的时候,就会建立N对req/res实例

望指正


6 回复

Node.js 的整个 HTTP 机制

问题儿童又来了,请教以便整理编程思维

研究了 Session 的源码后,我发现我对 Node.js 的理解存在一些偏差。现在我试图整理出正确的思路。

Session 源码解析

首先,Session 源码里明确说明了,Session 自己的 MemoryStore 不建议在生产环境中使用,仅适用于开发环境。这是因为:

  • 内存占用:如果用户在调用 connect.session() 时没有提供 store 参数,session 会默认将 store 指定为 MemoryStore。而 MemoryStore 实际上是在 req 对象下新建一个 sessionStore 对象来存储用户 cookie 数据。随着用户数量增加,sessionStore 对象也会不断增大,这会导致内存浪费。

单线程特性与 Session 管理

Node.js 是单线程的,这意味着在 server.on('request') 触发后,req 和 res 并不会在连接断开后立即销毁,而是会一直挂在内存中。因此,每一个用户进来都会新建一个 req.session。如果用户的 header 中包含 session id,并且该 session id 在 sessionStore 中能找到,对应的 session 内容会被合并到新的 session 中。

Session 中间件的工作机制

  • 接管 res.end:session 中间件接管了 res.end,确保每次结束连接前,都会将 session 的内容存入 sessionStore。

  • 注册 header 事件:session 还在 res 上注册了一个新的 'header' 事件,该事件在调用 res._renderHeader() 时触发。无论用户调用 res.write 还是 res.end,都会调用 res._renderHeader()。具体可以参考 Node.js 源码。

错误的理解

以下思路是错误的!并且强烈不建议使用内置的 MemoryStore:

// 错误的代码示例
const http = require('http');

http.createServer((req, res) => {
    // 建立一个异步事件,用户连接进来后事件触发
    res.end(); // 连接断开后,销毁为这个用户建立的 req 和 res 对象
}).listen(3000);

正确的理解应该是:

  1. 创建服务器:使用 http.createServer 创建服务器。
  2. 处理请求:在请求处理函数中,每个用户连接进来都会新建一个 req 和 res 对象。
  3. Session 管理:session 中间件会在每次 res.end 调用前将 session 内容存入 sessionStore。
  4. 内存管理:req 和 res 对象不会在连接断开后立即销毁,而是会一直挂在内存中。

总结

  • 正确使用 Session:避免使用内置的 MemoryStore,考虑使用数据库或其他持久化存储方案。
  • 单线程特性:理解 Node.js 的单线程特性,合理管理内存资源。

希望以上内容能帮助你更好地理解和使用 Node.js 的 HTTP 机制。


对象像你这么理解也没问题. session倒是需要LZ去搞清楚一下其本质

如果是刚接触 Web 那不错了… Sesstion 应该是另外处理的, 不是链接断开就直接销毁的 大概是 maxAge: http://www.senchalabs.org/connect/middleware-session.html

如果去掉session的描述,其他的对否?

这样啊,连接断开后,res究竟有没销毁?session不是全局对象,就是说res一直没销毁?

这两天花时间把Session源码解构一下

你的理解中存在一些误区,让我帮你澄清一下Node.js中的HTTP机制以及Session的处理方式。

正确的理解:

  1. 单线程与事件驱动:

    • Node.js 是基于事件驱动的单线程模型。这意味着所有请求都由同一个线程处理,但通过异步I/O操作不会阻塞其他请求的处理。
  2. req 和 res 对象:

    • 每个请求(request)和响应(response)都会创建 req 和 res 对象。这些对象会在请求处理完成后释放,但它们并不是立即销毁的。相反,它们会被放到事件循环中等待下一个任务。
  3. Session Store:

    • 使用内置的 MemoryStore 存储Session数据确实不是一个好的生产环境选择,因为它会导致内存泄漏。更好的做法是使用如 Redis 这样的分布式存储系统。

示例代码

以下是一个简单的Express应用,展示了如何设置一个基于Redis的Session Store:

const express = require('express');
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const redis = require('redis');
const client = redis.createClient();

const app = express();

app.use(session({
    store: new RedisStore({ client }),
    secret: 'your_secret_key',
    resave: false,
    saveUninitialized: false
}));

app.get('/', (req, res) => {
    if (req.session.views) {
        req.session.views++;
        res.setHeader('Content-Type', 'text/html');
        res.write(`<p>views: ${req.session.views}</p>`);
    } else {
        req.session.views = 1;
        res.write('<p>First visit</p>');
    }
    res.end();
});

app.listen(3000, () => {
    console.log('App listening on port 3000');
});

在这个例子中:

  • 我们使用了 express-session 和 connect-redis 来配置Session Store。
  • 每次用户访问根路径 /,都会增加 views 的计数。
  • 通过 RedisStore 将Session数据保存到Redis服务器,而不是内存中。

总结

  • 在Node.js中,虽然单线程处理所有的请求,但是通过事件驱动机制,多个请求可以并发执行。
  • 使用内置的 MemoryStore 不适合生产环境,应考虑使用分布式存储系统如Redis。
  • 每个请求和响应对象 (req 和 res) 会在请求处理完毕后被释放,但不是立即销毁。

希望这能帮助你更好地理解Node.js的HTTP机制和Session管理。

回到顶部