有办法将一个函数变成非阻塞的么?利用child_process之类的,比如这段代码在koa
发布于 3天前 作者 hwoarangzk 279 次浏览 来自 问答
var app = require('koa')();
app.use(function *(next) {
    var result = compiled(data);
    this.body = result;
});
app.listen(8080);

这里compiled是一个模板编译函数,是同步的。可能发生的情况是,data或者html有问题,导致compiled执行的时候发生死循环,这样整个服务会导致cpu100%然后挂掉,后续请求无法进行。 我在想是否有一种方法可以让compiled变成非阻塞的?这样就算compiled某一个请求死循环的时候,至少保证cpu不会100%,后续的请求不会阻塞。理论上是否有可行的方法?是不是要修改底层的东西才能实现?还有一个关键问题是,this.body不能在一个异步回调的函数里来赋值

38 回复

修改compiled

@hezedu 具体如何修改呢?我是想知道用什么样的机制?

process_trick好像可以吧 自豪地采用 CNodeJS ionic

应该可以预编译吧。没有的话,自己写一下,也造福后人

process_trick?我去百度下 预编译是指要写c++么。。。

@hwoarangzk node的一个函数 说错了 是process.nextTick() 自豪地采用 CNodeJS ionic

刚刚发现我之前说的有点错就删掉了 但是你这样把compiled变成异步了 this.body就更不可能赋值了

@wenshiqi0 是啊,在异步函数里给this.body赋值没用的,但我又想实现异步模板渲染后给this.body,感觉貌似做不到,this.body总归要等待渲染结果的

本来我想的是把compiled弄成yieldable的样子,类似this.body = yield compiled(data),但这里还是会等待

@hwoarangzk 把异步方法用generator来管理异步流程就可以了 koa内部是用这个来管理的 你最好不要使用callback了 用promise和generator把它平展开 自豪地采用 CNodeJS ionic

@hwoarangzk 你这里是不能不等待的 因为koa内部会调用res.end() 它不会等你的 自豪地采用 CNodeJS ionic

对啊,我想到平展开就是把compiled变成yieldable的样子,但是总归还是要等待

难道没有什么方法可以么?底层一点的东西呢?

@hwoarangzk 我做的东西和你差不多 但是我的模板是用的swig 目前我没有觉得有什么问题 你的compiler如果是要动态提供才会想你这样可能出错 那也就只能看看用超时了 自豪地采用 CNodeJS ionic

超时是怎么弄?koa-timeout?

@hwoarangzk 直接对你的绘画函数使用settimeout 这个也会把你的绘画函数变成异步 但是超时之后func如果函数没有执行就会返回回来 自豪地采用 CNodeJS ionic

@wenshiqi0 但是超时之后func如果函数没有执行就会返回回来 这句话没明白,跟this.body赋值有什么关系?

这样可以有一个可以错误处理的机会 如果你的模板渲染的有问题 可以给它body赋值一个错误代码 自豪地采用 CNodeJS ionic

    app.use(function *(next) {
        var self = this;
        setTimeout(function() {
            self.body = compiled(data);
        }, 1000);
    });

你是说像这样么?

不是这样 我的表述好像不太对 settimeout是延迟异步执行这个函数 你可以这个函数来抛出错误 自豪地采用 CNodeJS ionic

我刚刚去看了看书 重新看看这个timeout函数 自豪地采用 CNodeJS ionic

还是不大明白你说的setTimeout和抛出错误的意义? 你是想类似:

app.use(function *(next) {
        var self = this;
        setTimeout(function() {
            self.throw(408, 'timeout');
        }, 1000);
        this.body = compiled(data);
    });

这样吗?如果超时,我至少可以抛出错误,能够处理?

我的想法是这样的 你的compile为什么会出现这种错呢 自豪地采用 CNodeJS ionic

compile是个开源组件的东西,可能内部有bug吧,刚好发现了 但是这个setTimeout是没用的 如果compiled死循环了,setTimeout永远执行不到的 是个难题 - -!

我也在想想 自豪地采用 CNodeJS ionic

我估计不动c++层面的东西很难搞定,我还不确定理论上能不能做到

先让我把我的md写好就来考虑 好歹我也是用的这一套 说不定也会遇到 自豪地采用 CNodeJS ionic

你试过koa-timeout嘛

koa-timeout不能解决这个问题,它还是setTimeout来搞的

如果是死循环 有点无解。

除非。

对node而言,回调内部的硬性CPU运算消耗是无法避免的,如果你有资源,可以做成远程调用,让别人帮你算,算完之后传给你。就你提出的具体问题,我觉得你还是想办法把死循环原因找出来,消灭掉,这个是程序错误造成的,而非真实的计算消耗。我说的办法是真实的计算消耗,可以异步远程调用(可以是其他CPU,或者是其他计算机)。

@coordcn 嗯,错误原因是找到了也修改了,但我想在cpu100之前做一些措施预防掉,而不是等出现错误后再补救。感觉我这种情况对于单线程的js来说有点难搞,很难实现的样子

我觉着单线程是硬伤,如果是死循环,在自己的进程里,神仙也救不活。 可以考虑使用cluster模块用另一个思路解决吧,这个 100%的worker让他自己去死就行了,死了以后master可以自动再启动一个worker,其他worker 会继续处理其他请求。

@superobin 我是用cluster来启动我的服务的,只是对于某一个单独的请求死循环了而且让cpu100了,怎么样能补救,而且有办法判断某一个cluster死掉了么?

启动child progress执行compile函数,再设置个定时器,child progress Xms没退出就kill掉,退出即响应结果。还是要改掉cpu100的碧油鸡。

@zlbbq child progress是啥?那什么时候给 this.body赋值呢?

回到顶部