MongoDB复制集

一、MongoDB复制集概述

  • 组成
    MongoDB复制集(副本集replica set)由一组mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,MongoDB Driver(客户端)的所有数据都写入primary,secondary通过oplog来同步primary的数据,保证主节点和从节点数据的一致性,复制集在完成主从复制的基础上,通过心跳机制,一旦primary节点出现宕机,则触发选举一个新的主节点,剩下的secondary节点指向新的primary,时间应该在10-30s内完成感知primary节点故障,实现高可用数据库集群;

  • 特点

    • 主是唯一的,但不是固定的
    • 通过oplog同步数据,保证数据的一致性;
    • 从库无法写入(默认情况下,不使用驱动连接时,读也是不能查询的);
    • 相对于传统的主从结构,复制集可以自动容灾;

二、MongoDB复制集原理

  • 角色(按是否存储数据划分)

    • primary主节点
      由选举产生,负责客户端的写操作,产生oplog日志文件
    • secondary从节点
      负责客户端的读操作,提供数据的备份和故障的切换
    • arbiter仲裁节点
      只参与选举的投票,不会成为primary,也不向primary同步数据,若部署了一个2个节点的复制集,1个primary,1个secondary,任意节点宕机,复制集将不能提供服务(无法选出primary),这时可以给复制集添加一个arbiter节点,即使有节点宕机,仍能选出primary;
  • 角色(按类型区分)

    • standard(标准)
      这种是常规节点,它存储一份完整的数据副本,参与投票选举,有可能成为主节点
    • passive(被动)
      存储完整的数据副本,参与投票,不能成为活跃节点
    • arbiter(投票)
      仲裁节点只参与投票,不接收复制的数据,也不能成为活跃节点
    注:每个参与节点(非仲裁者)有个优先权(0-1000),优先权(priority)为0则是被动的,不能成为活跃节点,优先权不为0的,按照由大到小选出活跃节点,优先值一样的则看谁的数据比较新;
    注:Mongodb 3.0里,复制集成员最多50个,参与Primary选举投票的成员最多7个;
    
  • 选举
    每个节点通过优先级定义出节点的类型(标准、被动、投票);
    标准节点通过对比自身数据进行选举出primary节点或者secondary节点;

    • 影响选举的因素

      • 心跳检测
        复制集内成员每隔两秒向其他成员发送心跳检测信息,若10秒内无响应,则标记其为不可用
      • 连接
        在多个节点中,最少保证连个节点为工作状态,如果集群中共三个节点,挂掉两个节点,那么剩余的节点无论状态是primary还是处于选举过程中,都会直接降权为secondary
    • 触发的选举的情况

      • 初始化状况
      • 从节点们无法与主节点进行通信
      • 主节点辞职
    • 主节点辞职情况

      • 在接收到replSetStepDown命令后
      • 在现有的环境中,其他secondary节点的数据落后与本身10s内,且拥有更高优先级
      • 当主节点无法与集群中多数节点通信时
      注:当主节点辞职后,主节点将关闭自身所有的连接,避免出现客户端在从节点进行写入操作;

  • 总结

    • 架构方面
      复制集由一个primary和多个secondary节点构成,在多个实例中进行选举以上角色;
    • 选举过程
      每个MongoDB实例都会通过优先级被定义成为不同的类型(标准、被动、投票);
      标准节点和被动节点进行投票选举,选举一个标准节点作为primary节点;
      其他所有节点除仲裁节点以外,都被选举成secondary节点,通过oplog日志文件向primary节点同步数据;
    • 故障切换
      在集群内,所有节点每隔10秒发送一次心跳检测信息,若在规定时间内未响应,则认为宕机,触发选举操作;
      在多个节点中,至少两个节点是正常工作状态,如只剩下一个节点,则降级为secondary;

三、部署MongoDB实现应用复制集

  • 异常处理
    当primary宕机时,如果有数据未同步到secondary,当primary重新加入时,如果新的primary上已经发生写操作,则旧primary需要回滚部分操作,以保证数据集与新的primary一致;旧primary将会滚的数据写到单独的rollback目录下,数据库管理员可根据需要使用mongorestore进行恢复。

  • 环境

系统 主机名 IP 所需软件
centos7.8 mongodb 192.168.100.105 mongodb-linux-x86_64-rhel70-3.6.3.tgz
  • 安装mongodb
[root@mongodb ~]# tar xf mongodb-linux-x86_64-rhel70-3.6.3.tgz 
[root@mongodb ~]# mv mongodb-linux-x86_64-rhel70-3.6.3 /usr/local/mongodb
[root@mongodb ~]# echo "export PATH=/usr/local/mongodb/bin:\$PATH" >>/etc/profile
[root@mongodb ~]#  source /etc/profile
[root@mongodb ~]# ulimit -n 25000
[root@mongodb ~]# ulimit -u 25000
[root@mongodb ~]# echo 0 >/proc/sys/vm/zone_reclaim_mode
[root@mongodb ~]# sysctl -w vm.zone_reclaim_mode=0
vm.zone_reclaim_mode = 0
[root@mongodb ~]# echo never >/sys/kernel/mm/transparent_hugepage/enabled 
[root@mongodb ~]# echo never >/sys/kernel/mm/transparent_hugepage/defrag
  • 创建并启动四个实例
[root@mongodb ~]# cd /usr/local/mongodb/bin/
[root@mongodb bin]# mkdir  {../mongodb1,../mongodb2,../mongodb3,../mongodb4}
[root@mongodb bin]# mkdir ../logs
[root@mongodb bin]# touch ../logs/mongodb{1..4}.log
[root@mongodb bin]# chmod 777 ../logs/mongodb*
[root@mongodb bin]# cat <<END >>/usr/local/mongodb/bin/mongodb1.conf
 bind_ip=192.168.100.105
 port=27017
 dbpath=/usr/local/mongodb/mongodb1/
 logpath=/usr/local/mongodb/logs/mongodb1.log
 logappend=true
 fork=true
 maxConns=5000
 replSet=haha
 #replication name
 END
[root@mongodb bin]# cat <<END >>/usr/local/mongodb/bin/mongodb2.conf
 bind_ip=192.168.100.105
 port=27018
 dbpath=/usr/local/mongodb/mongodb2/
 logpath=/usr/local/mongodb/logs/mongodb2.log
 logappend=true
 fork=true
 maxConns=5000
 replSet=haha
 END
[root@mongodb bin]# vi /usr/local/mongodb/bin/mongodb2.conf 
[root@mongodb bin]# cat <<END >>/usr/local/mongodb/bin/mongodb3.conf
 bind_ip=192.168.100.105
 port=27019
 dbpath=/usr/local/mongodb/mongodb3/
 logpath=/usr/local/mongodb/logs/mongodb3.log
 logappend=true
 fork=true
 maxConns=5000
 replSet=haha
 END
[root@mongodb bin]# cat <<END >>/usr/local/mongodb/bin/mongodb4.conf
 bind_ip=192.168.100.105
 port=27020
 dbpath=/usr/local/mongodb/mongodb4/
 logpath=/usr/local/mongodb/logs/mongodb4.log
 logappend=true
 fork=true
 maxConns=5000
 replSet=haha
 END
[root@mongodb bin]# cd 
[root@mongodb ~]# mongod -f  /usr/local/mongodb/bin/mongodb1.conf
[root@mongodb ~]# mongod -f  /usr/local/mongodb/bin/mongodb2.conf
[root@mongodb ~]# mongod -f  /usr/local/mongodb/bin/mongodb3.conf
[root@mongodb ~]# mongod -f  /usr/local/mongodb/bin/mongodb4.conf
[root@mongodb ~]# netstat -utpln |grep mongod
tcp        0      0 192.168.100.105:27019   0.0.0.0:*               LISTEN      1224/mongod         
tcp        0      0 192.168.100.105:27020   0.0.0.0:*               LISTEN      1252/mongod         
tcp        0      0 192.168.100.105:27017   0.0.0.0:*               LISTEN      1168/mongod         
tcp        0      0 192.168.100.105:27018   0.0.0.0:*               LISTEN      1196/mongod         
[root@mongodb ~]# echo -e "/usr/local/mongodb/bin/mongod -f  /usr/local/mongodb/bin/mongodb1.conf \n/usr/local/mongodb/bin/mongod -f  /usr/local/mongodb/bin/mongodb2.conf\n/usr/local/mongodb/bin/mongod -f  /usr/local/mongodb/bin/mongodb3.conf\n/usr/local/mongodb/bin/mongod -f  /usr/local/mongodb/bin/mongodb4.conf">>/etc/rc.local
[root@mongodb ~]#  chmod +x /etc/rc.local
[root@mongodb ~]# cat <<END >>/etc/init.d/mongodb
 #!/bin/bash
 INSTANCE=\$1
 ACTION=\$2
 case "\$ACTION" in
 'start')
 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/"\$INSTANCE".conf;;
 'stop')
 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/"\$INSTANCE".conf --shutdown;;
 'restart')
 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/"\$INSTANCE".conf --shutdown
 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/"\$INSTANCE".conf;;
 esac
 END
[root@mongodb ~]# chmod +x /etc/init.d/mongodb
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 stop
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 start
  • 配置实例
[root@mongodb ~]# mongo --port 27017 --host 192.168.100.105
##添加节点
> cfg={"_id":"haha","members":[{"_id":0,"host":"192.168.100.105:27017"},{"_id":1,"host":"192.168.100.105:27018"},{"_id":2,"host":"192.168.100.105:27019"}]}
{
    "_id" : "haha",
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.100.105:27017"
        },
        {
            "_id" : 1,
            "host" : "192.168.100.105:27018"
        },
        {
            "_id" : 2,
            "host" : "192.168.100.105:27019"
        }
    ]
}

##初始化节点
> rs.initiate(cfg)
{
    "ok" : 1,
    "operationTime" : Timestamp(1661686022, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1661686022, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
##查看复制群状态
haha:OTHER> rs.status()
{
    "set" : "haha",
    "date" : ISODate("2022-08-28T11:27:19.065Z"),
    "myState" : 1,
    "term" : NumberLong(1),
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1661686035, 3),
            "t" : NumberLong(1)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1661686035, 3),
            "t" : NumberLong(1)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1661686035, 3),
            "t" : NumberLong(1)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1661686035, 3),
            "t" : NumberLong(1)
        }
    },
    "members" : [
        {
            "_id" : 0,
            "name" : "192.168.100.105:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",         ##主节点
            "uptime" : 452,
            "optime" : {
                "ts" : Timestamp(1661686035, 3),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2022-08-28T11:27:15Z"),
            "infoMessage" : "could not find member to sync from",
            "electionTime" : Timestamp(1661686033, 1),
            "electionDate" : ISODate("2022-08-28T11:27:13Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "192.168.100.105:27018",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",           ##从节点
            "uptime" : 16,
            "optime" : {
                "ts" : Timestamp(1661686035, 3),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1661686035, 3),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2022-08-28T11:27:15Z"),
            "optimeDurableDate" : ISODate("2022-08-28T11:27:15Z"),
            "lastHeartbeat" : ISODate("2022-08-28T11:27:17.897Z"),
            "lastHeartbeatRecv" : ISODate("2022-08-28T11:27:15.023Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "192.168.100.105:27017",
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "192.168.100.105:27019",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",           ##从节点
            "uptime" : 16,
            "optime" : {
                "ts" : Timestamp(1661686035, 3),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1661686035, 3),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2022-08-28T11:27:15Z"),
            "optimeDurableDate" : ISODate("2022-08-28T11:27:15Z"),
            "lastHeartbeat" : ISODate("2022-08-28T11:27:17.896Z"),
            "lastHeartbeatRecv" : ISODate("2022-08-28T11:27:15.018Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "192.168.100.105:27017",
            "configVersion" : 1
        }
    ],
    "ok" : 1,
    "operationTime" : Timestamp(1661686035, 3),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1661686035, 3),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}

##添加仲裁节点
haha:PRIMARY> rs.addArb("192.168.100.105:27020")
{
    "ok" : 1,
    "operationTime" : Timestamp(1661686116, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1661686116, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}

haha:PRIMARY> rs.status()
...
{
            "_id" : 3,
            "name" : "192.168.100.105:27020",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",
            "uptime" : 19,
            "lastHeartbeat" : ISODate("2022-08-28T11:28:54.331Z"),
            "lastHeartbeatRecv" : ISODate("2022-08-28T11:28:51.329Z"),
            "pingMs" : NumberLong(0),
            "configVersion" : 2
        }
        ...

注:rs.add()和rs.remove()命令分别用于添加和删除标准节点

haha:PRIMARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
haha:PRIMARY> use cloud
switched to db cloud
haha:PRIMARY> db.users.insert({"id":"1","name":"xiaoming"})
WriteResult({ "nInserted" : 1 })
haha:PRIMARY> db.users.find()
{ "_id" : ObjectId("630b53a4c821b079238237d4"), "id" : "1", "name" : "xiaoming" }
haha:PRIMARY> exit
bye

[root@mongodb ~]# mongo --port 27018 --host 192.168.100.105
haha:SECONDARY> show dbs        ##secondary节点默认无法读取
2022-08-28T19:39:49.549+0800 E QUERY    [thread1] Error: listDatabases failed:{
    "operationTime" : Timestamp(1661686785, 1),
    "ok" : 0,
    "errmsg" : "not master and slaveOk=false",
    "code" : 13435,
    "codeName" : "NotMasterNoSlaveOk",
    "$clusterTime" : {
        "clusterTime" : Timestamp(1661686785, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:65:1
shellHelper.show@src/mongo/shell/utils.js:816:19
shellHelper@src/mongo/shell/utils.js:706:15

#通过以下方式或者驱动方式实现
haha:SECONDARY> db.getMongo().setSlaveOk();
haha:SECONDARY> show dbs
admin   0.000GB
cloud   0.000GB
config  0.000GB
local   0.000GB
haha:SECONDARY> use cloud
switched to db cloud
##secondary节点无法写入
haha:SECONDARY> db.users.insert({"id":"2","name":"xiaohong"})
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })
haha:SECONDARY> db.users.find()
{ "_id" : ObjectId("630b53a4c821b079238237d4"), "id" : "1", "name" : "xiaoming" }
haha:SECONDARY> exit
bye
  • 模拟primary故障,查看角色切换情况
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb1.conf --shutdown
[root@mongodb ~]# mongo --port 27018 --host 192.168.100.105
haha:PRIMARY> rs.status()
{
    "set" : "haha",
    "date" : ISODate("2022-08-28T11:46:53.956Z"),
    "myState" : 1,
    "term" : NumberLong(2),
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1661687175, 1),
            "t" : NumberLong(1)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1661687175, 1),
            "t" : NumberLong(1)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1661687212, 1),
            "t" : NumberLong(2)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1661687212, 1),
            "t" : NumberLong(2)
        }
    },
    "members" : [
        {
            "_id" : 0,
            "name" : "192.168.100.105:27017",
            "health" : 0,
            "state" : 8,
            "stateStr" : "(not reachable/healthy)",     ##无法访问
            "uptime" : 0,
            "optime" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
            },
            "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
            "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
            "lastHeartbeat" : ISODate("2022-08-28T11:46:53.225Z"),
            "lastHeartbeatRecv" : ISODate("2022-08-28T11:46:19.785Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "Connection refused",
            "configVersion" : -1
        },
        {
            "_id" : 1,
            "name" : "192.168.100.105:27018",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",     ##主节点
            "uptime" : 1748,
            "optime" : {
                "ts" : Timestamp(1661687212, 1),
                "t" : NumberLong(2)
            },
            "optimeDate" : ISODate("2022-08-28T11:46:52Z"),
            "infoMessage" : "could not find member to sync from",
            "electionTime" : Timestamp(1661687191, 1),
            "electionDate" : ISODate("2022-08-28T11:46:31Z"),
            "configVersion" : 2,
            "self" : true
        },
        {
            "_id" : 2,
            "name" : "192.168.100.105:27019",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",       ##从节点
            "uptime" : 1189,
            "optime" : {
                "ts" : Timestamp(1661687212, 1),
                "t" : NumberLong(2)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1661687212, 1),
                "t" : NumberLong(2)
            },
            "optimeDate" : ISODate("2022-08-28T11:46:52Z"),
            "optimeDurableDate" : ISODate("2022-08-28T11:46:52Z"),
            "lastHeartbeat" : ISODate("2022-08-28T11:46:53.218Z"),
            "lastHeartbeatRecv" : ISODate("2022-08-28T11:46:53.380Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "192.168.100.105:27018",
            "configVersion" : 2
        },
        {
            "_id" : 3,
            "name" : "192.168.100.105:27020",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",         ##仲裁节点
            "uptime" : 1097,
            "lastHeartbeat" : ISODate("2022-08-28T11:46:53.213Z"),
            "lastHeartbeatRecv" : ISODate("2022-08-28T11:46:51.915Z"),
            "pingMs" : NumberLong(0),
            "configVersion" : 2
        }
    ],
    "ok" : 1,
    "operationTime" : Timestamp(1661687212, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1661687212, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
haha:PRIMARY> exit
bye
  • 启用并手动切换primary角色
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb1.conf
[root@mongodb ~]# mongo --port 27018 --host 192.168.100.105
haha:PRIMARY> cfg={"_id":"haha","members":[{"_id":0,"host":"192.168.100.105:27017","priority":100},{"_id":1,"host":"192.168.100.105:27018","priority":10},{"_id":2,"host":"192.168.100.105:27019","priority":10}]}
haha:PRIMARY> rs.reconfig(cfg)
haha:PRIMARY> exit
bye
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb2.conf --shutdown
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb2.conf
[root@mongodb ~]# mongo --port 27017 --host 192.168.100.105
haha:PRIMARY> exit
bye
  • 将标准节点停掉,被动节点也不会成为主节点
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb1.conf --shutdown
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb2.conf --shutdown
[root@mongodb ~]# mongo --port 27019 --host 192.168.100.105
haha:SECONDARY> rs.status()
{
    "set" : "haha",
    "date" : ISODate("2022-08-28T12:04:41.351Z"),
    "myState" : 2,
    "term" : NumberLong(4),
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1661688219, 1),
            "t" : NumberLong(4)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1661688219, 1),
            "t" : NumberLong(4)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1661688219, 1),
            "t" : NumberLong(4)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1661688219, 1),
            "t" : NumberLong(4)
        }
    },
    "members" : [
        {
            "_id" : 0,
            "name" : "192.168.100.105:27017",
            "health" : 0,
            "state" : 8,
            "stateStr" : "(not reachable/healthy)",
            "uptime" : 0,
            "optime" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
            },
            "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
            "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
            "lastHeartbeat" : ISODate("2022-08-28T12:04:39.126Z"),
            "lastHeartbeatRecv" : ISODate("2022-08-28T12:03:47.988Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "Connection refused",
            "configVersion" : -1
        },
        {
            "_id" : 1,
            "name" : "192.168.100.105:27018",
            "health" : 0,
            "state" : 8,
            "stateStr" : "(not reachable/healthy)",
            "uptime" : 0,
            "optime" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
            },
            "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
            "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
            "lastHeartbeat" : ISODate("2022-08-28T12:04:39.126Z"),
            "lastHeartbeatRecv" : ISODate("2022-08-28T12:03:53.292Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "Connection refused",
            "configVersion" : -1
        },
        {
            "_id" : 2,
            "name" : "192.168.100.105:27019",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 125,
            "optime" : {
                "ts" : Timestamp(1661688219, 1),
                "t" : NumberLong(4)
            },
            "optimeDate" : ISODate("2022-08-28T12:03:39Z"),
            "infoMessage" : "could not find member to sync from",
            "configVersion" : 4,
            "self" : true
        }
    ],
    "ok" : 1,
    "operationTime" : Timestamp(1661688219, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1661688219, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
haha:SECONDARY> exit
bye
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb1.conf
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb2.conf
[root@mongodb ~]# netstat -utpln |grep mongod
tcp        0      0 192.168.100.105:27019   0.0.0.0:*               LISTEN      1918/mongod         
tcp        0      0 192.168.100.105:27020   0.0.0.0:*               LISTEN      1252/mongod         
tcp        0      0 192.168.100.105:27017   0.0.0.0:*               LISTEN      2024/mongod         
tcp        0      0 192.168.100.105:27018   0.0.0.0:*               LISTEN      2103/mongod
  • 查询复制集状态及查看oplog日志文件的大小
[root@mongodb ~]# mongo --port 27019 --host 192.168.100.105
haha:PRIMARY> use local
switched to db local
haha:PRIMARY> rs.printSlaveReplicationInfo()        ##查看节点信息
source: 192.168.100.105:27017
    syncedTo: Sun Aug 28 2022 20:08:17 GMT+0800 (CST)
    0 secs (0 hrs) behind the primary 
source: 192.168.100.105:27018
    syncedTo: Sun Aug 28 2022 20:08:17 GMT+0800 (CST)
    0 secs (0 hrs) behind the primary
haha:PRIMARY> rs.printReplicationInfo()
configured oplog size:   990MB          ##oplog大小为990M
log length start to end: 2535secs (0.7hrs)
oplog first event time:  Sun Aug 28 2022 19:27:02 GMT+0800 (CST)
oplog last event time:   Sun Aug 28 2022 20:09:17 GMT+0800 (CST)
now:                     Sun Aug 28 2022 20:09:18 GMT+0800 (CST)
haha:PRIMARY> db.oplog.rs.stats()
{
    "ns" : "local.oplog.rs",
    "size" : 28427,
    "count" : 249,
    "avgObjSize" : 114,
    "storageSize" : 45056,
    "capped" : true,
    "max" : -1,
    "maxSize" : 1038090240,     ##单位是字节
...
  • 部署用户认证登录(秘钥对)的复制集
[root@mongodb ~]# mongo --port 27019 --host 192.168.100.105
haha:PRIMARY> use admin
switched to db admin
haha:PRIMARY> db.createUser({"user":"root","pwd":"123","roles":["root"]})
Successfully added user: { "user" : "root", "roles" : [ "root" ] }
haha:PRIMARY> exit
bye
[root@mongodb ~]# echo -e "clusterAuthMode=keyFile\nkeyFile=/usr/local/mongodb/bin/cloudkey1" >>/usr/local/mongodb/bin/mongodb1.conf
[root@mongodb ~]# echo -e "clusterAuthMode=keyFile\nkeyFile=/usr/local/mongodb/bin/cloudkey2" >>/usr/local/mongodb/bin/mongodb2.conf
[root@mongodb ~]# echo -e "clusterAuthMode=keyFile\nkeyFile=/usr/local/mongodb/bin/cloudkey3" >>/usr/local/mongodb/bin/mongodb3.conf
[root@mongodb ~]# echo "haha key" >/usr/local/mongodb/bin/cloudkey1
[root@mongodb ~]# echo "haha key" >/usr/local/mongodb/bin/cloudkey2
[root@mongodb ~]# echo "haha key" >/usr/local/mongodb/bin/cloudkey3
[root@mongodb ~]# chmod 600 /usr/local/mongodb/bin/cloudkey*
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 restart
[root@mongodb ~]# /etc/init.d/mongodb mongodb2 restart
[root@mongodb ~]# /etc/init.d/mongodb mongodb3 restart
[root@mongodb ~]# mongo --port 27019 --host 192.168.100.105
haha:PRIMARY> show dbs
2022-08-28T20:15:53.475+0800 E QUERY    [thread1] Error: listDatabases failed:{
...
haha:PRIMARY> use admin
switched to db admin
haha:PRIMARY> db.auth("root","123")
1
haha:PRIMARY> show dbs
admin   0.000GB
cloud   0.000GB
config  0.000GB
local   0.000GB
haha:PRIMARY> exit
bye

李泽信 发布于 2022-8-28 18:16

MongoDB介绍

一、MongoDB

-概述
MongoDB是由C++语言编写的,是一个基于分布式文件存储的非关系型开源数据库系统。其优势在于可以存放海量数据,具备强大的查询功能,是一个独立的面向集合文档形式的

  • 起源与发展
    2007年10月,MongoDB由10gen团队所发展。2009年2月首度推出。
  • 应用平台
    MongoDB支持Unix、Linux、Windows等系统平台。

二、MongoDB特点

  • 存储型

    • 面向集合
      Collection-Oriented,数据被分组存储在数据集中,被称为一个集合(Collection)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库里的表,不同的是它不需要定义任何模式。
    • 面向文档
      存储在集合中的文档,被存储为键-值对的形式。键用于唯一标识一个文档,为字符串类型,而值则可以是各种复杂的文件类型。我们称这种存储形式为BSON(Binary Serialized Document Format);
    • 高效二进制数据存储
      包括大型对象(如视频)。使用二进制格式存储,可以保存任何类型的数据对象;
  • 操作型

    • 完全索引
      可以在任意属性上建立索引,包含内部对象。以提高查询的速度;
    • 强大的聚合工具
      MongoDB 除了提供丰富的查询功能外,还提供强大的聚合工具,如count、group 等,支持使用MapReduce 完成复杂的聚合任务;
    • 支持Perl、PHP、Java、C#、JavaScript、Ruby、C和C++语言的驱动程序
      MongoDB提供了当前所有主流开发语言的数据库驱动包,开发人员使用任何一种主流开发语言都可以轻松编程,实现访问MongoDB 数据库;
  • 可用性

    • 支持复制和数据恢复
      MongoDB支持主从复制机制,可以实现数据备份、故障恢复、读扩展等功能。而基于副本集的复制机制提供了自动故障恢复的功能,确保了集群数据不会丢失;
    • 自动处理分片
      MongoDB支持集群自动切分数据,对数据进行分片可以使集群存储更多的数据,实现更大的负载,也能保证存储的负载均衡;

三、MongoDB应用场景

  • 适用场景

    • 网站数据
      mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性;
    • 缓存
      由于性能很高,mongo也适合作为信息基础设施的缓存层。在系统重启之后,由mongo搭建的持久化缓存可以避免下层的数据源过载;
    • 密度高、价值数据低
      使用传统的关系数据库存储一些数据时可能会比较贵,在此之前,很多程序员往往会选择传统的文件进行存储;
    • 高伸缩性的场景
      mongo非常适合由数十或者数百台服务器组成的数据库。
    • 用于对象及JSON数据的存储
      mongo的BSON数据格式非常适合文档格式化的存储及查询;
  • 非适用场景

    • 高度事务性的系统
      例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序;
    • 传统的商业智能应用
      针对特定问题的数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择;
    • 需要传统的SQL语句的场景
  • MongoDB案例应用链接
    http://www.mongoing.com/archives/3734

四、MongoDB存储结构

  • 逻辑结构

    • 文档(document)
      是mongodb核心概念也是逻辑存储的最小单元,相当于行;
    • 集合(collection)
      多个文档组成集合,相当于表,但不同于表的是无固定结构;
    • 数据库(database)
      多个集合组成数据库
    • 总结
      一个MongoDB实例可以包含一组数据库,一个DataBase可以包含一组Collection,一个集合可以包含一组Document。一个Document包含一组field(字段),每一个字段都是一个key/value pair;
  • 物理结构

    • .ns文件
      每个表或索引对应一个命名空间,数据量增加,文件数量增多,存储了分配和正在使用的磁盘空间;
    • 数据文件
      存放数据的实体,并且使用预分配空间机制;
    • 日志文件
      系统日志文件、journal日志文件(用于mongodb崩溃恢复的保障)、oplog复制操作日志文件(相当于mysql的binary log文件)、慢查询日志:查询操作超出超时时间的慢动作;
    注:
    在mongodb 3.0版本后,默认的存储引擎已经改变,成为WT(wiredTiger)存储引擎,无以前的.ns文件;
    wiredTiger引擎:3.0新增引擎,官方宣称在read、insert和复杂的update下具有更高的性能。可以支撑更高的读写负载和并发量。因为对于production环境,更多的CPU可以有效提升wireTiger的性能,因为它是的IO是多线程的。wiredTiger不像MMAPV1引擎那样尽可能的耗尽内存,它可以通过在配置文件中指定“cacheSizeGB”参数设定引擎使用的内存量; 
    journal就是一个预写事务日志,来确保数据的持久性,wiredTiger每隔60秒(默认)或者待写入的数据达到2G时,mongodb将对journal文件提交一个checkpoint(检测点,将内存中的数据变更flush到磁盘中的数据文件中,并做一个标记点,表示此前的数据表示已经持久存储在了数据文件中,此后的数据变更存在于内存和journal日志)。对于write操作,首先被持久写入journal,然后在内存中保存变更数据,条件满足后提交一个新的检测点,即检测点之前的数据只是在journal中持久存储,但并没有在mongodb的数据文件中持久化,延迟持久化可以提升磁盘效率;
    为了确保数据的安全性,mongodb将所有的变更操作写入journal并间歇性的持久到磁盘上,对于实际数据文件将延迟写入,和wiredTiger一样journal也是用于数据恢复;
    


详看原文https://blog.csdn.net/xiaoql520/article/details/76973887

  • 内存映射存储引擎MMAP

    • mongodb会把数据文件映射到内存中,如果是读操作,内存中的数据起到缓存的作用,如果是写操作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能;
    • MongoDB并不干涉内存管理工作,而是把这些工作留给操作系统的虚拟内存管理器去处理,这样做的好处是简化了MongoDB的工作,但坏处是你没有方法很方便的控制MongoDB占多大内存,幸运的是虚拟内存管理器的存在让我们多数时候并不需要关心这个问题;
    • MongoDB的内存使用机制(持久化)让它在缓存重建方面更有优势,简而言之:如果重启进程,那么缓存依然有效;

五、MongoDB数据类型

六、部署MongoDB

  • 系统环境
系统 主机名 IP 所需软件
centos7.8 mongodb 192.168.100.108 mongodb-linux-x86_64-rhel70-3.6.3.tgz
  • 推荐学习地址http://www.runoob.com/mongodb/mongodb-php.html

  • 环境部署

[root@mongodb ~]# ulimit -n 25000       ##同一时间最多开启的文件数
[root@mongodb ~]# ulimit -u 25000       ##用户最多开启的程序数目
[root@mongodb ~]# echo 0 >/proc/sys/vm/zone_reclaim_mode        ##设置内核参数,当某个内存区域节点内存不足时,可以借用其他区域节点的内存
[root@mongodb ~]# sysctl -w vm.zone_reclaim_mode=0
vm.zone_reclaim_mode = 0
[root@mongodb ~]# echo never >/sys/kernel/mm/transparent_hugepage/enabled       ##设置内存分配页
[root@mongodb ~]# echo never >/sys/kernel/mm/transparent_hugepage/defrag
  • 解压MongoDB软件包
[root@mongodb ~]# tar xf mongodb-linux-x86_64-rhel70-3.6.3.tgz 
[root@mongodb ~]# mv mongodb-linux-x86_64-rhel70-3.6.3 /usr/local/mongodb
[root@mongodb ~]# echo "export PATH=/usr/local/mongodb/bin:\$PATH" >>/etc/profile
[root@mongodb ~]# source /etc/profile
  • 创建mongodb存储目录以及配置文件
[root@mongodb ~]# mkdir /usr/local/mongodb/mongodb1
[root@mongodb ~]#  mkdir /usr/local/mongodb/logs/
[root@mongodb ~]# touch /usr/local/mongodb/logs/mongodb1.log
[root@mongodb ~]# chmod 777 /usr/local/mongodb/logs/mongodb1.log
[root@mongodb ~]# cat <<END >>/usr/local/mongodb/bin/mongodb1.conf
 bind_ip=192.168.100.108
 port=27017
 dbpath=/usr/local/mongodb/mongodb1/
 logpath=/usr/local/mongodb/logs/mongodb1.log
 logappend=true
 fork=true
 maxConns=5000
 END
  • 编写服务启动脚本
[root@mongodb ~]# mongod -f  /usr/local/mongodb/bin/mongodb1.conf       ##启动实例
[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108     ##连接服务命令,ctrl+D退出
[root@mongodb ~]#  mongod -f  /usr/local/mongodb/bin/mongodb1.conf --shutdown       ##关闭实例
[root@mongodb ~]# echo /usr/local/mongodb/bin/mongod -f  /usr/local/mongodb/bin/mongodb1.conf >>/etc/rc.local       ##设置开机启动
[root@mongodb ~]# chmod +x /etc/rc.local
[root@mongodb ~]# cat <<END >>/etc/init.d/mongodb
 #!/bin/bash
 INSTANCE=\$1
 ACTION=\$2
 case "\$ACTION" in
 'start')
 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/"\$INSTANCE".conf;;
 'stop')
 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/"\$INSTANCE".conf --shutdown;;
 'restart')
 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/"\$INSTANCE".conf --shutdown
 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/"\$INSTANCE".conf;;
 esac
 END
[root@mongodb ~]# chmod +x /etc/init.d/mongodb
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 start        ##启动
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 stop         ##停止
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 restart      ##重启
  • 测试访问MongoDB数据库
[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108
MongoDB shell version v3.6.3
connecting to: mongodb://192.168.100.108:27017/
MongoDB server version: 3.6.3
Server has startup warnings: 
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] 
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] 
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] 
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] 
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2022-08-28T11:51:49.272+0800 I CONTROL  [initandlisten] 
> show dbs
admin  0.000GB
local  0.000GB
> exit
bye

七、MongoDB中语句操作


注:可以补全,可以不加;

##查看帮助
> help
> db.help

##查看数据库
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
> show databases
admin   0.000GB
config  0.000GB
local   0.000GB

##进入数据库,没有且创建
> use local
switched to db local

##查看集合
> show tables
startup_log
> show collections
startup_log

##创建linux数据库
> use linux
switched to db linux

##创建集合user
> db.user.insert({"id":1,"name":"tom"});
WriteResult({ "nInserted" : 1 })

##查看数据库
> show dbs
admin   0.000GB
config  0.000GB
linux   0.000GB
local   0.000GB

##查看集合
> show collections
user

##查看集合中的文档
> db.user.find()
{ "_id" : ObjectId("630ae8a21abdef07d14191fc"), "id" : 1, "name" : "tom" }

##统计集合的文档条目
> db.user.count()
1

##查看数据库状态
> db.stats()
{
    "db" : "linux",
    "collections" : 1,
    "views" : 0,
    "objects" : 1,
    "avgObjSize" : 48,
    "dataSize" : 48,
    "storageSize" : 16384,
    "numExtents" : 0,
    "indexes" : 1,
    "indexSize" : 16384,
    "fsUsedSize" : 2132975616,
    "fsTotalSize" : 18238930944,
    "ok" : 1
}

##集合中插入文档条目,并设置多种数据类型
> db.user.insert({"id":2,"name":"jack","isadmin":true,"gender":null,"favorite":["apple","banana" ,"orange",1,2,3],"regtime":new Date()});
WriteResult({ "nInserted" : 1 })

##查看集合中文档内容
> db.user.find()
{ "_id" : ObjectId("630ae8a21abdef07d14191fc"), "id" : 1, "name" : "tom" }
{ "_id" : ObjectId("630ae8f31abdef07d14191fd"), "id" : 2, "name" : "jack", "isadmin" : true, "gender" : null, "favorite" : [ "apple", "banana", "orange", 1, 2, 3 ], "regtime" : ISODate("2022-08-28T04:02:59.141Z") }

##根据key值搜索集合中文档内容
> db.user.findOne({"id":2})
{
    "_id" : ObjectId("630ae8f31abdef07d14191fd"),
    "id" : 2,
    "name" : "jack",
    "isadmin" : true,
    "gender" : null,
    "favorite" : [
        "apple",
        "banana",
        "orange",
        1,
        2,
        3
    ],
    "regtime" : ISODate("2022-08-28T04:02:59.141Z")
}

##查看集合中值的类型
> a=db.user.findOne({'id':2})
{
    "_id" : ObjectId("630ae8f31abdef07d14191fd"),
    "id" : 2,
    "name" : "jack",
    "isadmin" : true,
    "gender" : null,
    "favorite" : [
        "apple",
        "banana",
        "orange",
        1,
        2,
        3
    ],
    "regtime" : ISODate("2022-08-28T04:02:59.141Z")
}

##查看id值类型为数字
> typeof(a.id)
number

##查看name值类型为字符串
> typeof(a.name)
string

##后插入的key值会覆盖先存在的key值
> db.user.insert({"id":1,"id":2});
WriteResult({ "nInserted" : 1 })
> db.user.find()
...
{ "_id" : ObjectId("630aeb4d1abdef07d14191fe"), "id" : 2 }

##默认区分大小写
> db.user.insert({"id":1,"ID":2});
WriteResult({ "nInserted" : 1 })
> db.user.find()
...
{ "_id" : ObjectId("630aeb4d1abdef07d14191fe"), "id" : 2 }
{ "_id" : ObjectId("630aebca1abdef07d14191ff"), "id" : 1, "ID" : 2 }

##key值可以为kong,但是通常不会用
> db.user.insert({"":"20"});
WriteResult({ "nInserted" : 1 })
> db.user.find()
...
{ "_id" : ObjectId("630aec101abdef07d1419200"), "" : "20" }

##key值不可以是$开头
> db.user.insert({"$id":"20"});
WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 2,
        "errmsg" : "Document can't have $ prefixed field names: $id"
    }
})

##特殊符号可以作为key值中的一部分
> db.user.insert({"i$d":"20"});
WriteResult({ "nInserted" : 1 })
> db.user.find()
...
{ "_id" : ObjectId("630aecaf1abdef07d1419202"), "i$d" : "20" }

##更新集合中文档的内容
> db.user.update({"id":1},{$set:{"name":"xiaohong"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("630ae8a21abdef07d14191fc"), "id" : 1, "name" : "xiaohong" }

##批量增加文档条目
> for(i=1;i<=1000;i++){db.user.insert({"id":i,"name":"haha"})};
WriteResult({ "nInserted" : 1 })
> db.user.find()
...
{ "_id" : ObjectId("630aed901abdef07d1419203"), "id" : 1, "name" : "haha" }
{ "_id" : ObjectId("630aed901abdef07d1419204"), "id" : 2, "name" : "haha" }
{ "_id" : ObjectId("630aed901abdef07d1419205"), "id" : 3, "name" : "haha" }
{ "_id" : ObjectId("630aed901abdef07d1419206"), "id" : 4, "name" : "haha" }
{ "_id" : ObjectId("630aed901abdef07d1419207"), "id" : 5, "name" : "haha" }
...

##删除集合中的某条文档
> db.user.remove({"id":1})
WriteResult({ "nRemoved" : 3 })

##删除集合
> db.user.drop()
true

##删除当前所在的数据库
> db.dropDatabase()
{ "dropped" : "linux", "ok" : 1 }

##查看mongodb版本
> db.version()
3.6.3

##退出
> ctrl+d

八、MongoDB数据库的导入导出、备份恢复、复制数据库

  • 导入导出语法
导入语法:
mongoimport -d database_name -c collection_name --file source_name

导出语法:
mongoexport -d database_name -c coolection_name [-f list_name] -o backup.jso

##有些选项为可选,若进行数据过滤条件判断指定选项-q
  • 案例
[root@mongodb ~]# yum -y install mysql mariadb-server
[root@mongodb ~]# systemctl start mariadb
[root@mongodb ~]# mysql
MariaDB [(none)]> create database linux;
MariaDB [(none)]> use linux;
MariaDB [linux]> create table t1(id int,name varchar(20));
MariaDB [linux]> insert into t1 values(1,'jack');
Query OK, 1 row affected (0.00 sec)

MariaDB [linux]> insert into t1 values(2,'Rose');
Query OK, 1 row affected (0.01 sec)

MariaDB [linux]> select * from t1;
+------+------+
| id   | name |
+------+------+
|    1 | jack |
|    2 | Rose |
+------+------+
2 rows in set (0.00 sec)

MariaDB [linux]> select * from linux.t1 into outfile '/tmp/t1_mysql.csv' fields terminated by ","; 
Query OK, 2 rows affected (0.00 sec)

MariaDB [linux]> exit
Bye

[root@mongodb ~]# cat /tmp/systemd-private-b015b893b70a47d2bc3d3f2b7993359a-mariadb.service-JXIqTg/tmp/t1_mysql.csv 
1,jack
2,Rose

[root@mongodb ~]# /usr/local/mongodb/bin/mongoimport --port 27017 --host 192.168.100.108 -d benet -c tt1 -f id,name --file /tmp/systemd-private-b015b893b70a47d2bc3d3f2b7993359a-mariadb.service-JXIqTg/tmp/t1_mysql.csv --type csv
2022-08-28T12:40:35.413+0800    connected to: 192.168.100.108:27017
2022-08-28T12:40:35.425+0800    imported 2 documents

[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108
> show dbs
admin   0.000GB
benet   0.000GB
config  0.000GB
local   0.000GB
> use benet
switched to db benet
> show tables;
tt1
> db.tt1.find()
{ "_id" : ObjectId("630af1c3501853411e392cec"), "id" : 1, "name" : "jack" }
{ "_id" : ObjectId("630af1c3501853411e392ced"), "id" : 2, "name" : "Rose" }
> for(var i=1;i<=10000;i++)db.tt1.insert({"id":i,"name":"name"+i});
WriteResult({ "nInserted" : 1 })
> db.tt1.find({"id":{"$gt":5000}}).limit(3);
{ "_id" : ObjectId("630af278db5771d52ba03b8a"), "id" : 5001, "name" : "name5001" }
{ "_id" : ObjectId("630af278db5771d52ba03b8b"), "id" : 5002, "name" : "name5002" }
{ "_id" : ObjectId("630af278db5771d52ba03b8c"), "id" : 5003, "name" : "name5003" }
> db.tt1.find({"id":{"$gt":5000}}).count();
5000
> exit
bye

[root@mongodb ~]# /usr/local/mongodb/bin/mongoexport --host 192.168.100.108 --port 27017 -d benet -c tt1 -q '{"id":{"$gt":5000}}' -o /tmp/test.json
2022-08-28T12:47:53.190+0800    connected to: 192.168.100.108:27017
2022-08-28T12:47:53.271+0800    exported 5000 records
[root@mongodb ~]# ls /tmp/
mongodb-27017.sock                                                       systemd-private-b015b893b70a47d2bc3d3f2b7993359a-vgauthd.service-ThP1Bx
systemd-private-b015b893b70a47d2bc3d3f2b7993359a-chronyd.service-9Nf59b  systemd-private-b015b893b70a47d2bc3d3f2b7993359a-vmtoolsd.service-RM8UIQ
systemd-private-b015b893b70a47d2bc3d3f2b7993359a-mariadb.service-JXIqTg  test.json
[root@mongodb ~]# wc -l /tmp/test.json 
5000 /tmp/test.json
  • 备份恢复
逻辑备份
mongodump -h server_ip -d database_name -o dbdirectory

物理备份:冷备

恢复
mongorestore -d database_name --dir=dbdirectory
  • 案例
[root@mongodb ~]# mkdir /backup
[root@mongodb ~]# /usr/local/mongodb/bin/mongodump --host 192.168.100.108 --port 27017 -d benet -o /backup/
2022-08-28T12:52:22.805+0800    writing benet.tt1 to 
2022-08-28T12:52:22.881+0800    done dumping benet.tt1 (10002 documents)
[root@mongodb ~]# ls /backup/benet/
tt1.bson  tt1.metadata.json

注解:bson是由10gen开发的一个数据格式,目前主要用于mongoDB中,是mongoDB的数据存储格式。bson基于json格式,选择json进行改造的原因主要是json的通用性及json的schemaless的特性;

[root@mongodb ~]# /usr/local/mongodb/bin/mongorestore --host 192.168.100.108 --port 27017 -d bdqn --dir=/backup/benet/
2022-08-28T12:54:23.974+0800    the --db and --collection args should only be used when restoring from a BSON file. Other uses are deprecated and will not exist in the future; use --nsInclude instead
2022-08-28T12:54:23.975+0800    building a list of collections to restore from /backup/benet dir
2022-08-28T12:54:23.976+0800    reading metadata for bdqn.tt1 from /backup/benet/tt1.metadata.json
2022-08-28T12:54:23.986+0800    restoring bdqn.tt1 from /backup/benet/tt1.bson
2022-08-28T12:54:24.119+0800    no indexes to restore
2022-08-28T12:54:24.119+0800    finished restoring bdqn.tt1 (10002 documents)
2022-08-28T12:54:24.119+0800    done
[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108
> show dbs
admin   0.000GB
bdqn    0.000GB
benet   0.000GB
config  0.000GB
local   0.000GB
> exit
  • 复制数据库
复制数据库:
db.copyDatabase("source_db","des_db","192.168.100.108")
克隆集合:
db.runCommand({cloneCollection:"accp.t1",from:"192.168.100.102:27017"})
##将远程ip服务器的某个数据库中的某个集合克隆到本地
  • 案例
[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108
> db.copyDatabase("bdqn","bdqn2","192.168.100.108");
{ "ok" : 1 }
> show dbs
admin   0.000GB
bdqn    0.000GB
bdqn2   0.000GB
benet   0.000GB
config  0.000GB
local   0.000GB
> exit
bye

九、MongoDB数据库的用户角色权限管理

  • 角色

  • 注意

    • 创建用户时
      需要在默认test数据库中,不use到任何数据库,不然会导致普通用户的归属数据库错乱;
    • 用户在验证身份登录时
      必须要use到本用户的所属db数据库;
    • 查看扫描用户时
      需要在admin数据库中,执行use admin切换进去;
    • 撤销修改其权限时
      需要在用户所属的db数据库中进行;
    • 管理员删除用户时
      必须在admin数据库中执行删除;
[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108     ##登录后默认在test数据库中

##查看当前用户
> db.getUsers()
[ ]

##创建超级管理员root
> db.createUser({user:"root",pwd:"abc123",roles:[{role:"root",db:"admin"}]})
Successfully added user: {
    "user" : "root",
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}

##查看当前用户
> db.getUsers()
[
    {
        "_id" : "test.root",
        "user" : "root",
        "db" : "test",      ##所属数据库
        "roles" : [
            {
                "role" : "root",
                "db" : "admin"      ##拥有权限的管理数据库
            }
        ]
    }
]

[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb1.conf --shutdown
[root@mongodb ~]# mongod -f /usr/local/mongodb/bin/mongodb1.conf --auth
about to fork child process, waiting until server is ready for connections.
forked process: 15675
child process started successfully, parent exiting

[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108
> show dbs          ##无法认证,所以报错
2022-08-28T13:09:12.646+0800 E QUERY    [thread1] Error: listDatabases failed:{
    "ok" : 0,
    "errmsg" : "not authorized on admin to execute command { listDatabases: 1.0, $db: \"admin\" }",
    "code" : 13,
    "codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:65:1
shellHelper.show@src/mongo/shell/utils.js:816:19
shellHelper@src/mongo/shell/utils.js:706:15
@(shellhelp2):1:1

>  db.auth('root','abc123')     ##认证用户
1
> show dbs          ##验证查看权限
admin   0.000GB
bdqn    0.000GB
bdqn2   0.000GB
benet   0.000GB
config  0.000GB
local   0.000GB

> db.haha.insert({"id":"1","num":"101"})        ##测试插入内容
WriteResult({ "nInserted" : 1 })
> db.haha.find()
{ "_id" : ObjectId("630afa790f394408576d6329"), "id" : "1", "num" : "101" }

##创建普通用户,注意,当前root所在的数据库是test,所以创建的用户hahaadmin所属库也是test,也就是说hahaadmin在登陆时只能在test库中才能认证成功
> db.createUser({user:"hahaadmin",pwd:"123123",roles:[{role:"read",db:"haha"},{role:"readWrite",db:"hehe"}]})
Successfully added user: {
    "user" : "hahaadmin",
    "roles" : [
        {
            "role" : "read",
            "db" : "haha"
        },
        {
            "role" : "readWrite",
            "db" : "hehe"
        }
    ]
}

##查看当前用户
> db.getUsers()
[
    {
        "_id" : "test.hahaadmin",
        "user" : "hahaadmin",
        "db" : "test",
        "roles" : [
            {
                "role" : "read",
                "db" : "haha"
            },
            {
                "role" : "readWrite",
                "db" : "hehe"
            }
        ]
    },
    {
        "_id" : "test.root",
        "user" : "root",
        "db" : "test",      ##所属库
        "roles" : [
            {
                "role" : "root",
                "db" : "admin"
            }
        ]
    }
]
##切换到admin数据库内,扫描所有的mongodb内的用户
> use admin
switched to db admin
> db.system.users.find()
{ "_id" : "test.root", "user" : "root", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "v2dJWCCErnbPoPVMbnuqFA==", "storedKey" : "hxhDLSqDRUeC8BO/qSkWRjtwpTE=", "serverKey" : "539frIWAAuJtwZQxzWOPOxcdYis=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "test.hahaadmin", "user" : "hahaadmin", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "yyOYhCn4P4tQ7eim9Or+AQ==", "storedKey" : "4P5NDvPLNJ1Cs9w+9tesArLfOjA=", "serverKey" : "pWR/ALlYFggx517MKyn5XmdniZw=" } }, "roles" : [ { "role" : "read", "db" : "haha" }, { "role" : "readWrite", "db" : "hehe" } ] }

[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108
##登陆普通用户,进行认证
> db.auth('hahaadmin','123123')
1
##切换至有读权限的数据库,测试能够读取数据,但是无法写入数据
> use haha      
switched to db haha
> db.user.insert({"id":1,"name":"zs"})
WriteResult({
    "writeError" : {
        "code" : 13,
        "errmsg" : "not authorized on haha to execute command { insert: \"user\", ordered: true, $db: \"haha\" }"
    }
})

[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108
##登陆普通用户进行认证
> db.auth('hahaadmin','123123')
1
##切换至有读写权限的数据库,测试能够读取数据,也可以写入数据
> use hehe
switched to db hehe
>  db.user.insert({"id":1,"name":"ls"})
WriteResult({ "nInserted" : 1 })
>  db.user.find()
{ "_id" : ObjectId("630afda9e8160ce0488d2ff6"), "id" : 1, "name" : "ls" }

[root@mongodb ~]# mongo --port 27017 --host 192.168.100.108
> db.auth('root','abc123')
1
##为hahaadmin用户提升在haha数据库中的权限,需要首先切换到hahaadmin用户所在的所属数据库test中
> use test
switched to db test
##现有权限基础上加权限
> db.grantRolesToUser("hahaadmin",[{role:"readWrite",db:"haha"}])
> use admin
switched to db admin
##扫描所有用户及权限
> db.system.users.find()
{ "_id" : "test.root", "user" : "root", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "v2dJWCCErnbPoPVMbnuqFA==", "storedKey" : "hxhDLSqDRUeC8BO/qSkWRjtwpTE=", "serverKey" : "539frIWAAuJtwZQxzWOPOxcdYis=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "test.hahaadmin", "user" : "hahaadmin", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "yyOYhCn4P4tQ7eim9Or+AQ==", "storedKey" : "4P5NDvPLNJ1Cs9w+9tesArLfOjA=", "serverKey" : "pWR/ALlYFggx517MKyn5XmdniZw=" } }, "roles" : [ { "role" : "readWrite", "db" : "haha" }, { "role" : "read", "db" : "haha" }, { "role" : "readWrite", "db" : "hehe" } ] }
> use test
switched to db test

##现有权限基础上撤销权限
> db.revokeRolesFromUser("hahaadmin",[{role:"readWrite",db:"hehe"}])
> use admin
switched to db admin

##扫描所有用户及权限
> db.system.users.find()
{ "_id" : "test.root", "user" : "root", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "v2dJWCCErnbPoPVMbnuqFA==", "storedKey" : "hxhDLSqDRUeC8BO/qSkWRjtwpTE=", "serverKey" : "539frIWAAuJtwZQxzWOPOxcdYis=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "test.hahaadmin", "user" : "hahaadmin", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "yyOYhCn4P4tQ7eim9Or+AQ==", "storedKey" : "4P5NDvPLNJ1Cs9w+9tesArLfOjA=", "serverKey" : "pWR/ALlYFggx517MKyn5XmdniZw=" } }, "roles" : [ { "role" : "readWrite", "db" : "haha" }, { "role" : "read", "db" : "haha" } ] }

##删除用户
> db.system.users.remove({user:"hahaadmin"})
WriteResult({ "nRemoved" : 1 })

##扫描系统中所有用户,主义当前必须在admin中
> db.system.users.find()
{ "_id" : "test.root", "user" : "root", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "v2dJWCCErnbPoPVMbnuqFA==", "storedKey" : "hxhDLSqDRUeC8BO/qSkWRjtwpTE=", "serverKey" : "539frIWAAuJtwZQxzWOPOxcdYis=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
>

十、MongoDB连接php

  • 安装部署lamp及MongoDB驱动
[root@mongodb ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@mongodb ~]# yum -y install httpd php php-devel openssl openssl-devel
[root@mongodb ~]# unzip mongo-php-driver-legacy-master.zip
[root@mongodb ~]# cd mongo-php-driver-legacy-master/
[root@mongodb mongo-php-driver-legacy-master]# phpize
[root@mongodb mongo-php-driver-legacy-master]# ./configure && make && make install
[root@mongodb mongo-php-driver-legacy-master]# cd
[root@mongodb ~]# cat <<END >>/etc/php.ini 
[MongoDB]
extension=mongo.so
END
[root@mongodb ~]# systemctl start httpd

测试phpinfo页面
[root@mongodb ~]# cat <<END >>/var/www/html/index.php
<?php
phpinfo();
?>
END

  • 测试php连接mongodb数据库
[root@mongodb ~]# vi /var/www/html/a.php 
<?php
$m = new MongoClient("mongodb://192.168.100.108:27017");
$db = $m ->linux;
//指定数据库位置,若不存在,则会自动创建
echo "sucess"
?>

  • 测试php连接MongoDB数据库并创建集合
[root@mongodb ~]# vi /var/www/html/b.php 
<?php
$m = new MongoClient("mongodb://192.168.100.108:27017");
$db = $m->linux;
$collection = $db->createCollection("test1");
echo "集合test1创建成功";
?>

  • 测试php连接MongoDB数据库并插入文档
[root@mongodb ~]# vi /var/www/html/c.php 
<?php
$m = new MongoClient("mongodb://192.168.100.108:27017");
$db = $m->linux;
$collection = $db->test1;
$document = array(
    "title" => "MongoDB",
    "description" => "database",
    "likes" => 100,
    "url" => "http://www.linuxfan.cn","by","linuxfan"
);
$collection->insert($document);
echo "数据插入成功";
?>

  • 测试MongoDB数据库内数据
[root@mongodb ~]# mongo --host 192.168.100.108 --port 27017 
> show dbs
admin   0.000GB
bdqn    0.000GB
bdqn2   0.000GB
benet   0.000GB
config  0.000GB
haha    0.000GB
hehe    0.000GB
linux   0.000GB
local   0.000GB
> use linux
switched to db linux
> db.test1.find()
{ "_id" : ObjectId("630b014e4b0139904c8b4567"), "title" : "MongoDB", "description" : "database", "likes" : NumberLong(100), "url" : "http://www.linuxfan.cn", "0" : "by", "1" : "linuxfan" }
> exit
bye

李泽信 发布于 2022-8-28 11:10

keepalived热备应用

一、keepalived概述

  • 概述

keepalived起初为lvs设计的一款强大的辅助工具,保证lvs负载调度器的故障切换以及web节点的健康状态检查,后续被应用到很多需要容错的场景下,keepalived自身基于VRRP协议--虚拟路由冗余协议,思科共有协议;

二、设计原理

  • 应用场景

  • 设计模块

    • core模块
      为keepalived的核心组件,负责主进程的启动、维护及全局配置文件的加载和解析
    • check模块
      负责real server节点池的节点的健康检测
    • VRRP模块在master与backup之间执行新调检测
  • 热备实现过程
    将多个主机以软件的方式组成一个热备足,通过共有虚拟ip(VIP)地址对外提供服务,同一时刻,热备足中只有一台主机在工作,别的主机冗余状态,当当前在线的主机失效时,其他冗余的主机会自动阶梯虚拟主机ip地址,继续提供服务,以保证架构的稳定性;

三、keepalived实现双机热备

系统类型 IP地址 主机名 所需软件
centos7.8 192.168.100.105 node1.linux.com keepalived-1.2.13.tar.gz
centos7.8 192.168.100.106 node2.linux.com keepalived-1.2.13.tar.gz
  • 安装node1节点上的httpd服务
[root@node1 ~]# yum -y install httpd
[root@node1 ~]# cat <<END >>/var/www/html/index.html
192.168.100.105
END
[root@node1 ~]# systemctl start httpd
[root@node1 ~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
[root@node1 ~]# netstat -utpln |grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1217/httpd 
  • 安装node2节点上的httpd服务
[root@node1 ~]# yum -y install httpd
[root@node1 ~]# cat <<END >>/var/www/html/index.html
192.168.100.106
END
[root@node1 ~]# systemctl start httpd
[root@node1 ~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
[root@node1 ~]# netstat -utpln |grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1217/httpd 
  • 在两台node节点上安装keepalived软件程序(两台安装步骤一致,在此只列出一台)
[root@node1 ~]# yum -y install kernel-devel openssl-devel popt-devel        ##安装内核开发包,popt支持库等工具
[root@node1 ~]# tar -zxvf keepalived-1.2.13.tar.gz -C /usr/src/
[root@node1 ~]# cd /usr/src/keepalived-1.2.13/
[root@node1 keepalived-1.2.13]# ./configure --prefix=/usr/local/keepalived 
[root@node1 keepalived-1.2.13]# make &&make install
[root@node1 keepalived-1.2.13]# cd
[root@node1 ~]# mkdir -p /etc/keepalived        ##程序的主配置目录
[root@node1 ~]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/        ## 复制主配置文件
[root@node1 ~]# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/       ##复制启动时需要加载的配置文件
[root@node1 ~]# cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/        ##复制服务的控制脚本
[root@node1 ~]# cp /usr/local/keepalived/sbin/keepalived /usr/sbin/     ##复制keepalived的命令
[root@node1 ~]# chmod 755 /etc/init.d/keepalived        ##为指控脚本指定权限
  • 配置node1上master主节点
[root@node1 ~]#  vi /etc/keepalived/keepalived.conf
global_defs {
    router_id HA_TEST_R1                ##本服务器的名称,若环境中有多个keepalived时,此名称不能一致
}
vrrp_instance VI_1 {                    ##定义VRRP热备实例,每一个keep组都不同
    state MASTER                                ##MASTER表示主服务器
    interface eth0                              ##承载VIP地址的物理接口
    virtual_router_id 1                 ##虚拟路由器的ID号,每一个keep组都不同
    priority 100                                ##优先级,数值越大优先级越高
    advert_int 1                                ##通告检查间隔秒数(心跳频率)
    authentication {                    ##认证信息
        auth_type PASS          ##认证类型
        auth_pass 123456                ##密码字串
    }
    virtual_ipaddress {
  192.168.100.95                                ##指定漂移地址(VIP)
    }
}
virtual_server 192.168.100.95 80 {       #vip配置
    delay_loop 2                                 #每隔2秒检查一次real_server状态
    #lb_algo wrr                    ##指定lvs的调度算法
    #lb_kind DR                 ##lvs集群模式(如若不结合LVS请删掉两个配置)
    persistence_timeout 60              ##会话保持时间
    protocol TCP                                        ##选择协议
    real_server 192.168.100.105 80 {             ##本机地址
        weight :3                               ##服务器的权重
        notify_down /etc/keepalived/check.sh            ##指定节点失效后,采用的脚本,notify_up表示节点正常后,采用的脚本
                ##健康检查方式一共有HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK这些
        TCP_CHECK {
            connect_timeout 10          ##连接超时时间
            nb_get_retry 3      ##重连次数
            delay_before_retry 3        ##重连间隔时间
                        connect_port 80         ##健康检查端口
        }
    }
   }
[root@node1 ~]# vi /etc/keepalived/check.sh
#!/bin/bash
/etc/init.d/keepalived stop
echo -e "$(ip a |grep eth0 |grep inet |awk '{print $2}'|awk -F'/' '{print $1}') (httpd) is down on $(date +%F-%T)" >>/root/check_httpd.log
:wq
[root@node1 ~]# chmod 777 /etc/keepalived/check.sh
[root@node1 ~]# /etc/init.d/keepalived start
Starting keepalived (via systemctl):                       [  确定  ]
[root@node1 ~]# ip a |grep 192.168.100.95
    inet 192.168.100.95/32 scope global eth0
  • 配置node2上backup从节点
[root@node2 ~]# vi /etc/keepalived/keepalived.conf
global_defs {
    router_id HA_TEST_R2            ##本服务器的名称
}
vrrp_instance VI_1 {
    state BACKUP                    ##BACKUP表示从服务器
    interface eth0
    virtual_router_id 1
    priority 99                 ##优先级,低于主服务器
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        192.168.100.95
    }
}
virtual_server 192.168.100.95 80 {   ##vip配置
    delay_loop 2                     ##每隔2秒检查一次real_server状态
    #lb_algo wrr
    #lb_kind DR                 ##如若不结合LVS,需要去掉两个配置项
    persistence_timeout 60           ##会话保持时间
    protocol TCP
    real_server 192.168.100.106 80 {    ##本机地址
        weight :3
        notify_down /etc/keepalived/check.sh
        TCP_CHECK {
            connect_timeout 10          ##连接超时时间
            nb_get_retry 3          ##重连次数
            delay_before_retry 3        ##重连间隔时间
            connect_port 80             ##健康检查端口
        }
    }
   }
:wq
[root@node2 ~]# vi /etc/keepalived/check.sh
#!/bin/bash
/etc/init.d/keepalived stop
echo -e "$(ip a |grep eth0 |grep inet |awk '{print $2}'|awk -F'/' '{print $1}') (httpd) is down on $(date +%F-%T)" >>/root/check_httpd.log
:wq
[root@node2 ~]# chmod 777 /etc/keepalived/check.sh
[root@node2 ~]# /etc/init.d/keepalived start
  • 客户端访问测试双机热备的效果
    当node1与node2均正常状态

    当node1的httpd服务关闭
[root@node1 ~]# systemctl stop httpd
[root@node1 ~]# /etc/init.d/keepalived status
¡ñ keepalived.service - SYSV: Start and stop Keepalived
   Loaded: loaded (/etc/rc.d/init.d/keepalived; bad; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:systemd-sysv-generator(8)

8ÔÂ 24 21:28:57 node1.linux.com Keepalived_healthcheckers[2860]: Netlink reflector reports IP 192.168.100.95 added
8ÔÂ 24 21:29:02 node1.linux.com Keepalived_vrrp[2861]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.100.95
8ÔÂ 24 21:36:44 node1.linux.com Keepalived_healthcheckers[2860]: TCP connection to [192.168.100.105]:80 failed !!!
8ÔÂ 24 21:36:44 node1.linux.com Keepalived_healthcheckers[2860]: Removing service [192.168.100.105]:80 from VS [192.168.100.95]:80
8ÔÂ 24 21:36:44 node1.linux.com Keepalived_healthcheckers[2860]: IPVS: Service not defined
8ÔÂ 24 21:36:44 node1.linux.com Keepalived_healthcheckers[2860]: Executing [/etc/keepalived/check.sh] for service [192.168.100.105]:80 in VS [192.168.100.95]:80
8ÔÂ 24 21:36:44 node1.linux.com Keepalived_healthcheckers[2860]: Lost quorum 1-0=1 > 0 for VS [192.168.100.95]:80
8ÔÂ 24 21:36:44 node1.linux.com systemd[1]: Stopping SYSV: Start and stop Keepalived...
8ÔÂ 24 21:36:44 node1.linux.com keepalived[2926]: Stopping keepalived: [  确定 ]
8ÔÂ 24 21:36:44 node1.linux.com systemd[1]: Stopped SYSV: Start and stop Keepalived.

将node1的httpd和keepalived服务重新启动

[root@node1 ~]# systemctl start httpd
[root@node1 ~]# /etc/init.d/keepalived start
Starting keepalived (via systemctl):                       [  确定  ]
[root@node1 ~]# /etc/init.d/keepalived status
¡ñ keepalived.service - SYSV: Start and stop Keepalived
   Loaded: loaded (/etc/rc.d/init.d/keepalived; bad; vendor preset: disabled)
   Active: active (running) since Èý 2022-08-24 21:38:10 CST; 4s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 2979 ExecStart=/etc/rc.d/init.d/keepalived start (code=exited, status=0/SUCCESS)
 Main PID: 2986 (keepalived)
   CGroup: /system.slice/keepalived.service
           ©À©¤2986 keepalived -D
           ©À©¤2988 keepalived -D
           ©¸©¤2989 keepalived -D

8ÔÂ 24 21:38:11 node1.linux.com Keepalived_healthcheckers[2988]: IPVS: Scheduler or persistence engine not found
8ÔÂ 24 21:38:11 node1.linux.com Keepalived_healthcheckers[2988]: IPVS: No such process
8ÔÂ 24 21:38:11 node1.linux.com Keepalived_healthcheckers[2988]: Using LinkWatch kernel netlink reflector...
8ÔÂ 24 21:38:11 node1.linux.com Keepalived_healthcheckers[2988]: Activating healthchecker for service [192.168.100.105]:80
8ÔÂ 24 21:38:11 node1.linux.com Keepalived_vrrp[2989]: VRRP_Instance(VI_1) Transition to MASTER STATE
8ÔÂ 24 21:38:11 node1.linux.com Keepalived_vrrp[2989]: VRRP_Instance(VI_1) Received lower prio advert, forcing new election
8ÔÂ 24 21:38:12 node1.linux.com Keepalived_vrrp[2989]: VRRP_Instance(VI_1) Entering MASTER STATE
8ÔÂ 24 21:38:12 node1.linux.com Keepalived_vrrp[2989]: VRRP_Instance(VI_1) setting protocol VIPs.
8ÔÂ 24 21:38:12 node1.linux.com Keepalived_vrrp[2989]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.100.95
8ÔÂ 24 21:38:12 node1.linux.com Keepalived_healthcheckers[2988]: Netlink reflector reports IP 192.168.100.95 added

将node1节点的httpd和keepalived服务重新启动后,发现node1节点重新抢占了master主节点,如若不想实现node节点自动抢占,可在主从节点配置文件中修改如下:


李泽信 发布于 2022-8-24 20:13

ansible(一)

一、ansible自动化工具

  • 概述
    ansible是基于Python开发,集合了众多优秀运维工具的优点,实现批量运行命令、程序部署、配置系统等功能。默认通过SSH协议进行远程命令执行或下发配置,无需部署任何客户端代理软件,从何使得自动化环境部署变得更加简单。可同时支持多台主机并行管理,使得管理主机更加便捷。
  • ansible特性功能
    应用代码自动化部署、系统管理自动化、支持持续交付自动化、支持云计算、大数据平台环境、轻量级,无需客户端安装agent,更新时只需在控制台更新即可,批量任务执行可写成脚本,不用分发到远程就可执行、支持非root用户管理操作,支持sudo、使用python编写,维护更简单。

二、ansible实现原理

  • 内部组件
1.Ansible core核心引擎:
2.Host inventory主机清单:用来定义Ansible所管理的主机,默认是在Ansible的hosts配置文件中定义被管理主机,同时也支持自定义动态主机清单和指定其他配置文件的位置;
3.Connection plugins连接插件:负责和被管理主机实现通信。除支持使用SSH连接被管理主机外,Ansible还支持其他的连接方式,所以需要有连接插件将各个主机用连接插件连接到Ansible;
4.Playbooks(yam1,yam2)剧本:用来集中定义Ansible任务的配置文件,即将多个任务定义在一个剧本中由Ansible自动执行,可以由控制主机针对多台被管理主机同时运行多个任务;
5.Core modules核心模块:是Ansible自带的模块,使用这些模块将资源分发到被管理主机,使其执行特定任务或匹配特定的状态;
6.Custom modules自定义模块:用于完成模块功能的补充,可借助相关插件完成记录日志、发送邮件等功能;
  • 实现过程
  • 核心命令

三、安装ansible

系统环境 IP地址 主机名 所需软件
centos7.8 192.168.100.101 ansible ansible
centos7.8 192.168.100.102 slave1
centos7.8 192.168.100.103 slave2
  • 在管理节点进行安装ansible并配置被管理主机
[root@ansible ~]# wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
[root@ansible ~]# yum -y install ansible
[root@ansible ~]# rpm -qa ansible
ansible-2.9.27-1.el7.noarch
[root@ansible ~]# rpm -qc ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts
[root@ansible ~]# ls /etc/ansible/
ansible.cfg                     ##主配置文件
hosts                       ##定义被管理主机IP或主机名
roles                           ##角色或者插件路径,默认该目录为空

[root@ansible ~]# vi /etc/ansible/hosts     #配置被管理主机列表,本机也可以是被管理主机
[webservers]
192.168.100.102
192.168.100.103

#主配置文件
inventory = /etc/ansible/hosts      #这个参数表示资源清单inventory文件的位置
library = /usr/share/ansible        #指向存放Ansible模块的目录,支持多个目录方式,只要用冒号(:)隔开就可以
forks = 5       #并发连接数,默认为5
sudo_user = root        #设置默认执行命令的用户
remote_port = 22        #指定连接被管节点的管理端口,默认为22端口,建议修改,能够更加安全
host_key_checking = False       #设置是否检查SSH主机的密钥,值为True/False。关闭后第一次连接不会提示配置实例
timeout = 60        #设置SSH连接的超时时间,单位为秒
log_path = /var/log/ansible.log     #指定一个存储ansible日志的文件(默认不记录日志)
  • ansible命令详解
    命令格式如下:
ansible <host-pattern>  [-m module_name] [-a args] [options]

<host-pattern> :指定主机组或IP
[-m module_name] : 指定调用模块
[-a args] [options] : 传递给模块的参数

-a MODULE_ARGS   #模块的参数,如果执行默认COMMAND的模块,即是命令参数,如: “date”,“pwd”等等
-k,--ask-pass #ask for SSH password。登录密码,提示输入SSH密码而不是假设基于密钥的验证
--ask-su-pass #ask for su password。su切换密码
-K,--ask-sudo-pass #ask for sudo password。提示密码使用sudo,sudo表示提权操作
--ask-vault-pass #ask for vault password。假设我们设定了加密的密码,则用该选项进行访问
-B SECONDS #后台运行超时时间
-C #模拟运行环境并进行预运行,可以进行查错测试
-c CONNECTION #连接类型使用
-f FORKS #并行任务数,默认为5
-i INVENTORY #指定主机清单的路径,默认为/etc/ansible/hosts
--list-hosts #查看有哪些主机组
-m MODULE_NAME #执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数
-o #压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用
-S #用 su 命令
-R SU_USER #指定 su 的用户,默认为 root 用户
-s #用 sudo 命令
-U SUDO_USER #指定 sudo 到哪个用户,默认为 root 用户
-T TIMEOUT #指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改
-u REMOTE_USER #远程用户,默认为 root 用户
-v #查看详细信息,同时支持-vvv,-vvvv可查看更详细信息

常用命令

ansible test --list-hosts # 列出执行主机列表
ansible-doc -l  # 查看所有模块   (键入q退出)
ansible-doc command # 查看command模块详细信息
ansible-doc -s command  # 查看command模块详细用法
ansible test -m command -a 'df -h'  # 对所有被控服务器使用df -h 命令
ansible web -m command -a 'useradd Tom' # 批量添加用户
  • ansible ping模块
    作用:测试被管理主机的连通性;
[root@ansible ~]# ssh-keygen -t rsa
[root@ansible ~]# ssh-copy-id root@192.168.100.102
[root@ansible ~]# ssh-copy-id root@192.168.100.103
[root@ansible ~]# ansible -k all -m ping
SSH password: 123123
192.168.100.102 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.100.103 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
  • ansible command模块
    作用:在被管理主机上执行shell命令,默认就是此模块;
chdir       ##执行命令前,切换到该目录
creates     ##当该文件存在时,则不执行该步骤
executable  ##换用其他shell环境执行命令
free_form   ##需要执行的脚本
removes     ##当该文件不存在时,则不执行该步骤

例如

[root@ansible ~]# ansible webservers -a 'chdir=/root/ ls'       ##切换到该路径,执行ls命令
192.168.100.103 | CHANGED | rc=0 >>
anaconda-ks.cfg
apache-tomcat-9.0.10.tar.gz
jdk-8u171-linux-x64.tar.gz
192.168.100.102 | CHANGED | rc=0 >>
anaconda-ks.cfg
apache-tomcat-9.0.10.tar.gz
jdk-8u171-linux-x64.tar.gz

[root@ansible ~]# ansible webservers -a 'creates=/etc/fstab ls /root'       ##如果该文件存在,则不执行ls /root命令
192.168.100.103 | SUCCESS | rc=0 >>
skipped, since /etc/fstab exists
192.168.100.102 | SUCCESS | rc=0 >>
skipped, since /etc/fstab exists

[root@ansible ~]# ansible webservers -a 'removes=/etc/fstab ls /root'       ##如果该文件存在,则执行ls /root
192.168.100.102 | CHANGED | rc=0 >>
anaconda-ks.cfg
apache-tomcat-9.0.10.tar.gz
jdk-8u171-linux-x64.tar.gz
192.168.100.103 | CHANGED | rc=0 >>
anaconda-ks.cfg
apache-tomcat-9.0.10.tar.gz
jdk-8u171-linux-x64.tar.gz
  • ansible copy模块
    作用:复制ansible节点的文件到被管理主机;
src         ##源文件位置
content     ##手动编写源文件内容
dest        ##目标主机上的目标文件位置
mode        ##设置文件权限
owner       ##设置文件属性
group       ##设置文件属组
force       ##强制覆盖文件
backup      ##当文件内容发生改变后,再覆盖前备份源文件,备份文件包含时间信息
directory_mode      ##递归设定目录的权限,默认为系统默认权限
others      ##所有的file模块中的选项可以在这里使用
1.复制文件
[root@ansible ~]# ansible webservers -m copy -a 'src=/root/1.sh dest=/root/hello'
192.168.100.103 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "2c7123d6102ba1c47057f51fa46ebad71bbfb3a5", 
    "dest": "/root/hello", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "path": "/root/hello", 
    "size": 19, 
    "state": "file", 
    "uid": 0
}
192.168.100.102 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "2c7123d6102ba1c47057f51fa46ebad71bbfb3a5", 
    "dest": "/root/hello", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "path": "/root/hello", 
    "size": 19, 
    "state": "file", 
    "uid": 0
}

2.给定内容生成文件,并制定权限
[root@ansible ~]# ansible webservers -m copy -a 'content="I am keer\n" dest=/root/name mode=666'
192.168.100.103 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "0421570938940ea784f9d8598dab87f07685b968", 
    "dest": "/root/name", 
    "gid": 0, 
    "group": "root", 
    "mode": "0666", 
    "owner": "root", 
    "path": "/root/name", 
    "size": 10, 
    "state": "file", 
    "uid": 0
}
192.168.100.102 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "0421570938940ea784f9d8598dab87f07685b968", 
    "dest": "/root/name", 
    "gid": 0, 
    "group": "root", 
    "mode": "0666", 
    "owner": "root", 
    "path": "/root/name", 
    "size": 10, 
    "state": "file", 
    "uid": 0
}
查看生成文件的权限
[root@ansible ~]# ansible webservers -m shell -a 'ls -l /root'
192.168.100.102 | CHANGED | rc=0 >>
总用量 196060
-rw-------. 1 root root      1262 1月  23 2019 anaconda-ks.cfg
-rw-r--r--  1 root root   9858504 10月 30 2021 apache-tomcat-9.0.10.tar.gz
-rw-r--r--  1 root root        19 8月  24 15:48 hello
-rw-r--r--  1 root root 190890122 10月 30 2021 jdk-8u171-linux-x64.tar.gz
-rw-rw-rw-  1 root root        10 8月  24 15:58 name
192.168.100.103 | CHANGED | rc=0 >>
总用量 196060
-rw-------. 1 root root      1262 1月  23 2019 anaconda-ks.cfg
-rw-r--r--  1 root root   9858504 10月 30 2021 apache-tomcat-9.0.10.tar.gz
-rw-r--r--  1 root root        19 8月  24 15:48 hello
-rw-r--r--  1 root root 190890122 10月 30 2021 jdk-8u171-linux-x64.tar.gz
-rw-rw-rw-  1 root root        10 8月  24 15:58 name

3.覆盖
[root@ansible ~]# ansible webservers -m copy -a 'content="hello world\n" backup=yes dest=/root/name mode=666'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/root/name.4722.2022-08-24@16:01:49~", 
    "changed": true, 
    "checksum": "22596363b3de40b06f981fb85d82312e8c0ed511", 
    "dest": "/root/name", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "6f5902ac237024bdd0c176cb93063dc4", 
    "mode": "0666", 
    "owner": "root", 
    "size": 12, 
    "src": "/root/.ansible/tmp/ansible-tmp-1661328108.07-16905-102450375068468/source", 
    "state": "file", 
    "uid": 0
}
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/root/name.18438.2022-08-24@16:01:49~", 
    "changed": true, 
    "checksum": "22596363b3de40b06f981fb85d82312e8c0ed511", 
    "dest": "/root/name", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "6f5902ac237024bdd0c176cb93063dc4", 
    "mode": "0666", 
    "owner": "root", 
    "size": 12, 
    "src": "/root/.ansible/tmp/ansible-tmp-1661328108.08-16906-87257431749426/source", 
    "state": "file", 
    "uid": 0
}
查看文件及备份情况
[root@ansible ~]# ansible webservers -m shell -a 'ls -l /root'
192.168.100.103 | CHANGED | rc=0 >>
总用量 196064
-rw-------. 1 root root      1262 1月  23 2019 anaconda-ks.cfg
-rw-r--r--  1 root root   9858504 10月 30 2021 apache-tomcat-9.0.10.tar.gz
-rw-r--r--  1 root root        19 8月  24 15:48 hello
-rw-r--r--  1 root root 190890122 10月 30 2021 jdk-8u171-linux-x64.tar.gz
-rw-rw-rw-  1 root root        12 8月  24 16:01 name
-rw-rw-rw-  1 root root        10 8月  24 15:58 name.18438.2022-08-24@16:01:49~
192.168.100.102 | CHANGED | rc=0 >>
总用量 196064
-rw-------. 1 root root      1262 1月  23 2019 anaconda-ks.cfg
-rw-r--r--  1 root root   9858504 10月 30 2021 apache-tomcat-9.0.10.tar.gz
-rw-r--r--  1 root root        19 8月  24 15:48 hello
-rw-r--r--  1 root root 190890122 10月 30 2021 jdk-8u171-linux-x64.tar.gz
-rw-rw-rw-  1 root root        12 8月  24 16:01 name
-rw-rw-rw-  1 root root        10 8月  24 15:58 name.4722.2022-08-24@16:01:49~
[root@ansible ~]# ansible webservers -m shell -a 'cat /root/name'
192.168.100.103 | CHANGED | rc=0 >>
hello world
192.168.100.102 | CHANGED | rc=0 >>
hello world
  • ansible yum模块
    作用:在被管理主机上yum安装软件包;
name        ##软件包名称
state       ##软件包状态,present表示安装,absent表示卸载,latest安装最新
update_cache        ##安装软件前更新缓存
enablerepo      ##指定yum源名称
conf_file       ##指定yum安装时所加载的yum配置文件
disable_pgp_check       ##是否禁止GPG checking,只用于present or latest
disablerepo     ##临时禁止使用yum库,只用于安装或更新
enablerepo      ##临时使用的yum库,只用于安装或更新

例如

安装httpd
[root@ansible ~]# ansible webservers -m yum -a 'name=httpd state=present'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-67.el7.centos will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package       Arch           Version                       Repository     Size\n================================================================================\nInstalling:\n httpd         x86_64         2.4.6-67.el7.centos           local         2.7 M\n\nTransaction Summary\n================================================================================\nInstall  1 Package\n\nTotal download size: 2.7 M\nInstalled size: 9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : httpd-2.4.6-67.el7.centos.x86_64                             1/1 \n  Verifying  : httpd-2.4.6-67.el7.centos.x86_64                             1/1 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-67.el7.centos                                            \n\nComplete!\n"
    ]
}
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-67.el7.centos will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package       Arch           Version                       Repository     Size\n================================================================================\nInstalling:\n httpd         x86_64         2.4.6-67.el7.centos           local         2.7 M\n\nTransaction Summary\n================================================================================\nInstall  1 Package\n\nTotal download size: 2.7 M\nInstalled size: 9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : httpd-2.4.6-67.el7.centos.x86_64                             1/1 \n  Verifying  : httpd-2.4.6-67.el7.centos.x86_64                             1/1 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-67.el7.centos                                            \n\nComplete!\n"
    ]
}

启动验证
[root@ansible ~]# ansible webservers   -a 'systemctl start httpd'
[root@ansible ~]# ansible webservers   -a 'netstat -utpln |grep 80'
192.168.100.103 | CHANGED | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      19935/httpd         
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      856/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1009/master         
udp        0      0 127.0.0.1:323           0.0.0.0:*                           637/chronyd         
192.168.100.102 | CHANGED | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      6218/httpd          
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      855/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1008/master         
udp        0      0 127.0.0.1:323           0.0.0.0:*                           636/chronyd 

卸载httpd

[root@ansible ~]# ansible webservers -m yum -a 'name=httpd state=absent'
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "removed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-67.el7.centos 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package       架构           版本                         源              大小\n================================================================================\n正在删除:\n httpd         x86_64         2.4.6-67.el7.centos          @local         9.4 M\n\n事务概要\n================================================================================\n移除  1 软件包\n\n安装大小:9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  正在删除    : httpd-2.4.6-67.el7.centos.x86_64                            1/1 \n  验证中      : httpd-2.4.6-67.el7.centos.x86_64                            1/1 \n\n删除:\n  httpd.x86_64 0:2.4.6-67.el7.centos                                            \n\n完毕!\n"
    ]
}
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "removed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-67.el7.centos 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package       架构           版本                         源              大小\n================================================================================\n正在删除:\n httpd         x86_64         2.4.6-67.el7.centos          @local         9.4 M\n\n事务概要\n================================================================================\n移除  1 软件包\n\n安装大小:9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  正在删除    : httpd-2.4.6-67.el7.centos.x86_64                            1/1 \n  验证中      : httpd-2.4.6-67.el7.centos.x86_64                            1/1 \n\n删除:\n  httpd.x86_64 0:2.4.6-67.el7.centos                                            \n\n完毕!\n"
    ]
}
  • ansible file模块
    作用:该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。

state       ##状态:
                    directory为目录,不存在则创建
                    touch为文件,不存在则创建,存在则更新其为最后修改时间
                    file即使文件不存在也不创建
                    link创建软链接
                    hard创建硬链接
                    absent删除目录、文件或者取消链接文件
owner       ##属主,后面必须跟上     path        ##目标位置
group       ##属组,后面可以加上      mode   ##文件/目录权限
dest        ##被链接的路径,只应用于state=link的情况

例如

1.创建目录
[root@ansible ~]# ansible webservers -m file -a 'path=/root/app state=directory'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/root/app", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/root/app", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}

查看验证
[root@ansible ~]# ansible webservers -m shell -a 'ls -l /root'
192.168.100.102 | CHANGED | rc=0 >>
总用量 196064
-rw-------. 1 root root      1262 1月  23 2019 anaconda-ks.cfg
-rw-r--r--  1 root root   9858504 10月 30 2021 apache-tomcat-9.0.10.tar.gz
drwxr-xr-x  2 root root         6 8月  24 16:42 app
-rw-r--r--  1 root root        19 8月  24 15:48 hello
-rw-r--r--  1 root root 190890122 10月 30 2021 jdk-8u171-linux-x64.tar.gz
-rw-rw-rw-  1 root root        12 8月  24 16:01 name
-rw-rw-rw-  1 root root        10 8月  24 15:58 name.4722.2022-08-24@16:01:49~
192.168.100.103 | CHANGED | rc=0 >>
总用量 196064
-rw-------. 1 root root      1262 1月  23 2019 anaconda-ks.cfg
-rw-r--r--  1 root root   9858504 10月 30 2021 apache-tomcat-9.0.10.tar.gz
drwxr-xr-x  2 root root         6 8月  24 16:42 app
-rw-r--r--  1 root root        19 8月  24 15:48 hello
-rw-r--r--  1 root root 190890122 10月 30 2021 jdk-8u171-linux-x64.tar.gz
-rw-rw-rw-  1 root root        12 8月  24 16:01 name
-rw-rw-rw-  1 root root        10 8月  24 15:58 name.18438.2022-08-24@16:01:49~

2.创建链接文件
[root@ansible ~]# ansible webservers -m file -a 'path=/root/bbb.jpg src=aaa.jpg state=link'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/root/bbb.jpg", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 7, 
    "src": "aaa.jpg", 
    "state": "link", 
    "uid": 0
}
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/root/bbb.jpg", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 7, 
    "src": "aaa.jpg", 
    "state": "link", 
    "uid": 0
}
验证查看
[root@ansible ~]# ansible webservers -m shell -a 'ls -l /root'
192.168.100.102 | CHANGED | rc=0 >>
总用量 196064
-rw-r--r--  1 root root         0 8月  24 16:57 aaa.jpg
lrwxrwxrwx  1 root root         7 8月  24 16:58 bbb.jpg -> aaa.jpg
192.168.100.103 | CHANGED | rc=0 >>
总用量 196064
-rw-r--r--  1 root root         0 8月  24 16:57 aaa.jpg
lrwxrwxrwx  1 root root         7 8月  24 16:58 bbb.jpg -> aaa.jpg

3.删除文件
[root@ansible ~]# ansible webservers -m file -a 'path=/root/name state=absent'
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/root/name", 
    "state": "absent"
}
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/root/name", 
    "state": "absent"
}
查看验证
[root@ansible ~]# ansible webservers -m shell -a 'ls /root/name'
192.168.100.102 | FAILED | rc=2 >>
ls: 无法访问/root/name: 没有那个文件或目录non-zero return code
192.168.100.103 | FAILED | rc=2 >>
ls: 无法访问/root/name: 没有那个文件或目录non-zero return code
  • ansible user模块
    作用:在被管理主机上创建用户或者组
name            ##用户名
home            ##家目录位置
shell           ##指定登录shell
uid             ##指定用户uid
state           ##状态,不指定为新建,absent为删除
force           ##强制删除
comment         ##用户的描述信息
createhome      ##是否创建家目录
group           ##指定基本组
groups          ##指定附加组,如果指定为(groups=)表示删除所有组
move_home       ##如果设置为home=时,试图将用户主目录移动到指定的目录
non_unique      ##该选项允许改变非唯一的用户ID值
password        ##指定用户密码
remove          ##在使用state=absent时,行为是userdel -remove一致
system          ##当创建一个用户,设置这个用户是系统用户。这个设置不能跟更改现有用户

例如

1.添加用户
[root@ansible ~]# ansible webservers -m user -a 'name=zhangsan uid=111111'
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 1000, 
    "home": "/home/zhangsan", 
    "name": "zhangsan", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 111111
}
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 1000, 
    "home": "/home/zhangsan", 
    "name": "zhangsan", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 111111
}

查看验证
[root@ansible ~]# ansible webservers -m shell -a 'cat /etc/passwd |grep zhangsan'
192.168.100.103 | CHANGED | rc=0 >>
zhangsan:x:111111:1000::/home/zhangsan:/bin/bash
192.168.100.102 | CHANGED | rc=0 >>
zhangsan:x:111111:1000::/home/zhangsan:/bin/bash

2.删除用户
[root@ansible ~]# ansible webservers -m user -a 'name=zhangsan state=absent'
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "zhangsan", 
    "remove": false, 
    "state": "absent"
}
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "zhangsan", 
    "remove": false, 
    "state": "absent"
}

查看验证
[root@ansible ~]# ansible webservers -m shell -a 'cat /etc/passwd |grep zhangsan'
192.168.100.103 | FAILED | rc=1 >>
non-zero return code
192.168.100.102 | FAILED | rc=1 >>
non-zero return code
  • ansible cron模块
    作用:在被管理主机上执行计划任务程序
name            ##计划任务名称
minute          ##分钟
hour            ##小时
day             ##日
month           ##月
weekday         ##周
job             ##指定运行的命令是什么
reboot          ##任务在重启时运行,不建议使用,建议使用special_time
special_time        ##特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
state           ##指定状态,present表示添加定时任务,也是默认设置,absent表示删除定时任务
user            ##以哪个用户的身份执行

例如

1.添加计划任务
[root@ansible ~]# ansible webservers -m cron -a 'name="ntp update every 5 min"  minute=*/5 job="/sbin/ntpdate 192.168.100.101 &> /dev/null"'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "ntp update every 5 min"
    ]
}
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "ntp update every 5 min"
    ]
}

验证查看
[root@ansible ~]# ansible webservers -m shell -a 'crontab -l'
192.168.100.103 | CHANGED | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 192.168.100.101 &> /dev/null
192.168.100.102 | CHANGED | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 192.168.100.101 &> /dev/null

2.删除计划任务
[root@ansible ~]# ansible webservers -m cron -a 'name="ntp update every 5 min" minute=*/5 job="/sbin/ntpdate 192.168.100.101 &> /dev/null" state=absent'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": []
}
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": []
}

查看验证
[root@ansible ~]# ansible webservers -m shell -a 'crontab -l'
192.168.100.103 | CHANGED | rc=0 >>

192.168.100.102 | CHANGED | rc=0 >>
  • ansible shell模块
    作用:用于执行远端主机上的shell命令或脚本,支持比command更多的指令;
[root@ansible ~]# ansible webservers -m shell -a 'cat /etc/passwd |grep root'
192.168.100.102 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
192.168.100.103 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
  • ansible setup模块
    作用:获取远端主机的系统所有信息;
[root@ansible ~]# ansible 192.168.100.102 -m setup
192.168.100.102 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.100.102"
        ], 
        "ansible_all_ipv6_addresses": [], 
        "ansible_apparmor": {
            "status": "disabled"
        }, 
        "ansible_architecture": "x86_64", 
        "ansible_bios_date": "07/02/2015", 
        "ansible_bios_version": "6.00", 
        "ansible_cmdline": {
            "BOOT_IMAGE": "/vmlinuz-3.10.0-693.el7.x86_64", 
            "ipv6.disable": "1", 
            "net.ifnames": "0", 
            "quiet": true, 
            "rd.lvm.lv": "centos/swap", 
            "rhgb": true, 
            "ro": true, 
            "root": "/dev/mapper/centos-root"
        }, 
  • ansible service模块
    作用:用于服务程序的启动
arguments           ##命令行提供额外的参数
enabled             ##设置开机启动
name=               ##服务名称
runlevel            ##开机启动的级别,一般不指定
sleep               ##再重启服务的过程中,是否等待。如在服务关闭以后等待2秒在启动。(定义在剧本中)
state               ##有四种状态,分别为:started--->启动服务,stopped--->停止服务,restarted--->重启服务,reloaded--->重载配置

例如:

1.启动httpd服务
[root@ansible ~]# ansible webservers -m service -a 'name=httpd state=started enabled=true'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "enabled": true, 
    "name": "httpd", 
    "state": "started",
    ...
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "enabled": true, 
    "name": "httpd", 
    "state": "started",
    ...

验证查看
[root@ansible ~]# ansible webservers -m shell -a 'ss -ntl'
192.168.100.102 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:80                       *:*  
192.168.100.103 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:80                       *:*

2.关闭httpd服务
[root@ansible ~]# ansible webservers -m service -a 'name=httpd state=stopped'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "httpd", 
    "state": "stopped",
    ...
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "httpd", 
    "state": "stopped", 
    ...

验证查看
[root@ansible ~]# ansible webservers -m shell -a 'ss -ntl|grep 80'
192.168.100.103 | FAILED | rc=1 >>
non-zero return code
192.168.100.102 | FAILED | rc=1 >>
non-zero return code
  • ansible group模块
    作用:该模块主要用于添加或删除组
gid         ##设置组的GID
name=       ##指定组的名称
state=      ##指定组的状态,默认为创建,设置值为absent删除
system=     ##设置为yes,表示创建为系统组

例如:

1.创建组
[root@ansible ~]# ansible web -m group -a 'name=happy gid=12222'
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 12222, 
    "name": "happy", 
    "state": "present", 
    "system": false
}
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 12222, 
    "name": "happy", 
    "state": "present", 
    "system": false
}

验证查看
[root@ansible ~]# ansible web -m shell -a 'cat /etc/group |grep 12222'
192.168.100.102 | CHANGED | rc=0 >>
happy:x:12222:
192.168.100.103 | CHANGED | rc=0 >>
happy:x:12222:

2.删除组
[root@ansible ~]# ansible web -m group -a 'name=happy state=absent'
192.168.100.103 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "happy", 
    "state": "absent"
}
192.168.100.102 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "happy", 
    "state": "absent"
}

验证查看
[root@ansible ~]# ansible web -m shell -a 'cat /etc/group|grep 12222'
192.168.100.102 | FAILED | rc=1 >>
non-zero return code
192.168.100.103 | FAILED | rc=1 >>
non-zero return code
  • ansible script模块
    作用:该模块用于将本机的脚本在被管理端的机器上运行
1.编辑脚本
[root@ansible ~]# vi free.sh
#!/bin/bash

date >>/root/free_total.log
free -g >>/root/free_total.log

[root@ansible ~]# chmod +x free.sh
直接运行命令实现在被管理端执行该脚本
[root@ansible ~]# ansible web -m script -a '/root/free.sh'
192.168.100.102 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.100.102 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.100.102 closed."
    ], 
    "stdout": "", 
    "stdout_lines": []
}
192.168.100.103 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.100.103 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.100.103 closed."
    ], 
    "stdout": "", 
    "stdout_lines": []
}

验证查看
[root@ansible ~]# ansible web -m shell -a 'cat /root/free_total.log'
192.168.100.102 | CHANGED | rc=0 >>
2022年 08月 25日 星期四 17:19:20 CST
              total        used        free      shared  buff/cache   available
Mem:              0           0           0           0           0           0
Swap:             1           0           1
192.168.100.103 | CHANGED | rc=0 >>
2022年 08月 25日 星期四 17:19:20 CST
              total        used        free      shared  buff/cache   available
Mem:              0           0           0           0           0           0
Swap:             1           0           1
  • ansible fetch模块
    作用:该模块用于从远程某主机复制到本地
dest            ##用来存放文件的目录
src             ##在远程获取的文件,必须是文件,不能是目录

例如

[root@ansible ~]# ansible web -m fetch -a 'src=/root/202208.file dest=/root'
192.168.100.103 | CHANGED => {
    "changed": true, 
    "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", 
    "dest": "/root/192.168.100.103/root/202208.file", 
    "md5sum": "d41d8cd98f00b204e9800998ecf8427e", 
    "remote_checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", 
    "remote_md5sum": null
}
192.168.100.102 | CHANGED => {
    "changed": true, 
    "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", 
    "dest": "/root/192.168.100.102/root/202208.file", 
    "md5sum": "d41d8cd98f00b204e9800998ecf8427e", 
    "remote_checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", 
    "remote_md5sum": null
}
可以查看到文件复制成功,要注意,文件保存的路径是我们设置的接收目录下的被管制的主机IP目录下
[root@ansible ~]# ls
192.168.100.102  192.168.100.103

李泽信 发布于 2022-8-24 09:52

WebLogic 12c介绍及安装

一、Weblogic服务概述

  • 概述
    WebLogic是美国oracle公司出品的一个application server,确切的说是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中;
  • 特点
    WebLogic Server拥有处理关键Web应用系统问题所需的性能、可扩展性和高可用性;
    对业内多种标准的全面支持,包括EJB、JSP、JMS、JDBC、XML、WML,使Web应用系统的实施更为简单;
    Weblogic服务都多个版本,例如:wls_****_generic.jar文件,他本身无自带jdk,需要手动去安装;

二、Weblogic与Tomcat区别

  • WebLogic:
    WebLogic是美国bea公司出品的一个application server,确切的说是一个基于Javaee架构的中间件,纯java开发的,最新版本WebLogic Server 9.0是迄今为止发布的最卓越的BEA应用服务器。BEA WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中。完全遵循J2EE 1.4规范;
  • Tomcat:
    Tomcat服务器是一个免费的开源的Web 应用服务器,是Apache 软件基金会的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,运行时占用的系统资源小,扩展性好,支持负载平衡与邮件服务等开发应用系统常用的功能;而且很重要的是她免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。而且由于开源,它还在不断的改进和完善中,任何一个感兴趣的程序员都可以更改它或在其中加入新的功能。

三、Weblogic部署项目的三种方式

  • 在控制台中安装部署;
  • 将部署包放在domain域中autodeploy目录下部署;
  • 用域中配置文件config.xml 进行项目的部署,在此案例中用到的事控制台安装部署,再生产环境中通过控制台部署项目也是比较实用的,可以把项目集中到一个目录下统一管理;

四、部署WebLogic 12c;

1、静默安装
系统类型 IP地址 主机名 所需软件
centos7.8 192.168.100.105 www.linux.com fmw_12.2.1.3.0_wls.jar
  • 部署jdk环境
[root@www ~]# cat <<END >>/etc/hosts
> 192.168.100.105 www.linux.com
> END
[root@localhost ~]# tar xf jdk-8u171-linux-x64.tar.gz 
[root@localhost ~]# mv jdk1.8.0_171/ /usr/local/java
[root@localhost ~]# vi /etc/profile
export JAVA_HOME=/usr/local/java
export PATH=$PATH:$JAVA_HOME/bin
[root@localhost ~]# source /etc/profile
[root@localhost ~]# java -version
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
  • root用户创建目录/opt/weblogic并授权
[root@localhost ~]# mkdir /opt/weblogic
[root@localhost ~]# chmod 777  /opt/weblogic
[root@localhost ~]# touch /opt/weblogic/oraInst.loc
[root@localhost ~]# touch /opt/weblogic/wls.rsp
[root@localhost ~]# vi /opt/weblogic/oraInst.loc
inventory_loc=/opt/weblogic/oraInventory
inst_group=weblogic
[root@localhost ~]# vi /opt/weblogic/oraInst.loc
[ENGINE]
Response File Version=1.0.0.0.0

[GENERIC]
ORACLE_HOME=/opt/weblogic/Oracle/Middleware
INSTALL_TYPE=WebLogic Server
[root@localhost ~]# mkdir /opt/weblogic/Oracle/Middleware
[root@localhost ~]# mkdir -p /opt/weblogic/Oracle/Middleware
[root@localhost ~]# chown -R weblogc:weblogic /opt/weblogic
  • 安装weblogic
在/home/weblogic目录下运行指令
[weblogic@www ~]$ $JAVA_HOME/bin/java $JAVA_OPTIONS -Xmx1024m -XX:MaxPermSize=2048m weblogic.Server
启动程序日志文件为/tmp/OraInstall2022-08-23_09-49-15PM/launcher2022-08-23_09-49-15PM.log。
正在提取安装程序... . . . . . . . . 完成
检查 CPU 速度是否大于 300 MHz。   实际为 2207.471 MHz    通过
检查交换空间: 必须大于 512 MB。   实际为 2047 MB    通过
检查此平台是否需要 64 位 JVM。   实际为64    通过 (不需要 64 位)
检查临时空间: 必须大于 300 MB。   实际为 12726 MB    通过
准备从/tmp/OraInstall2022-08-23_09-49-15PM启动 Oracle Universal Installer
日志:/tmp/OraInstall2022-08-23_09-49-15PM/install2022-08-23_09-49-15PM.log
版权所有 (c) 1996, 2017, Oracle 和/或其附属公司。保留所有权利。
正在读取响应文件...
跳过软件更新
开始检查: CertifiedVersions
预期的结果: oracle-6, oracle-7, redhat-7, redhat-6, SuSE-11, SuSE-12之一
实际结果: redhat-null
检查完成。此次检查的总体结果为: 通过
CertifiedVersions 检查: 成功。

开始检查: CheckJDKVersion
预期的结果: 1.8.0_131
实际结果: 1.8.0_171
检查完成。此次检查的总体结果为: 通过
CheckJDKVersion 检查: 成功。

已启用此会话的验证。
正在验证数据
复制文件
完成百分比: 10
完成百分比: 20
完成百分比: 30
完成百分比: 40
完成百分比: 50
完成百分比: 60
完成百分比: 70
完成百分比: 80
完成百分比: 90
完成百分比: 100

Oracle Fusion Middleware 12c WebLogic Server 和 Coherence 12.2.1.3.0 的 安装 已成功完成。
日志已成功复制到/opt/weblogic/oraInventory/logs。
  • 静默创建域
[weblogic@localhost ~]$ source /opt/weblogic/Oracle/Middleware/wlserver/server/bin/setWLSEnv.sh
CLASSPATH=/usr/local/java/lib/tools.jar:/opt/weblogic/Oracle/Middleware/wlserver/modules/features/wlst.wls.classpath.jar:

PATH=/opt/weblogic/Oracle/Middleware/wlserver/server/bin:/opt/weblogic/Oracle/Middleware/wlserver/../oracle_common/modules/thirdparty/org.apache.ant/1.9.8.0.0/apache-ant-1.9.8/bin:/usr/local/java/jre/bin:/usr/local/java/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/local/java/bin:/home/weblogic/.local/bin:/home/weblogic/bin:/opt/weblogic/Oracle/Middleware/wlserver/../oracle_common/modules/org.apache.maven_3.2.5/bin

Your environment has been set.

[weblogic@localhost ~]$ mkdir -p /opt/weblogic/Oracle/Middleware/user_projects/domains/hnDoMain
[weblogic@localhost ~]$ cd /opt/weblogic/Oracle/Middleware/user_projects/domains/hnDoMain
[weblogic@localhost hnDoMain]$ $JAVA_HOME/bin/java $JAVA_OPTIONS -Xmx1024m -XX:MaxPermSize=2048m weblogic.Server
...
Would you like the server to create a default configuration and boot? (y/n): y
...
Enter username to boot WebLogic server:weblogic
Enter password to boot WebLogic server:     ##注意密码至少8位,必须包含字符串和数字,否则会创建domain失败
For confirmation, please re-enter password required to boot WebLogic server:
...
成功后显示Server state changed to RUNNING.
  • 登录控制台
启动命令,创建域时已经启动
[weblogic@www ~]$ /opt/weblogic/Oracle/Middleware/user_projects/domains/hnDoMain/bin/startWebLogic.sh &



李泽信 发布于 2022-8-23 21:58

nginx+tomcat实现Java负载均衡

  • 项目环境
系统类型 IP地址 主机名 所需软件
centos7.8 192.168.100.101 nginx.linux.cn nginx-1.22.0.tar.gz
centos7.8 192.168.100.102 tomcat1.linux.cn apache-tomcat-9.0.10.tar.gz jdk-8u171-linux-x64.tar.gz
centos7.8 192.168.100.103 tomcat2.linux.cn apache-tomcat-9.0.10.tar.gz jdk-8u171-linux-x64.tar.gz
centos7.8 192.168.100.104 mysql.linux.cn mariadb-server、mysql
  • 安装并配置Nginx程序
[root@nginx ~]# yum -y install pcre-devel zlib-devel
[root@nginx ~]# useradd -M -s /sbin/nologin nginx
[root@nginx ~]# tar xf nginx-1.22.0.tar.gz -C /usr/src/
[root@nginx ~]# cd /usr/src/nginx-1.22.0/
[root@nginx nginx-1.22.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module
[root@nginx nginx-1.22.0]# make && make install
[root@nginx nginx-1.22.0]# cd 
[root@nginx ~]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
[root@nginx ~]# cat <<END >>/usr/lib/systemd/system/nginx.service
[Unit]
Description=nginxapi
After=network.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=kill -s HUP \$(cat /usr/local/nginx/logs/nginx.pid)
ExecStop=kill -s QUIT \$(cat /usr/local/nginx/logs/nginx.pid)
PrivateTmp=Flase

[Install]
WantedBy=multi-user.target
END
[root@nginx ~]# systemctl start nginx
[root@nginx ~]# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
[root@nginx ~]# netstat -utpln |grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      6005/nginx: master

  • 安装并配置tomcat程序,并且自定义页面(两个tomcat节点配置一致,在此列举tomcat1)
    [root@tomcat1 ~]# tar xf jdk-8u171-linux-x64.tar.gz 
    [root@tomcat1 ~]# mv jdk1.8.0_171/ /usr/local/java
    [root@tomcat1 ~]# tar xf apache-tomcat-9.0.10.tar.gz 
    [root@tomcat1 ~]# mv apache-tomcat-9.0.10 /usr/local/tomcat
    [root@tomcat1 ~]# vi /usr/local/tomcat/bin/catalina.sh
    #!/bin/sh
    JAVA_OPTS="-Xms512m -Xmx1024m -Xss1024K -XX:PermSize=512m -XX:MaxPermSize=1024m"
    export CATALINA_HOME=/usr/local/tomcat
    export JRE_HOME=/usr/local/java/jre
    export JAVA_HOME=/usr/local/java/jdk1.8.0_171
    export TOMCAT_HOME=/usr/local/tomcat
    [root@tomcat1 ~]#  /usr/local/tomcat/bin/startup.sh
    [root@tomcat1 ~]# netstat -utpln |grep 8080
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1192/java

[root@tomcat1 ~]# vi /usr/local/tomcat/conf/server.xml
150         <Context docBase="/web/webapp" path="" reloadable="false"></Context>    #在150行左右位置添加
[root@tomcat1 ~]# mkdir -p /web/webapp
[root@tomcat1 ~]# cat <<END >>/web/webapp/index.jsp
192.168.100.102
END
[root@tomcat1 ~]# /usr/local/tomcat/bin/shutdown.sh
[root@tomcat1 ~]#  /usr/local/tomcat/bin/startup.sh


  • 配置Nginx服务的反向代理
[root@nginx ~]# vi /usr/local/nginx/conf/nginx.conf
     34     upstream tomserver {
     35         server 192.168.100.102:8080 weight=1;
     36         server 192.168.100.103:8080 weight=2;
     37     }
     52     location ~\.(jsp|do|js|css|png|jpg|jpeg)$ {
     53         proxy_pass      http://tomserver;
     54     }
[root@nginx ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
  • 访问测试Nginx验证页面切换


  • 安装部署MySQL程序

[root@mysql ~]# yum -y install mariadb-server mysql
[root@mysql ~]# systemctl start mariadb
[root@mysql ~]# systemctl enable mariadb
Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.
[root@mysql ~]# netstat -utpln |grep 3306
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      1423/mysqld 
[root@mysql ~]# mysqladmin -u root password 123123
[root@mysql ~]# mysql -uroot -p123123
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 5.5.56-MariaDB MariaDB Server

Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>exit

[root@mysql ~]# ls
smbms_db.sql
[root@mysql ~]# mysql -uroot -p123123 <smbms_db.sql 
[root@mysql ~]# mysql -uroot -p123123
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| smbms              |
| test               |
+--------------------+
5 rows in set (0.00 sec)
MariaDB [(none)]> use smbms;
MariaDB [smbms]> show tables;
+-----------------+
| Tables_in_smbms |
+-----------------+
| smbms_address   |
| smbms_bill      |
| smbms_provider  |
| smbms_role      |
| smbms_user      |
+-----------------+
5 rows in set (0.00 sec)
MariaDB [smbms]> grant all on smbms.* to 'linux'@'192.168.100.102' identified by '123123';
MariaDB [smbms]> grant all on smbms.* to 'linux'@'192.168.100.103' identified by '123123';
MariaDB [smbms]>  flush privileges;
MariaDB [smbms]> exit
  • 将测试项目的文件部署到Tocmat节点(两个tomcat节点配置一致,在此列举tomcat1)
[root@tomcat1 webapp]# ls 
WebRoot
[root@tomcat1 webapp]# vi /web/webapp/WebRoot/WEB-INF/classes/database.properties
driver=com.mysql.jdbc.Driver
#在和mysql传递数据的过程中,使用unicode编码格式,并且字符集设置为utf-8
url=jdbc:mysql://192.168.100.104:3306/smbms?useUnicode=true&characterEncoding=utf-8
user=linux
password=123123
[root@tomcat1 webapp]#  vi /usr/local/tomcat/conf/server.xml
150         <Context docBase="/web/webapp/WebRoot/" path="" reloadable="false"></Context>
root@tomcat1 webapp]# /usr/local/tomcat/bin/shutdown.sh
[root@tomcat1 webapp]# /usr/local/tomcat/bin/startup.sh
  • 测试访问tomcat单点,登录超时管理系统

  • 修改Nginx配置,实现会话保持,避免登录错误

[root@nginx ~]# vi /usr/local/nginx/conf/nginx.conf
     34     upstream tomserver {
     35         ip_hash;
     36         server 192.168.100.102:8080 weight=1;
     37         server 192.168.100.103:8080 weight=2;
     38     }

  • 修改Nginx的配置,实现访问url的优化
[root@nginx ~]# vi /usr/local/nginx/conf/nginx.conf
     56         location /shopping {
     57                 rewrite ^/(.*) http://192.168.100.101/login.jsp permanent;
     58         }
[root@nginx ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx ~]# /usr/local/nginx/sbin/nginx -s reload


李泽信 发布于 2022-8-23 20:02

个人资料

搜索

日历

时间进度

    今日剩余 59.6%
    本周剩余 37.1%
    本月剩余 22.0%
    本年剩余 52.2%

访问统计