Egg: 请求超时

Created on 20 Oct 2017  ·  34Comments  ·  Source: eggjs/egg

这是一个简单的接口 长时间 没有给任何响应

// home.js
index(ctx) {
      let promise = new Promise((resoule, reject)=>{
        if(false){
          resoule({
              status: true
          })
        }
      });
      console.log(new Date());
      let result = yield promise.then((res) => {
        return res;
      }).catch((err) => {return err});
      this.ctx.body = {
        hello: 'world',
          result,
          now: new Date()
      };
    }

```javascript
// router.js
app.get('/home', 'home.index');

`http://127.0.0.1:8001/home`
```javascript
// 控制输出
2017-10-20T10:17:20.832Z
2017-10-20T10:19:20.841Z
2017-10-20T10:21:26.416Z
// 大概是两分钟 执行一次 index 接口

image

如果我的接口 一直都没有给任何的响应;这岂不是一个闭环的死循环;或者 如何配置 设置接口响应时间

Most helpful comment

😃本地debug时,请求重试的情况被我复现了一次,就是编辑代码 -> 保存 -> 服务还未完全启动,就发送了请求。
现在支持配置超时时间了,棒棒哒💯

const config = {
    serverTimeout: 5000,
}

All 34 comments

你可以在 nginx 设,一般 socket 也有超时时间。

或者自己 promise.race 一个 timeout

发自我的 iPhone

在 2017年10月20日,18:47,Haoliang Gao notifications@github.com 写道:

你可以在 nginx 设,一般 socket 也有超时时间。


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

和 promise.race 应该是没有关系的 console.log();提前 效果依然

index(ctx) {
      console.log(new Date());
      let promise = new Promise((resoule, reject)=>{
        if(false){
          resoule({
              status: true
          })
        }
      });
      let result = yield promise.then((res) => {
        return res;
      }).catch((err) => {return err});
      this.ctx.body = {
        hello: 'world',
          result,
          now: new Date()
      };
    }

就是一个简单的 get 请求 ; 用浏览器打开即可;我没有用fetch 也没有用 ajax

不知道你要干嘛,这个代码就是有 bug 的

就这么几行代码, 一直请求 但是不给响应结果!2 分钟后 这个index 函数会在执行一次! 我现在项目中就有这么一个接口,非常耗时间;200M的文件 2分钟是下载不完的;结果两分钟没有响应 会再次运行,导致一个闭环的死循环

@popomore 我是故意写成这样的 不是bug

那也和 server 没关系吧,再次请求也是浏览器吧。你 curl 看看

这种文件用 cdn 会比较好,自己玩的话也是 nginx 托管,然后 302 到那个路径。

image

重点不是cdn啊,什么的! 重点是 如果我的接口2分钟没有跑完,结果又执行了一次;再执行还是2分钟跑不完;它还会重新执行; 这不就是一个死循环吗!我的一个接口 就非常的耗时间,是需要下载上传文件的,文件比较大 @popomore

那也和 server 没关系吧,再次请求也是浏览器吧。你 curl 看看

https://github.com/eggjs/egg/issues/1553#issuecomment-338177264

这是你的代码设计问题,框架层面不会去主动超时的,因为超时后的处理逻辑是不确定的,有些只需要简单的返回一个错误信息,有些却需要去本地缓存拿个信息回复出去。

你的 Api 应该自己处理超时问题,就像我说的 Promise.race([ apiPromise, timeoutPromise]),自行处理。

至于 @popomore 说的上传 cdn,指的是,这类的场景,你应该上传到 CDN 去,这是最佳实践。

我就是简单描述一下 我目前遇到的问题;设置时间为 123000 就是为了大于 2分钟
@atian25

index(ctx) {
      console.log(new Date());
      let p1= new Promise((resoule, reject)=>{
        setTimeout(() => {
            resoule({
                now: new Date()
            });
        },123000);
      });
      let result = yield p1.then((res) => {
        return res;
      }).catch((err) => {
        return err;
      });

      console.log(result);
      ctx.body = {
        hello: 'world',
          result,
          now: new Date()
      };
    }

关于API 超时问题 我还是没有找到 相关的配置

然后? 你期望框架在超过 2 分钟后自动中断这次请求?

不期望中断啊! 2分钟 我的代码还没有跑完呢! 结果这个 这个API 会重新再跑一遍,可能我的代码跑完需要一个十分钟左右或者更长; 2分钟没有跑完 又跑了一遍,同样在跑一边 还是2分钟跑不完 ;没有给浏览器任何响应 就这么一直死循环下去

@atian25 您明白我的意思了吗 @popomore 好像不明白我的意思

那你为什么在前端请求的时候,不等待上一个请求的返回呢?

本来 HTTP 的模型,就是一来一回的,怎么可能有中间的状态返回。

你这么激动,很难继续交流的。

我没有发送第二次 请求 是服务器端 主动运行第二次的;浏览器端 也没有第二次 发请求 就发送一次请求

image
这个图片应该能说明一点问题吧!就是 前端请求就发送一次

服务器哪里来的第二次?哪段代码触发的?你试试 curl 或 postman,不要用浏览器访问,排查浏览器插件原因。

这样挤牙膏似的交流,效率很低。你还是用 egg-init 准备一个最小化的可复现代码,提交仓库上来,我们再继续交流吧。

稍等

git地址: https://github.com/YAO-JSON/egg-example.git 然后浏览器打开:http://127.0.0.1:7001/ 等两分钟后看一下 控制台打印的时间 @atian25

image
无法复现,你试试 curl 或 postman,不要用浏览器访问,排查浏览器插件原因。

您等一会啊!你等待要超过两分钟的!返回结果应该是 hi,egg 啊;
我最初的请求 就是postman 将postman 的timeout 设置为2000000ms;结果是一样的;

'use strict';

module.exports = app => {
  class HomeController extends app.Controller {
    * index() {
        console.log(new Date());
        let p1= new Promise((resoule, reject)=>{
            setTimeout(() => {
                resoule({
                    now: new Date()
                });
            },1230000);
          });
          let result = yield p1.then((res) => {
            return res;
          }).catch((err) => {
            return err;
          });
      this.ctx.body = 'hi, egg';
    }
  }
  return HomeController;
};

1508504840610

postman 还是无法复现。

image

跟等不等超时没有任何关系的,HTTP 的请求就是一来一回,egg 这块不可能做任何重试的。

@Yao-JSON 超时重试跟框架没有关系,这是HTTP1.1的规范,浏览器实现了这个规范,所以你用浏览器请求就会超时重试。

If an HTTP/1.1 client sends a request which includes a request body, but which does not include an Expect request-header field with the "100-continue" expectation, and if the client is not directly connected to an HTTP/1.1 origin server, and if the client sees the connection close before receiving any status from the server, the client SHOULD retry the request.

你这个Promise 调用对么yield promise.then
。如果可以的话,建一个独立的demo测试一下你的写法

这个是nodejs的问题,代码在这里,解决方法是获取server实例后,调用setTimeout方法设置超时时间。参考链接

这真是一个大问题,我今天也遇到了,超过2分钟页面就无响应,后台会继续执行。
请问egg再哪里获取实例?
我参照https://eggjs.org/zh-cn/basics/objects.html
在app.js中添加以下代码,没有效果。然后2分钟就超时~~~
app.once('server', server => {
server.setTimeout(600000); // 10分钟超时 Default: 120000 (2 minutes)
});

你确定这段代码执行了么? app.js 是在根目录的。
要在本地测试看看先,线上还有 nginx 等也可能会拦截

确定是执行了的~~就是本地 npm run dev 测试的

😃本地debug时,请求重试的情况被我复现了一次,就是编辑代码 -> 保存 -> 服务还未完全启动,就发送了请求。
现在支持配置超时时间了,棒棒哒💯

const config = {
    serverTimeout: 5000,
}
Was this page helpful?
0 / 5 - 0 ratings