prisma使用mongodb副本集群报错引发的一些列问题
-
前提:因为prisma对于增删改有事务,所以必须使用mongdb副本集群
- 详细参考官方:https://www.prisma.io/docs/concepts/database-connectors/mongodb#troubleshooting
-
错误描述
None of the available servers suitable for criteria Predicate. Topology: { Type: Unknown, Servers: [ { Address: localhost:27017, Type: RsGhost, Average RTT: 346.567µs, Last Update Time: DateTime(2022-02-16T20:00:59.552Z), Max Wire Version: 9, Min Wire Version: 0 }, ] }
错误描述很清楚Address: localhost:27017,没有找到合适可用的服务
-
.env文件
DATABASE_URL="mongodb://自己的云服务器ip地址:27018/test?authSource=admin&retryWrites=true&w=majority"
-
schema.prisma
datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" }
一切都很平平无奇,下面进行排查流程,此处不做如何搭建mongodb副本集群的教程,可以百度,上面有很多教程
思考1:db url字段
- 很显然,我的肯定是没问题,用一些gui 可视化mongodb连接工具即可
思考2:mongodb副本集群host字段不能为localhost或127.0.0.1
-
查看错误信息,如果是副本集群报错应该是多个数组(这里拿的是别人的错误,所以只有一个)
Topology: { Type: Unknown, Servers: [ { Address: localhost:27017, Type: RsGhost, Average RTT: 346.567µs, Last Update Time: DateTime(2022-02-16T20:00:59.552Z), Max Wire Version: 9, Min Wire Version: 0 }, ] }
-
可以看到
address
字段为localhost:port形式,那么,会不会因为prisma会向mongodb副本集群获取rs.config()
然后再根据配置的host
进行连接? -
这里直接告诉结论:是的,prisma就是这样做的
-
首先查看自己的配置信息,进入mongo/mongosh,
rs.config()
可以发现你配置的所有副本集群信息 -
对
host: localhost
进行修改// 进入主机节点,比如27017是主节点 mongo/mongosh localhost:27017 config = rs.config(); // 打印config信息 members: [ { _id: 1, host: 'localhost:27017', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 1, tags: {}, secondaryDelaySecs: Long("0"), votes: 1 }, { _id: 2, host: 'localhost:27018', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 1, tags: {}, secondaryDelaySecs: Long("0"), votes: 1 } ], // 因为使用了对host都是localhost, 所以直接修改配置文件会报错:Either all host names in a replica set configuration must be localhost references, or none must be; found 1 out of 2. // 意思就是,所有副本集的host配置要么是localhost要么都不是localhost // 移除副本节点 rs.remove('loclhost:27018'); // 修改配置 reconfig = rs.config().members[0].host = 'ip:port'; // 要么修改成ip:端口,也可以用域名代替 rs.reconfig(reconfig); // 查看是否修改成功 rs.config(); // 添加子节点 rs.add('ip:port'); // 或域名:端口 // 查看是否修改成功 rs.config(); // 查看状态 rs.status();
-
-
最后验证
-
npx prisma studio:进去后不报错就是ok
-
跑一个查询代码
import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function main() { await prisma.$connect(); const allUsers = await prisma.user.findMany(); console.log(allUsers); } main() .catch((e) => { console.log(e); }) .finally(async () => { await prisma.$disconnect(); });
结果不管怎样,只要没报错就是ok的
-
使用docker-compose部署
贴上一个简单实用keyFile集群成员认证 + 客户端账号密码认证的1主2从副本集群攻略
日期:2022-07-31
- 运行之前需要生成一个KeyFile
openssl rand -base64 756 > /data/mongodb.key
-
docker-compose文件
version: '3.1' services: mongodb1: # 默认最新 image: mongo # 错误后自动重启 restart: on-failure container_name: mongo1 volumes: # 数据存放目录 - ./db/mongo1:/data/db # keyfile:用于集群之间的认证,⚠️ 注意调整你自己的路径 - /data/mongodb/mongodb.key:/data/mongodb.key # 配置目录 - ./config/mongo1:/data/configdb ports: - 27017:27017 environment: MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_PASSWORD: admin networks: - mongoNet command: mongod --replSet rs0 --keyFile /data/mongodb.key entrypoint: - bash - -c - | chmod 400 /data/mongodb.key chown 999:999 /data/mongodb.key exec docker-entrypoint.sh $$@ mongodb2: image: mongo restart: on-failure container_name: mongo2 volumes: - ./db/mongo2:/data/db - /data/mongodb/mongodb.key:/data/mongodb.key - ./config/mongo2:/data/configdb ports: - 27018:27017 environment: MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_PASSWORD: admin networks: - mongoNet command: mongod --replSet rs0 --keyFile /data/mongodb.key entrypoint: - bash - -c - | chmod 400 /data/mongodb.key chown 999:999 /data/mongodb.key exec docker-entrypoint.sh $$@ mongodb3: image: mongo restart: on-failure container_name: mongo3 volumes: - ./db/mongo3:/data/db - /data/mongodb/mongodb.key:/data/mongodb.key - ./config/mongo3:/data/configdb ports: - 27019:27017 environment: MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_PASSWORD: admin networks: - mongoNet command: mongod --replSet rs0 --keyFile /data/mongodb.key entrypoint: - bash - -c - | chmod 400 /data/mongodb.key chown 999:999 /data/mongodb.key exec docker-entrypoint.sh $$@ networks: mongoNet: driver: bridge
-
进入节点:
docker exec -it mongo1 /bin/bash
rs.initiate({ // 集群名称,一定要和配置文件保持一致 _id: "rs0", members: [ // 一定要用公网,否则访问不到 { _id: 0, host: "xxxxxxxx:port" }, { _id: 1, host: "xxxxxxxx:port" }, { _id: 2, host: "xxxxxxxx:port" } ] }); rs.status(); // 测试:查看集群状态
-
测试,使用gui通过账号密码登陆测试
// 我用的DataGrip(all in one 工具) 你可以用navicat、stdio 3T mongodb://admin:admin@xxx:port1,xxx:port2,xxx:port3/test?replicaSet=rs0&authSource=admin&slaveOk=true&connectTimeoutMS=5000