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;
- 文档(document)
-
物理结构
- .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也是用于数据恢复;
- .ns文件
详看原文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
keepalived热备应用
一、keepalived概述
- 概述
keepalived起初为lvs设计的一款强大的辅助工具,保证lvs负载调度器的故障切换以及web节点的健康状态检查,后续被应用到很多需要容错的场景下,keepalived自身基于VRRP协议--虚拟路由冗余协议,思科共有协议;
二、设计原理
-
设计模块
- core模块
为keepalived的核心组件,负责主进程的启动、维护及全局配置文件的加载和解析 - check模块
负责real server节点池的节点的健康检测 - VRRP模块在master与backup之间执行新调检测
- core模块
-
热备实现过程
将多个主机以软件的方式组成一个热备足,通过共有虚拟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
[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节点自动抢占,可在主从节点配置文件中修改如下:
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
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 &
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
[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
[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
Tomcat优化
- 定义默认页面、页面超时、禁止列出目录
[root@localhost ~]# vi /usr/local/tomcat/conf/web.xml
115 <init-param>
116 <param-name>listings</param-name>
117 <param-value>false</param-value>
118 </init-param>
##禁止列出目录
606 <session-config>
607 <session-timeout>30</session-timeout>
608 </session-config>
## 页面超时
4704 <welcome-file-list>
4705 <welcome-file>index.html</welcome-file>
4706 <welcome-file>index.htm</welcome-file>
4707 <welcome-file>index.jsp</welcome-file>
4708 </welcome-file-list>
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml
115 <!-- Define an AJP 1.3 Connector on port 8009
116 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
117 -->
[root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh
[root@localhost ~]# /usr/local/tomcat/bin/startup.sh
[root@localhost ~]# netstat -utpln |grep java
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 2354/java
tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 2354/java
- 配置网页传输压缩
注:如若有apache、nginx等做代理,tomcat则不必配置传输压缩;
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml
69 <Connector port="8080" protocol="HTTP/1.1"
70 connectionTimeout="20000"
71 redirectPort="8443"
72 compression="on" ##开启压缩
73 compressionMinSize="50" ##指定最小的压缩文件,单位是字节
74 noCompressionUserAgents="gozilla, traviata" ##此浏览器类型不进行压缩
75 compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" /> ##压缩文件的格式
-
tomcat的三种模式切换
-
先了解四个概念:
- 同步:自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写)。
- 异步:委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS(银行卡和密码),OS需要支持异步IO操作API)。
- 阻塞:ATM排队取款,你只能等待(使用阻塞IO时,Java调用会一直阻塞到读写完成才返回)。
- 非阻塞:柜台取款,取个号,然后坐在椅子上做其它事,等号广播会通知你办理,没到号你就不能去,你可以不断问大堂经理排到了没有,大堂经理如果说还没到你就不能去(使用非阻塞IO时,如果不能读写Java调用会马上返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成。
-
Java对BIO、NIO、AIO的支持:
- Java BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
- Java NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
- Java AIO(NIO.2):异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
-
BIO、NIO、AIO适用场景分析:
-
-
配置
- 模式一 Bio:tomcat 7.0版本以前默认是Bio
- 模式二Nio:tomcat 8.0版本以后默认是Nio,废弃Bio
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" ##更改位置 connectionTimeout="20000" redirectPort="8443" compression="on" compressionMinSize="50" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" /> [root@localhost bin]# tail -f ../logs/catalina.out ... 22-Aug-2022 22:51:26.479 信息 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
- 模式三Apr:
[root@localhost ~]# rpm -e apr --nodeps [root@localhost ~]# yum -y install apr apr-devel [root@localhost ~]# cp /usr/local/tomcat/bin/tomcat-native.tar.gz /root/ [root@localhost ~]# tar xf tomcat-native.tar.gz [root@localhost ~]# cd tomcat-native-1.2.17-src/native/ [root@localhost native]# ./configure --with-apr=/usr/bin/apr-1-config --with-java-home=/usr/local/java/ [root@localhost native]# make && make install Libraries have been installed in: ##安装成功的提示 /usr/local/apr/lib [root@localhost ~]# vi /usr/local/tomcat/bin/catalina.sh ##添加或追加 #!/bin/sh CATALINA_OPTS="-Djava.library.path=/usr/local/apr/lib" [root@localhost ~]# vi /usr/local/tomcat/conf/server.xml ##注意需要将https的8443端口配置项删除,不然会导致http端口8080无法启动 <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="20000" compression="on" compressionMinSize="50" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" /> [root@localhost ~]# vi /usr/local/tomcat/bin/catalina.sh export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib [root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh [root@localhost ~]# /usr/local/tomcat/bin/startup.sh [root@localhost ~]# netstat -utpln |grep java tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 4859/java tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 4859/java [root@localhost ~]# tail -f ../logs/catalina.out ... 22-Aug-2022 23:10:16.286 信息 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-apr-8080"]
-
解决重启tomcat服务后,8005端口延迟启动的问题
[root@localhost ~]# vi /usr/local/java/jre/lib/security/java.security
17 securerandom.source=file:/dev/urandom
或 117 securerandom.source=file:/dev/./random
[root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh
[root@localhost ~]# /usr/local/tomcat/bin/startup.sh
- 生产环境tomcat配置
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
URIEncoding="UTF-8" ##设置编码
maxThreads="300" ##接收客户请求最大线程数,也就是同时处理请求的最大数目,默认值为“200”,并不是配置的越大越好,事实上你即使配置成999999也是没有用的,因为这个最大值是受操作系统及相关硬件所制约的,并且最大值并不一定是最优值,所以我们追寻的应该是最优值而不是最大值。建议值为1000;
QPS(Query Per Second):每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。我们常常使用 QPS值来衡量一个服务器的性能。
QPS = 并发数 / 平均响应时间 或者 并发数 = QPS * 平均响应时间
一个系统吞吐量通常由QPS、并发数两个因素决定,每套系统的这两个值都有一个相对极限值,在应用场景访问压力下,只要某一项达到系统最高值,系统的吞吐量就上不去了,如果压力继续增大,系统的吞吐量反而会下降,原因是系统超负荷工作,上下文切换、内存等等其它消耗导致系统性能下降。所谓吞吐量这里可以理解为每秒能处理请求的次数。
所以选择一个合理的 maxThreads值,其实并不是那么容易的事。因为过多的线程只会造成,更多的内存开销,更多的CPU开销,但是对提升QPS确毫无帮助;找到最佳线程数后通过简单的设置,可以让web系统更加稳定,得到最高,最稳定的QPS输出。
通过以下几种方式来获取 maxThreads的最佳值:
(1)通过线上系统不断使用和用户的不断增长来进行性能测试,观察QPS,响应时间,这种方式会在爆发式增长时系统崩溃,如双12等。
(2)根据公式计算,服务器端最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量,这种方式有时会被误导,因为某些系统处理环节可能会耗时比较长,从而影响公式的结果。
(3)单、多用户压力测试,查看CPU的消耗,然后直接乘以百分比,再进行压测,一般这个值的附近应该就是最佳线程数量,这种方式理想场景比较适用,实际情况会比这个复杂的多。
(4)根据系统的自身情况调整,如硬件限制,系统限制,程序处理能力限制等。
(5)定期修改为不同的 maxThreads值,看服务器响应结果及用户反应。
QPS和线程数的关系:
(1)在最佳线程数量之前,QPS和线程是互相递增的关系,线程数量到了最佳线程之后,QPS持平,不在上升,甚至略有下降,同时相应时间持续上升。
(2)同一个系统而言,支持的线程数越多(最佳线程数越多而不是配置的线程数越多),QPS越高。
QPS和响应时间的关系:
(1)对于一般的web系统,响应时间一般有CPU执行时间+IO等待时间组成。
(2)CPU的执行时间减少,对QPS有实质的提升,IO时间的减少,对QPS提升不明显。如果要想明显提升QPS,优化系统的时候要着重优化CPU消耗大户。
minSpareThreads="25" ##最小空闲的线程数,Tomcat初始化时创建的 socket线程数,默认为10
maxSpareThreads="75" ##最大空闲线程数,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。默认值50
enableLookups="false" ##关闭DNS反向查询
disableUploadTimeout="true" ##该标志位表明当执行servlet时,是否允许servlet容器使用一个不同的、更长的连接超时。启用该标志位将导致在上传数据时,要么使用更长的时间完成上传,要么出现更长的超时。如果不指定,该属性为“false”。
connectionTimeout="20000" ##当请求已经被接受,但未被处理,也就是等待中的超时时间。单位为毫秒,默认值为60000。通常情况下设置为30000。
acceptCount="300" ##容许的最大连接的队列长度,一般设置为maxProcessors是其参数的1.5倍即可,默认值为100。此值设置的过大会导致排队的请求超时而未被处理。所以这个值应该是主要根据应用的访问峰值与平均值来权衡配置。
tcpNoDelay="true" ##如果为true,服务器socket会设置TCP_NO_DELAY选项,在大多数情况下可以提高性能。缺省情况下设为true。
maxProcessors="1000" ##并发处理的最大请求数,默认值为75,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程
<!-- 前端使用nginx作为反向代理,不需要启用tomcat压缩功能。
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
-->
redirectPort="8443" ##开启安全通道ssl
/>
-
JVM内存优化管理;
- JVM内存管理:
JVM管理的内存可以总体划分为两部分:堆内存Heap Memory和非堆内存Native Memory。堆内存Heap Memory:供Java应用的代码使用的;
非堆内存Native Memory:也称为C-Heap,是供JVM自身进程使用的;
Heap Memory及其内部各组成的大小可以通过JVM的一系列命令行参数来控制;
Native Memory没有相应的参数来控制大小,其大小依赖于操作系统进程的最大值; - 为什么会内存溢出:
简单理解java process memory = java heap + native memory。因此内存溢出时,首先要区分是堆内存溢出还是非堆内存溢出;
非堆内存Native Memory本质上就是因为耗尽了进程地址空间。对于HotSpot JVM来说,不断的分配直接内存,会导致如下错误信息:Allocated 1953546760 bytes of native memory before running out; -
调优JVM分配内存数据:
- 堆内存分配:
JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;
JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4;
默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;
空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制;
因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小;
说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemoryError: Heap space错误; - 非堆内存分配:
JVM使用-XX:PermSize= 设置非堆内存初始值,默认是物理内存的1/64;
JVM使用-XX:MaxPermSize= 设置最大非堆内存的大小,默认是物理内存的1/4;
说明:-XX:MaxPermSize= 设置过小会导致java.lang.OutOfMemoryError: PermGen space 就是内存溢出;
[root@localhost ~]# vi /usr/local/tomcat/bin/catalina.sh #!/bin/sh JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx2048m -XX:NewSize=512m -XX:MaxNewSize=512m" 注解: -Xms初始堆内存Heap大小,使用的最小内存,cpu性能高时此值应设的大一些; -Xmx初始堆内存heap最大值,使用的最大内存; -XX:PermSize= 设定非堆内存的初始内存大小; -XX:MaxPermSize= 设定非堆内存最大值内存大小; -XX:NewSize= 设置Yong Generation的初始值大小; -XX:MaxNewSize=设置Yong Generation的最大值大小; -Xss15120这使得Tomcat每增加一个线程(thread)就会立即消耗15M内存,而最佳值应该是128K,默认值好像是512k;
- 堆内存分配:
- JVM内存管理:
-
Executor线程池优化管理;
- 概述:Executor代表了一个线程池,可以在Tomcat组件之间共享。使用线程池的好处在于减少了创建销毁线程的相关消耗,而且可以提高线程的使用效率。
- 配置管理线程池:
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml 53 <Service name="Catalina"> 54 <Executor name="tomcatThreadPool" 55 namePrefix="catalina-exec-" 56 maxThreads="1000" 57 minSpareThreads="100" 58 maxIdleTime="60000" 59 maxQueueSize="Integer.MAX_VALUE" 60 prestartminSpareThreads="false" 61 threadPriority="5" 62 className="org.apache.catalina.core.StandardThreadExecutor"/> [root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh [root@localhost ~]# /usr/local/tomcat/bin/startup.sh #注解: name:线程池名称,用于 Connector中指定。 namePrefix:所创建的每个线程的名称前缀,单独的线程名称为 namePrefix+threadNumber。 maxThreads:池中最大线程数。 minSpareThreads:活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在。 maxIdleTime:线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒。 maxQueueSize:在被执行前最大线程排队数目,默认为Int的最大值,也就是广义的无限。除非特殊情况,这个值不需要更改,否则会有请求不会被处理的情况发生。 prestartminSpareThreads:启动线程池时是否启动。 minSpareThreads部分线程。默认值为false,即不启动。 threadPriority:线程池中线程优先级,默认值为5,值从1到10。 className:线程池实现类,未指定情况下,默认实现类为org.apache.catalina.core.StandardThreadExecutor。如果想使用自定义线程池首先需要实现 org.apache.catalina.Executor接口。