• prisma使用mongodb副本集群报错引发的一些列问题


    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 }, ] }
      
      • 1

      错误描述很清楚Address: localhost:27017,没有找到合适可用的服务

    • .env文件

      DATABASE_URL="mongodb://自己的云服务器ip地址:27018/test?authSource=admin&retryWrites=true&w=majority"
      
      • 1
    • schema.prisma

      datasource db {
        provider = "mongodb"
        url      = env("DATABASE_URL")
      }
      
      generator client {
        provider        = "prisma-client-js"
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    一切都很平平无奇,下面进行排查流程,此处不做如何搭建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 
            }, 
         	] 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    • 可以看到address字段为localhost:port形式,那么,会不会因为prisma会向mongodb副本集群获取rs.config()然后再根据配置的host进行连接?

    • 这里直接告诉结论:是的,prisma就是这样做的

      1. 首先查看自己的配置信息,进入mongo/mongosh,rs.config()可以发现你配置的所有副本集群信息

      2. 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();
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
    • 最后验证

      1. npx prisma studio:进去后不报错就是ok

      2. 跑一个查询代码

        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();
          });
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17

        结果不管怎样,只要没报错就是ok的

    使用docker-compose部署

    贴上一个简单实用keyFile集群成员认证 + 客户端账号密码认证的1主2从副本集群攻略

    日期:2022-07-31

    • 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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
    • 进入节点: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" }
        ] 
      });
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    • 测试,使用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
      
      • 1
      • 2
  • 相关阅读:
    note_前端框架Vue的安装和简单入门(Windows 11)
    【每日一题】852. 山脉数组的峰顶索引
    记一次 .NET 某仪器测量系统 CPU爆高分析
    pytest一些常见的插件
    RocketMQ部署
    平面设计实验四 绘制工具和修饰工具
    什么是泛型?
    4大软件测试策略的特点和区别(单元测试、集成测试、确认测试和系统测试)
    服务治理--Eureka
    聚类分类应用题
  • 原文地址:https://blog.csdn.net/qq_45593068/article/details/126089042