现在的项目是用nodejs开发了手游的服务端,数据库用的是mysql,目前还在开发阶段,访问量很少,就自己人测试访问下。 但是发现问题是有时候就4-5个人或者更多一点的访问的时候会出现等待,基本上就要等到nginx断开再重连了,或者这个时候重启一下nodejs,再连马上就能连上。我开始怀疑是nodejs阻塞造成的,于是我在服务器上用PM2多开了几个进程,maxSockets也设置到100了,但是发现还是会出现这种问题,我现在就不知道是什么原因造成了的,这问题也不知道怎么查?从哪下手查,刚接触nodejs没多久。 PS:开始以为是数据库的问题,但是我测试了当我服务器连不上的时候,我马上运行我本地代码,连接数据库又是正常的,就不知道什么原因了。 刚接触nodejs不久,还望给位帮忙分析分析,该怎么处理。 另外,我人在上海,忘各位帮帮帮,要是在上海的帮解决了我愿请各位吃个饭什么的都行。外地的实在不行发个红包也行。 这问题真是搞了一个多月了 还不知道怎么弄。 再次谢过!
@klesh 我在底层用了2种连接池,一个是mysql中间件,这个我好像没有看到哪里可以设置连接池大小,还有一个是generic-pool,这个max我设置的是60。但是当出现连接不上服务器的时候,我在mysql里面show processlist,当前连接都还没达到60啊,而且我个人理解连接池就算占满了,当有新的连接进来的时候,会从新从数据库里初始化一个连接,网上查了这个初始化有点耗时和耗资源,但是也不应该出现连接不上的情况啊。
怎么会用到2种连接池?mysql中间件是怎么说?没道理mysql还要挂载到 app 上面去啊?是指连接库吧?你要确认连接池一个就够了!如果是2个池,下面的池假定是5,上面的池是60,当在外面取第6个时,上面的池就会去问下面的池要,下面的池没有了就会一直卡住。池是进去了连接就被存在池里面不会释放,有人要的时候直接返回连接。总之不能搞2个池,只会将情况复杂化!
池的意思是达到上限了就排队,不是不够用了还会新建连接,你的理解完全错误,那样叫溢出了,真正是错误的行为!
@klesh 我说错了,mysql这个是连接库。还有一个是generic-pool,这个也是一个连接库。那这里我有一个疑问:假如我数据库允许的最大连接数(A)是100,连接池的最大数量是B,那我是不是应该让B=A,如果B<A的,假如B=90,那是不是就会有10个连接永远都用不到呢。 还有,池的作用不应该是连接用完就放回池里,连接在池里闲置是有时间限制的,超过这个时间,这个连接就会被数据库回收掉。当一个新的连接上了的时候,先从池里拿,如果有那么就直接拿来用,如果池里没有,那么才在数据库里去拿。 不知道我理解的对不对,因为我这也是在网上查的。
@imhered 没错,你这次讲得对,但是占满了是不会再建新的链接的,要等池里某个链接释放了!你仔细看你这段话,跟你之前讲的占满了就建新的连接是没有冲突的。两回事。
dbConfigArray 是什么样的?console.log 输出一下?
@klesh 就是数据库连接字符串 'host’: 'xxxxx’, 'user’: 'root’, 'password’: 'password’, 'database’: 'database’, 'charset’: ‘utf8’
@MiguelValentine 和return应该没关系吧,我写return是因为 我在if里面callback之后,后面没有写else,所有在这个callback的时候加了return 不让走后面的代码
@MiguelValentine Holy xxxx! 咱别泛酸,你说说:
return callback(err, results);
和
callback(err, results);
return;
这两句,除开返回结果不说,在 执行 顺序上会有任何不同吗?然而第一种不是更简洁明了吗?
@klesh 对,是这样的。因为这里是最终操作数据库里嘛,所有不管它是有没有error都给返回,所以return callback写在了if(error)的外面,而里面只是做一个错误记录,而return callback后面没有代码了,就只剩下几个括号了。
一个进程最多支持5个Sockets?听起来更像是浏览器。然后应该是代码问题,先别测试太过具体的业务代码,直接弄几个比较简单例子来测试,比如插入数据库或查询,mysql我之前有测试过,用node.js连接操作,并发50每秒执行200-400才比较正常
@wldlzt 对,因为我查了下文档,nodejs 0.12之前的版本,默认就是5个,就是http请求。 http.globalAgent.maxSockets 就是这个限制了的,好像从0.12以后的版本这个值就是无穷大了。
照你说的,createPool都没指定池大小啊?connectionLimit 就是池大小,你试下改这个参数,看看情况是不是有所改变,若是的话说明有哪处地方没有 release connection 了。
@MiguelValentine 和谐和谐嘛,都是为了帮我,谢谢了。 应该是这个问题了,因为我没配置connectionLimit 这个值,查了下官方文档默认是10. 连接超过这个值,多余的就会排队等待到有空闲的连接出来。
@imhered 问题的根源应该还不是这里,你这玩意貌似还在开发中吧,照理不应该有那么长时间的数据库操作。应该还是哪里没有 release connection,这个必须排查清楚,否则即使你把它设到10000000还是有用完的时候,connection 不被 release 会一直占着池而且不会关闭,池满了你的程序也就到头了。
@MiguelValentine 我觉得你真是奇怪,为什么会突然觉得你是传道者而我就成了小孩了。顾左右而言它,视问题而不答你不去搞政治实在太可惜了。程序执行是很简单的东西,是按什么顺序这个更是基础中的基本,莫说你年纪不太可能大过于我,就这种程度的讨论最多只能说是切磋,尚且不至于由你来教我。
@klesh 这个倒也有可能,但是我操作数据库的底层函数就那么几个,全都release了的,还有就是放个周末什么的时候,也就是过几天没人连接数据库的时候,我show processlist命令的时候,是没有连接的,那说明连接都是release了的。 我再仔细查查。
@klesh 找了半天,确实有一个地方没有release,但是我这里用的事物,请教下我是应该在AB位置分别release(感觉有点不对),还是在C里面rollback或者commint后面release呢。 代码截图,其中118行的conn就是从连接池中获取的。