peaksnail / pinpoint-node-agent

pinpoint agent for nodejs
Apache License 2.0
75 stars 26 forks source link

关于module._load的bug #14

Closed fernandou closed 7 years ago

fernandou commented 7 years ago

instance变量用于存储加载过的变量,但是如果遇到不同版本号的模块时(模块名字相同,但是路径不一样)因为不同模块可能依赖相同的模块,但是依赖模块的版本号不一样,导致依赖模块的绝对路径不一样(实际上是两个模块了),但是你之前通过instance存储了,导致第二次加载名字相同但是路径不同的模块式实际上用的第一次的模块,不知道我有没有表达清楚;

peaksnail commented 7 years ago

1 instance变量不是存储加载过的变量,而是 会判断当前module是否加载过,如果未加载过,或根据应用的nodes_module 路径去查找加载,否则返回缓存中加载过的模块

2 不同版本的模块,如果要能使用,假设都在同一nodes_module下,那么他们在nodes_modules下的模块名(目录名)肯定也是不一样的。假设在不同的nodes_modules下,模块名相同,这样的话,node在查找模块时,当发现要加载的模块名时,就加载了,后面一个模块也不会被加载。

所以 即使两个不同版本的模块,也是被视为两个不同的模块,要想能被分别加载,模块名也是不一样的,这样,路径也不一样,load也能正常工作。

或许你可以提供下你说的实际场景,再讨论下?

fernandou commented 7 years ago

你好: 1:比方说有两个模块都依赖promise,但是依赖的版本不同,所以两个模块的nodes_module下面都有一个promise,当应用开启时,先加载的promise会被存储到instance,后加载的promise直接就用这个instance,因为两个模块都是require('promise'); 就是一个应用依赖模块a和b,a模块依赖promise1.0,b模块依赖promise2.0,如果a先加载,promise1.0会被先存储到instance,当加载promise2.0时就直接用这个instance了;因为require('promise');key值是一样的 2:关于你说的第一点,个人觉得系统已经实现了,没必要自己再去实现一遍

peaksnail commented 7 years ago

1 这个问题确实可能存在,我这边需要再验证修复下 2 缓存是在require那边,后面看下能否优化 多谢了

fernandou commented 7 years ago

恩恩,可以把key值统一换成filename(绝对路径); 另外有个问题没弄明白,想请教一下,我就写在这里了,关于process.namespaces是如何跟踪一个请求的,traceContext通过traceContextFactory创建,这个不是一直存在的么,但是为什么每次请求过来traceContext会被重新初始化,这个是怎么实现的,还有就是namespace.id = process.addAsyncListener这个是什么意思

peaksnail commented 7 years ago

这里是使用 cls 模块 因为 nodejs 存在回调函数的链式调用,本身并没有类似java threadLocal的机制,也就不知道某次调用栈的上下文关系。 cls 模块正好提供了保存调用栈上下文关系的能力。具体可以查看下上面github介绍,通过异步监听的方式实现。

再说下traceContextFactory,每次请求都会调用此函数,去获取当前上下文是否已经保存相关的跟踪数据结构,如果存在,则会返回跟踪的数据结构,继续跟踪,如果不存在,则认为是新的请求,重新设置上下文的命名空间,初始化跟踪数据结构,以便后面的调用栈能够获取。

fernandou commented 7 years ago

恩恩,大概意思能明白了,谢谢