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') 触发后,reqres 并不会在连接断开后立即销毁,而是会一直挂在内存中。因此,每一个用户进来都会新建一个 req.session。如果用户的 header 中包含 session id,并且该 session id 在 sessionStore 中能找到,对应的 session 内容会被合并到新的 session 中。

Session 中间件的工作机制

  • 接管 res.endsession 中间件接管了 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. 处理请求:在请求处理函数中,每个用户连接进来都会新建一个 reqres 对象。
  3. Session 管理session 中间件会在每次 res.end 调用前将 session 内容存入 sessionStore
  4. 内存管理reqres 对象不会在连接断开后立即销毁,而是会一直挂在内存中。

总结

  • 正确使用 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)都会创建 reqres 对象。这些对象会在请求处理完成后释放,但它们并不是立即销毁的。相反,它们会被放到事件循环中等待下一个任务。
  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-sessionconnect-redis 来配置Session Store。
  • 每次用户访问根路径 /,都会增加 views 的计数。
  • 通过 RedisStore 将Session数据保存到Redis服务器,而不是内存中。

总结

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

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

回到顶部