在 prisma deploy 上出现内部服务器错误

Posted

技术标签:

【中文标题】在 prisma deploy 上出现内部服务器错误【英文标题】:Getting Internal Server Error on prisma deploy 【发布时间】:2019-11-16 19:38:41 【问题描述】:

我在 Heroku 上有一个 Postgres 数据库,在通过执行 prisma deploy 部署数据模型时,经常会产生以下错误。

ERROR: Whoops. Looks like an internal server error. Search your server logs for request ID: local:cjxrmcnpx00hq0692zuwttqwv


 "data": 
   "addProject": null
 ,
 "errors": [
   
     "message": "Whoops. Looks like an internal server error. Search your server logs for request ID: local:cjxrmcnpx00hq0692zuwttqwv",
     "path": [
       "addProject"
     ],
     "locations": [
       
         "line": 2,
         "column": 9
       
     ],
     "requestId": "local:cjxrmcnpx00hq0692zuwttqwv"
   
 ],
 "status": 200

在检查 Docker 日志时,我看到了这个错误:

Jul 14, 2019 12:18:34 PM org.postgresql.Driver connect
prisma_1  | SEVERE: Connection error: 
prisma_1  | org.postgresql.util.PSQLException: FATAL: too many connections for role "bcueventxumaik"  
prisma_1  |     at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2433)
prisma_1  |     at org.postgresql.core.v3.QueryExecutorImpl.readStartupMessages(QueryExecutorImpl.java:2566)
prisma_1  |     at org.postgresql.core.v3.QueryExecutorImpl.<init>(QueryExecutorImpl.java:131)        
prisma_1  |     at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:210)
prisma_1  |     at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
prisma_1  |     at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
prisma_1  |     at org.postgresql.Driver.makeConnection(Driver.java:452)
prisma_1  |     at org.postgresql.Driver.connect(Driver.java:254)
prisma_1  |     at slick.jdbc.DriverDataSource.getConnection(DriverDataSource.scala:101)
prisma_1  |     at slick.jdbc.DataSourceJdbcDataSource.createConnection(JdbcDataSource.scala:68)      
prisma_1  |     at slick.jdbc.JdbcBackend$BaseSession.<init>(JdbcBackend.scala:453)
prisma_1  |     at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:46)
prisma_1  |     at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:37)
prisma_1  |     at slick.basic.BasicBackend$DatabaseDef.acquireSession(BasicBackend.scala:249)        
prisma_1  |     at slick.basic.BasicBackend$DatabaseDef.acquireSession$(BasicBackend.scala:248)       
prisma_1  |     at slick.jdbc.JdbcBackend$DatabaseDef.acquireSession(JdbcBackend.scala:37)
prisma_1  |     at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:274)
prisma_1  |     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)    
prisma_1  |     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)    
prisma_1  |     at java.lang.Thread.run(Thread.java:748)
prisma_1  |
prisma_1  | Exception in thread "main" org.postgresql.util.PSQLException: FATAL: too many connections 
prisma_1  |     at org.postgresql.core.v3.QueryExecutorImpl.readStartupMessages(QueryExecutorImpl.java:2566)prisma_1  |     at org.postgresql.core.v3.QueryExecutorImpl.<init>(QueryExecutorImpl.java:131)prisma_1  |     at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:210)
prisma_1  |     at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)prisma_1  |     at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
prisma_1  |     at org.postgresql.Driver.makeConnection(Driver.java:452)
prisma_1  |     at org.postgresql.Driver.connect(Driver.java:254)prisma_1  |     at slick.jdbc.DriverDataSource.getConnection(DriverDataSource.scala:101)
prisma_1  |     at slick.jdbc.DataSourceJdbcDataSource.createConnection(JdbcDataSource.scala:68)
prisma_1  |     at slick.jdbc.JdbcBackend$BaseSession.<init>(JdbcBackend.scala:453)
prisma_1  |     at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:46)
prisma_1  |     at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:37)
prisma_1  |     at slick.basic.BasicBackend$DatabaseDef.acquireSession(BasicBackend.scala:249)
prisma_1  |     at slick.basic.BasicBackend$DatabaseDef.acquireSession$(BasicBackend.scala:248)
prisma_1  |     at slick.jdbc.JdbcBackend$DatabaseDef.acquireSession(JdbcBackend.scala:37)
prisma_1  |     at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:274)
prisma_1  |     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
prisma_1  |     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
prisma_1  |     at java.lang.Thread.run(Thread.java:748)
prisma_prisma_1 exited with code 1

错误是说连接太多,但我只从一个终端触发prisma deploy,同时我能够使用 PgAdmin4 连接到数据库。此外,数据库似乎完全可以访问,因为我可以从容器内部 ping 数据库。

附言。在运行 docker logs -f processid 时更新了 docker 日志,我得到了较旧的日志,但现在再次使用 docker-compose up 构建容器时,我得到了最新的日志

【问题讨论】:

你能ping通ec2-54-228-246-214.eu-west-1.compute.amazonaws.com吗? 我可以从 Docker 容器内部 ping。当下次 prisma 部署不起作用时,我会复制相同的内容。 @arnonuem 是的,当prisma deploy 卡住并随后抛出内部服务器错误时,我可以从 docker 容器内部 ping ec2-54-228-246-214.eu-west-1.compute.amazonaws.com 日志文件清楚的说连接太多了。 但同时,我可以从 PgAdmin 和终端进行连接,我一次只能建立一个连接。 【参考方案1】:

由于错误清楚地表明与数据库的连接太多。所以我们需要调查有多少连接,谁在创建它们以及为什么创建它们。为了限制消费者或增加可用连接的数量。

首先我们可以使用 heroku CLI 检查已使用和可用连接的数量:

$ heroku pg:info

=== DATABASE_URL
Plan:                  Private 2
Status:                Available
HA Status:             Available
Data Size:             2.23 GB
Tables:                83
PG Version:            10.1
Connections:           26/400
Connection Pooling:    Available

有关如何调查 heroku postgres 数据库的更多信息,请参阅:https://devcenter.heroku.com/articles/heroku-postgresql#pg-info

要进一步调查谁连接到您的数据库,您可以使用 psql 或 pgAdmin。如果使用 pgAdmin,您可以选择数据库,单击仪表板选项卡并选择页面底部的服务器活动面板,显示所有连接的会话。如果使用 psql 你可以写一个这样的选择:

SELECT pid as process_id, 
       usename as username, 
       datname as database_name, 
       client_addr as client_address, 
       application_name,
       backend_start,
       state,
  FROM pg_stat_activity;

更详细的查看方法:https://dataedo.com/kb/query/postgresql/list-database-sessions

现在您可能已经确定了谁在创建与您的数据库的连接,并且可以限制客户端使用更少(或增加可用数据库连接的数量)。

一个可能的数据库连接消费者当然是 prisma 服务器本身。幸运的是,prisma 配置提供了一个限制数据库连接的设置。

PRISMA_CONFIG 中的 connectionLimit 属性决定了 Prisma 服务将使用的数据库连接。

您可以在这里阅读更多信息:https://www.prisma.io/docs/prisma-server/database-connector-POSTGRES-jgfr/#managing-database-connections

如果您使用 heroku 与您的 prisma 服务器一起运行 docker 容器,那么 PRISMA_CONFIG 可能如下所示:

port: $PORT
managementApiSecret: $PRISMA_MANAGEMENT_API_SECRET
databases:
  default:
    connector: postgres
    migrations: true
    connectionLimit: 2
    uri: $DATABASE_URL?ssl=1  

我希望这种结构化的方法有所帮助。如果您需要更多说明,请告诉我。如果是这样,请提供有关现有数据库连接性质的详细信息。

【讨论】:

抱歉,差不多两周后才回来,但在 Heroku 中,我从未达到最大连接数限制,我检查了来自 PgAdmin 的连接,只有 PgAdmin 和 Prisma 连接到数据库。此外,在过去的几个月里,我注意到当一个数据库使用了一定时间时,Prisma 会抛出这个错误,因为到目前为止我已经因为 Prisma 而销毁了 3 个数据库。【参考方案2】:

运行这个命令

docker logs <YOUR_PRISMA_CONTAINER_NAME>

【讨论】:

以上是关于在 prisma deploy 上出现内部服务器错误的主要内容,如果未能解决你的问题,请参考以下文章

Prisma deploy - 本地部署的身份验证错误

Prisma 的编译器错误

无法运行 prisma deploy:错误:未定义的集群不存在

生成 Prisma Graphql Schema 时使用 generate 和 post deploy 钩子之间的区别?

postgreSQL 的 prisma deploy 命令

prisma deploy --env-file variables.env 抛出错误