我在Next.js中开发了一个应用程序。对于后端,我使用了Nextjs中配置的api端点,这些端点位于pages/api
中。api端点经常返回502(网关超时错误)或504(我们的部署有问题)。
经过一些研究,我发现这是因为服务器超时。对于我已经部署Nextjs应用程序的Vercel,无服务器功能的最大超时时间为10秒。
其中一个端点的代码(https://bulkbays.com/api/fetchSections)是
import db from "../../config/db";
import Section from "../../Models/Section";
db();
export default async function handler(req, res) {
console.log('Entered the serverless function')
Section.find()
.lean()
.then((sections) => {
console.log('Fetched Sections',sections)
return res.json(sections);
})
.catch((err) => {
console.log('Error in fetching sessions',err)
return res.json({
status: false,
msg: "An unexpected problem occured",
err,
});
});
}
请有人告诉我怎么会超过10秒。这是最简单的查询。此外,这个查询的结果只是一个长度为9的数组,其中对象是以字符串为值的项。它看起来有点像
[
{
"_id":"6092a55478ccc2092c5e41b0",
"images":["http://res.cloudinary.com/bulkbays97/image/upload/v1620223428/eysvsch2hf4ymajizzcn.jpg","http://res.cloudinary.com/bulkbays97/image/upload/v1620223429/qiwa2idfrntiygsfmnx2.jpg","http://res.cloudinary.com/bulkbays97/image/upload/v1620223429/elwhjk7abwcde7ccqcxf.jpg","http://res.cloudinary.com/bulkbays97/image/upload/v1620223428/yuzhe8iehcyj1rmfyr09.jpg"],
"title":"P-Caps",
"createdAt":"2021-05-05T14:01:56.626Z",
"updatedAt":"2021-05-05T14:01:56.626Z","__v":0
},
....
]
这是发送502或504响应的请求之一的日志
[GET] /api/fetchSections
14:36:34:38
Status:-1
Duration:10010.32 ms
Init Duration: N/A
Memory Used:60 MB
ID:x7lh8-1620552994128-a44f049a01ae
User Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
2021-05-09T09:36:44.511Z 62c16977-9c5c-42f5-961f-a63083638a9c Task timed out after 10.01 seconds
请指导我。我该怎么办?我应该使用类似Heroku(而不是无服务器)的东西吗?
我为一个客户制作了这个网站,现在我不知道是什么问题导致了这个问题。
将Vercel与Hobby plan
一起使用时,只能为5 seconds
处理无服务器API路由。这意味着5秒后,路由将以504 GATEWAY TIMEOUT
错误进行响应。
要解决此问题,您需要减少API路由响应所需的时间,或升级您的Vercel计划。
我遇到了同样的问题
任务在 10.01秒后超时
使用Next.js API端点连接到MongoDB(图集)。对我来说,根本原因实际上是MongoDB中的网络访问被设置为我自己的IP地址,因此在我部署的应用程序中被禁止。对于那些在使用Next.js函数时遇到同样问题的人,还请检查MongoDB是否正确配置为接受来自您自己IP以外的IP地址的连接。
上下文见下文:
注意:Vercel使用动态IP地址,因此您需要添加一个例外,以便从MongoDB Atlas面板中的任何IP地址进行访问。要简化此操作,请导航到"网络访问"选项卡,单击"添加IP地址"按钮,然后单击"允许从任何位置访问"按钮,或者输入0.0.0/0作为"访问列表条目"。
首先尝试隔离问题的来源,这样您就知道接下来要采取什么步骤。
例如,尝试在不使用或不连接数据库的情况下返回一些伪数据。
export default async function handler(req, res) {
console.log('Entered the serverless function')
return { "dummy": "data"}
}
如果你仍然有超时问题,你现在知道这可能是因为你的Vercel NextJS设置。
如果你的NextJS设置不是问题所在,那么你就知道问题是由你的数据库引起的。问题可能出在查询本身,也可能出在连接中。
我不确定您使用的是什么DB(从语法上看,我认为是MongoDB)。
最可能的解决方案:
db()
做什么或是什么还不太清楚。我认为它处理与MongoDB实例的连接。无论哪种方式,请确保检查db()
函数是否异步。这是一个常见的错误;如果函数是异步的,并且您没有正确调用它,那么超时可能是由这个异步问题引起的- 您是为每个请求创建新的连接,还是重用现有的打开连接?每次创建一个新的连接可能代价高昂;这可能就是导致超时问题的原因
如果这些都不起作用,请尝试以下操作:
- 您的数据库是如何托管的?它是由Vercel管理的吗?请尝试使用另一个管理器来查看问题是否存在
- Vercel仪表板中的所有设置是否正确?确保您有正确的MongoDB连接字符串,并且您的MongoDB实例已设置为接受来自应用程序的连接
经过不断的研究,我在Heroku上发布了API,在Vercel上发布了前端。我在stackoverflow的一篇帖子中读到了一个家伙的建议,他说他在Vercel工作,这是最合适的解决方案。
我认为这是无服务器体系结构本身的问题。我尝试在netlify上部署Nextjs,但遇到了类似的情况。
我也遇到了同样的问题,这是由下一次身份验证引起的(在我的情况下)。所以问题出在4.15.0
之上的te版本上。我将next-auth
版本设置为4.15.0
,它为我解决了问题。希望它能为某人节省一些时间。
我刚刚也遇到了这个问题,并设法解决了它
我使用getStaticProps&getStaticPaths在我的页面组件中,该组件在开发中运行良好,但当我尝试在生产中部署时,出现了无效的json响应主体错误。
结果发现getStaticProps&getStaticPaths函数没有建立到我的MongoDB的连接,因此返回未定义导致应用程序崩溃。
解决方案:
我通过直接连接到我的MongoDB并从getStaticProps&getStaticPaths函数。
希望这能帮助到别人。
我遇到了同样的问题:
npm run build
在终端,它为我工作。
我在typegraphql-api和mongodb atlas设置中遇到了类似的问题。首先,如果有人在为vercel的配置而挣扎,我会粘贴我的vercel.json
{
"version": 2,
"builds": [
{
"src": "build/server.js",
"use": "@vercel/node",
"config": {
"includeFiles": [
"build/**"
]
}
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/build/server.js"
}
]
}
就我而言,我有一个顺序问题。我所要做的就是改变顺序。首先等待mongo连接,然后等待服务器
import { ApolloServer } from '@apollo/server'
import { expressMiddleware } from '@apollo/server/express4'
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'
import express from 'express'
import http from 'http'
import cors from 'cors'
import bodyParser from 'body-parser'
import { getSchema } from './schema'
// import geoip from 'geoip-lite'
import MobileDetect from 'mobile-detect'
import dotenv from 'dotenv'
import { Context } from './types/context'
import { connectToMongo } from './mongo'
import { getUserFromRequest } from './utils/token'
dotenv.config()
const graphQlPath = process.env.GRAPHQL_PATH
//TODO: check i18next-fs-backend
async function startApolloServer() {
// Required logic for integrating with Express
const app = express()
// Our httpServer handles incoming requests to our Express app.
// Below, we tell Apollo Server to "drain" this httpServer,
// enabling our servers to shut down gracefully.
const httpServer = http.createServer(app)
// Same ApolloServer initialization as before, plus the drain plugin
// for our httpServer.
const schema = await getSchema()
const server = new ApolloServer({
schema,
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
],
introspection: true,
})
await server.start()
app.use(
graphQlPath,
cors({
origin: '*',
}),
bodyParser.json(),
expressMiddleware(server, {
context: async ({ req }) => {
const ip = (req.headers['x-forwarded-for'] || req.socket.remoteAddress) as string
const user = getUserFromRequest(req)
const context: Context = {
req,
user,
ip,
// location: geoip.lookup(ip),
location: null,
md: new MobileDetect(req.headers['user-agent']),
}
return context
},
}),
)
await connectToMongo()
const port = process.env.PORT || 4000
await new Promise<void>((resolve) => httpServer.listen({ port }, resolve))
console.log(`🚀 Server ready at http://localhost:${port}/`)
}
startApolloServer().catch((e) => console.log('cannot start server', e))
我面临的另一个问题是geoap lite,所以我只是评论了它的用法。
对我来说,我没有正确发送响应。
错误:
return res.status(200);
正确:
res.status(200).send("");