OpenWhisk动作连接MongoDB超时问题排查求助
问题:OpenWhisk动作连接MongoDB超时,本地命令行/Node程序正常运行
在开发机上通过jar包运行OpenWhisk,本地Node程序和MongoDB命令行客户端都能正常连接MongoDB,但执行OpenWhisk动作时出现查询超时错误。
报错信息
执行curl调用动作时返回超时错误:
curl -u $tok "http://172.17.0.1:3233/api/v1/namespaces/_/actions/openwhiskmongo?blocking=true&result=true" -X POST -H "Content-Type: application/json" -d '{"username":"jonboy"}' {"error":{"message":"Operation users.findOne() buffering timed out after 10000ms","name":"MongooseError","stack":"MongooseError: Operation users.findOne() buffering timed out after 10000ms\n at Timeout.<anonymous> (/nodejsAction/hTFYlZze/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js:153:23)\n at listOnTimeout (internal/timers.js:557:17)\n at processTimers (internal/timers.js:500:7)"}}
本地连接验证正常
命令行连接MongoDB成功
mongo mongodb://172.17.0.1 MongoDB shell version v4.4.17 connecting to: mongodb://172.17.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("9777739e-0a81-4ef4-852a-a19a515ac376") } MongoDB server version: 4.4.17 --- The server generated these startup warnings when booting: 2022-11-21T21:32:14.551-05:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem 2022-11-21T21:32:16.601-05:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted --- >
Docker网络配置信息
宿主机docker0网卡配置:
ifconfig docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:efff:fecc:f630 prefixlen 64 scopeid 0x20<link> ether 02:42:ef:cc:f6:30 txqueuelen 0 (Ethernet) RX packets 153 bytes 11410 (11.4 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 278 bytes 7650054 (7.6 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Docker bridge网络详情:
[ { "Name": "bridge", "Id": "441a18a8d66ef7e29aaae1f2d5fee8b5e2f2edf39200b54a91f0df8b17407a46", "Created": "2022-11-19T09:03:56.78026462-05:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "13d0e2d487f03d2c806a917199857eefd77d9fb216eb9c68647ec5d7e93810e0": { "Name": "wsk0_243_prewarm_nodejs14", "EndpointID": "938de84937bfe214486713b4490645145a76f85cbff06f7ac49904beba9d8699", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
OpenWhisk动作代码
openmongowhisk.js
const mongoose = require('mongoose'); async function main(args) { require('./config/database'); require('./models/user'); const User = mongoose.model('User'); const name = args && args.username; var result = 'not initialized'; var user = await User.findOne({username: name}).exec(); if (user) { result = 'found'; } else { result = 'not found'; } return { user: user, result: result }; } exports.main = main;
config/database.js
const mongoose = require('mongoose'); const devConnection = "mongodb://172.17.0.1"; mongoose.connect(devConnection, { useNewUrlParser: true, useUnifiedTopology: true }); mongoose.connection.on('connected', () => { console.log('Database connected'); });
models/user.js
const mongoose = require('mongoose'); const UserSchema = new mongoose.Schema({ id: String, username: String, }); mongoose.model('User', UserSchema);
解决思路
检查MongoDB绑定地址:确认MongoDB配置文件(mongod.conf)中的
bindIp设置为0.0.0.0,而非仅127.0.0.1。如果只绑定localhost,Docker容器无法通过172.17.0.1访问MongoDB服务,修改后重启MongoDB。等待数据库连接建立后执行查询:当前代码中,引入database.js后直接发起查询,但
mongoose.connect是异步操作,可能连接未完成就执行查询导致超时。修改database.js返回连接Promise,在main函数中等待连接成功:// 修改config/database.js const mongoose = require('mongoose'); const devConnection = "mongodb://172.17.0.1"; const connectDB = async () => { try { await mongoose.connect(devConnection, { useNewUrlParser: true, useUnifiedTopology: true }); console.log('Database connected'); } catch (err) { console.error('Database connection failed:', err); throw err; } }; module.exports = connectDB; // 修改openmongowhisk.js的main函数 async function main(args) { const connectDB = require('./config/database'); await connectDB(); // 等待连接建立 require('./models/user'); const User = mongoose.model('User'); const name = args && args.username; var result = 'not initialized'; var user = await User.findOne({username: name}).exec(); if (user) { result = 'found'; } else { result = 'not found'; } return { user: user, result: result }; }增强连接配置参数:在
mongoose.connect中添加超时、重试参数,提升连接稳定性:mongoose.connect(devConnection, { useNewUrlParser: true, useUnifiedTopology: true, connectTimeoutMS: 5000, // 连接超时时间 socketTimeoutMS: 45000, // 套接字超时时间 retryWrites: true, // 重试写操作 retryReads: true // 重试读操作 });测试容器到宿主机的连通性:进入OpenWhisk的Node容器,测试能否访问宿主机的27017端口:
# 进入容器 docker exec -it wsk0_243_prewarm_nodejs14 bash # 测试ping连通性 ping 172.17.0.1 # 测试27017端口是否开放 telnet 172.17.0.1 27017如果不通,检查宿主机防火墙是否拦截了27017端口,或者Docker的icc(容器间通信)配置是否正常。
处理容器复用的连接失效问题:OpenWhisk的预热身容器可能会复用,若数据库连接已断开,需重新连接。在查询前检查连接状态:
async function main(args) { const mongoose = require('mongoose'); const connectDB = require('./config/database'); // 检查连接状态,未连接则重新连接 if (mongoose.connection.readyState !== 1) { await connectDB(); } require('./models/user'); const User = mongoose.model('User'); // 后续查询逻辑... }
内容的提问来源于stack exchange,提问作者Jonboy
相关产品推荐
相关产品推荐

