在第一次成功查询 heroku postgres table 后,之后的每个查询都失败了

After first successful query to heroku postgres table, every query after fails

这是部署到 Heroku 的服务器端 Web 应用程序(Node.js 和 Express)。我正在使用 Heroku Postgres 附加组件(client 指的是连接到我的 Heroku Postgres 数据库)。

我使用 this 作为参考来构建我的承诺。

第一个 GET 请求成功并且 returns 结果是 client.query('SELECT * FROM passenger WHERE username = ;', [username])。第二个 GET 请求收到内部服务器错误,之后的每个 GET 请求都收到相同的错误。我不知道从哪里开始寻找导致问题的原因?我不确定为什么它会工作一次,然后在同一 GET 请求之后立即失败。

JS 脚本

var express = require('express')
var app = express()
var bodyParser = require("body-parser")
var validator = require('validator')
var { check, validationResult } = require('express-validator')
const router = express.Router()
const data = require('./app.json')
const PORT = process.env.PORT || 5000

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))

var cors = require('cors')
var corsOptions = {
    origin: '*',
    optionsSuccessStatus: 200
}

var connectionString = *censored*;
var { Client } = require('pg')
var client = new Client({
    connectionString: process.env.DATABASE_URL || connectionString,
    ssl:{
        rejectUnauthorized: false
    }
})
client.connect()

app.use('/', router)

router.get('/passenger.json', cors(corsOptions), check('username'), (req, res) => {
    var errors = validationResult(req)
    if (!errors.isEmpty() ||  Object.keys(req.query).length === 0){
        res.json([])
    }

    var username = req.query.username
    username = validator.escape(username)

    client
        .query('SELECT * FROM passenger WHERE username = ;', [username])
        .then(result => res.json(result.rows))
        .catch(e => res.sendStatus(500))
        .then(() => client.end())
})

app.listen(PORT, () => console.log(`Listening on ${ PORT }`))

GET 请求尝试次数:

% curl -X GET "https://agile-dusk-02160.herokuapp.com/passenger.json?username=xIHNcana"
[{"username":"xIHNcana","lat":42.385408,"lng":-71.08689919999999},{"username":"xIHNcana","lat":42.385408,"lng":-71.08689919999999},{"username":"xIHNcana","lat":42.385408,"lng":-71.08689919999999},{"username":"xIHNcana","lat":42.385408,"lng":-71.08689919999999}]%                                         
% curl -X GET "https://agile-dusk-02160.herokuapp.com/passenger.json?username=xIHNcana"
Internal Server Error%  

引用两个 GET 请求的 Heroku 日志:

2020-06-24T22:25:14.123304+00:00 heroku[router]: at=info method=GET path="/passenger.json?username=xIHNcana" host=agile-dusk-02160.herokuapp.com request_id=07eca9c7-aaa2-45fd-a32c-55fe0551e4f6 fwd="73.126.3.226" dyno=web.1 connect=0ms service=20ms status=200 bytes=502 protocol=https
2020-06-24T22:25:15.520949+00:00 heroku[router]: at=info method=GET path="/passenger.json?username=xIHNcana" host=agile-dusk-02160.herokuapp.com request_id=28c34b65-c9cf-439f-901d-51ae220e90bf fwd="73.126.3.226" dyno=web.1 connect=0ms service=3ms status=500 bytes=273 protocol=https

这就是 heroku postgres table 的样子:

agile-????-?????::DATABASE=> select * from passenger;
 username |    lat    |        lng         
----------+-----------+--------------------
 xIHNcana | 42.385408 | -71.08689919999999
 USERNAME |     12.12 |              12.12
 xIHNcana | 42.385408 | -71.08689919999999
 USERNAME |     12.12 |              12.12
 xIHNcana | 42.385408 | -71.08689919999999
 USERNAME |     12.12 |              12.12
 xIHNcana | 42.385408 | -71.08689919999999
 USERNAME |     12.12 |              12.12
(8 rows)

我通过 pg-pool 模块从 Client(单客户端连接)切换到 Pool(连接池),现在可以使用了。来自 here,使用连接池的 node-postgres 笔记最适合处理频繁查询的 Web 应用程序。我认为这些是我第一次尝试的问题:

  • PostgreSQL 服务器只能处理 a limited number of clients at a time。根据您的 PostgreSQL 服务器的可用内存,如果您连接无限数量的客户端,您甚至可能使服务器崩溃。
  • PostgreSQL 只能以先进先出的方式在单个连接的客户端上一次处理一个查询。如果您的多租户 Web 应用程序仅使用一个连接的客户端,则所有同时请求中的所有查询都将被流水线化并串行执行,一个接一个。不好!
var express = require('express')
var app = express()
var bodyParser = require("body-parser")
var validator = require('validator')
var { check, validationResult } = require('express-validator')
const router = express.Router()
const data = require('./app.json')
const PORT = process.env.PORT || 5000

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))

var cors = require('cors')
var corsOptions = {
    origin: '*',
    optionsSuccessStatus: 200
}

var connectionString = *censored*;
const { Pool } = require('pg')
const pool = new Pool({
    connectionString: process.env.DATABASE_URL || connectionString,
    ssl:{
        rejectUnauthorized: false
    }
})
pool.on('error', (err, client) => {
  console.error('Unexpected error on idle client', err)
  process.exit(-1)
})

router.get('/passenger.json', cors(corsOptions), check('username'), (req, res) => {
    var errors = validationResult(req)
    if (!errors.isEmpty() ||  Object.keys(req.query).length === 0){
        res.json([])
        return
    }

    var username = req.query.username
    username = validator.escape(username)

    pool.connect((err, client, done) => {
      if (err) throw err
      client.query('SELECT * FROM passenger WHERE username = ;', [username], (err, result) => {
        done()
        if (err) {
          res.sendStatus(500)
        } else {
          res.json(result.rows)
        }
      })
    })
})