首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10014篇文章
优秀的个人博客,低调大师

基础为重,Python的基础,成就月薪过万

之前介绍了数字和字符串,接下来我们说的是列表和元祖这是之前的文章 Python安装与基本数据类型之一数字和字符串 List(列表) 列表是Python 中使⽤最频繁的数据类型。列表是写在⽅括号之间、⽤逗号分隔开的元素列表。列表中元素的类型可以不相同: 列表是写在⽅括号之间、⽤逗号分隔开的元素列表。列表中元素的类型可以不相同 和字符串⼀样,列表同样可以被索引和切⽚,列表被切⽚后返回⼀个包含所需元素的新列表。详细的在这⾥就不赘述了。 除了这些,列表还⽀持串联操作,使⽤+操作符: 与之前讲的字符串不⼀样的是,列表中的元素是可以改变的: PS: List写在⽅括号之间,元素⽤逗号隔开。 和字符串⼀样,list可以被索引和切⽚。 List可以使⽤+操作符进⾏拼接。 List中的元素是可以改变的。 Tuple(元组) 元组与列表类似,不同之处在于元组的元素不能修改。元组写在⼩括号⾥,元素之间⽤逗号隔开。 元组中的元素类型也可以不相同,元组与字符串类似,可以被索引且下标索引从0开始,也可以进⾏截取/切⽚ 其实,可以把字符串看作⼀种特殊的元组。 虽然tuple的元素不可改变,但它可以包含可变的对象,⽐如list列表。构造包含0个或1个元素的tuple是个特殊的问题,所以有⼀些额外的语法规则 现在手上也有一些Python的资料视频,大家可以加q-u-n 二二七,四三五,四五零 免费获取资料哈~ PS: 与字符串⼀样,元组的元素不能修改。 元组也可以被索引和切⽚,⽅法⼀样。 注意构造包含0或1个元素的元组的特殊语法规则。 元组也可以使⽤+操作符进⾏拼接。 Sets(集合) 集合是⼀个⽆序不重复元素的集。 基本功能是进⾏成员关系测试和消除重复元素。 可以使⽤⼤括号 或者 set()函数创建set集合,注意:创建⼀个空集合必须⽤ set() ⽽不是 { },因为{ }是⽤来创建⼀个空字典。 Dictionaries(字典) 我们最后再来介绍,字典是Python中另⼀个⾮常有⽤的内置数据类型。 字典是⼀种映射类型,它是⼀个⽆序的键 : 值对集合。关键字必须使⽤不可变类型,也就是说list和包含可变类型的tuple不能做关键字。在同⼀个字典中,关键字还必须互不相同。 PS: 字典是⼀种映射类型,它的元素是键值对。 字典的关键字必须为不可变类型,且不能重复。 创建空字典使⽤{ }。

优秀的个人博客,低调大师

HDFS的基础组成部分及基础操作

HDFS组件结构图解说: 1、如图所示中,NameNode充当master角色,职责包括:管理文档系统的命名空间(namespace);调节客户端访问到需要的文件(存储在DateNode中的文件) 2、DataNodes充当slaves角色,通常情况下,一台机器只部署一个Datenode,用来存储MapReduce程序需要的数据 3、Namenode会定期从DataNodes那里收到Heartbeat和Blockreport反馈 4、Heartbeat反馈用来确保DataNode没有出现功能异常; 5、Blockreport包含DataNode所存储的Block集合 二、HDFS设计原则 1、文件以块(block)方式存储 2、每个块带下远比多数文件系统来的大(预设64M) 3、通过副本机制提高可靠度和读取吞吐量 4、每个区块至少分到三台DataNode上(一般,对namenode进行raid1配置,对datanode进行raid5配置) 5、单一 master (NameNode)来协调存储元数据(metadata) 6、客户端对文件没有缓存机制 (No data caching) 三、NameNode(NN) NameNode主要功能提供名称查询服务,它是一个jetty服务器(一个开源的servlet容器,嵌入式的web服务器) NameNode保存metadate信息包括 文件owership和permissions 文件包含哪些块 Block保存在哪个DataNode(由DataNode启动时上报) 1、NameNode的metadate信息在启动后会加载到内存 2、metadata存储到磁盘文件名为”fsimage” Block的位置信息不会保存到fsimage 四.DataNode(DN) 保存Block 启动DN线程的时候会向NN汇报block信息 hadoop fs -cmd cmd :为具体的操作,基本上于UNIX的命令相同 args:参数 hdfs资源URL格式:scheme://bigdata/path scheme:协议名,file或hdfs bigdata:namenode主机名 path:路径 eg:hdfs://localhost:9000/user/chunk/test.txt 假设已经在core-site.xml设置了fs.default.name=hdfs://localhost:9000, 则仅使用/user/chunk/test.txt即可 hdfs命令示例:存放的数据以文件的形式存储,使用绝对路径来区分每个资源,在创建目录来存储资源时候要加/ #创建目录 hadoop fs -mkidr/myFirstDir #查看创建的目录 hadoop fs -ls /myFirstDir #返回为空,目前还没存放数据 #对当前创建目录存放文件 hadoop fs -put /etc/shadow /myFirstDir #查看目录下的文件 hadoop fs -ls /myFirstDir #复制文件到指定的位置 hadoop fs -get /hadoop目下的文件 /本地文件路径 hadoop fs -get /myFirstDir/shadow /home/#下载shadow到/home目录下 #新建一个空文件 hadoop fs -touchz /myFirstDir/newFile.txt #将hadoop上某个文件重命名 hadoop fs -mv /myFirstDir/newFile.txt /myFirstDir/bigdata.txt #将hadoop指定目录下所有内容保存为一个文件,同时down至本地 hadoop dfs -getmerge /myFirstDir/bigdata.txt /home/a #查看文件里的内容 hadoop fs -cat /myFirstDir/shadow #查看最后1000字节数据 hadoop fs -tail /myFirsDir/shadow #删除文件\目录 hadoop fs -rm -R /myFirstDir/shadow hadoop fs -rm -R /myFirstDir/Secondary #查看HDFS下的文件 hadoop fs -ls / #查看集群数据的信息,登陆master节点查看 http://192.168.1.114:50070 管理与更新 #查看HDFS的基本统计信息 hadoop dfsadmin -report #进出安全模式 hadoop dfsadmin -safemode enter hadoop dfsadmin -safemode leave #节点添加 添加一个新的DataNode节点,先在新加节点上安装好Hadoop, 要和NameNode使用相同的配置(可以直接从NameNode复制),修改$HADOOP_HOME/conf/master文件,加入NameNode主机名。 然后在NameNode节点上修改$HADOOP_HOME/conf/slaves文件,加入新节点名,再建立新加节点无密码的SSH连接,运行启动命令为: /bin/start-all.sh #负载均衡 HDFS的数据在各个DataNode中的分布可能很不均匀,尤其是在DataNode节点出现故障或新增DataNode节点时。 新增数据块时NameNode对DataNode节点的选择策略也有可能导致数据块分布不均匀。 用户可以使用命令重新平衡DataNode上的数据块的分布: start-balancer.sh 本文转自 DBAspace 51CTO博客,原文链接:http://blog.51cto.com/dbaspace/1874685

优秀的个人博客,低调大师

ClickHouse集群搭建(二)

重叠泪痕缄锦字,人生只有情难死。 分布式集群安装 在上一章我们已经完成ClickHouse分布式集群安装,也创建本地表和分布式表进行了测试,但是,假如停掉一个节点会发生神马情况? node03上kill掉clickhouse-server进程 [root@node03 ~]# ps -ef | grep clickhouse clickho+ 2233 1 73 13:07 ? 00:00:02 clickhouse-server --daemon --pid-file=/var/run/clickhouse-server/clickhouse-server.pid --config-file=/etc/clickhouse-server/config.xml root 2306 1751 0 13:07 pts/0 00:00:00 grep --color=auto clickhouse [root@node03 ~]# service clickhouse-server stop Stop clickhouse-server service: DONE [root@node03 ~]# ps -ef | grep clickhouse root 2337 1751 0 13:07 pts/0 00:00:00 grep --color=auto clickhouse node01上查询分布式表 node01 :) select * from cluster3s1r_all; # node03没有被杀掉时 SELECT * FROM cluster3s1r_all ┌─id─┬─website─────────────────┬─wechat─────┬─FlightDate─┬─Year─┐ │ 2 │ http://www.merryyou.cn/ │ javaganhuo │ 2020-11-28 │ 2020 │ └────┴─────────────────────────┴────────────┴────────────┴──────┘ ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ ┌─id─┬─website──────────────┬─wechat─┬─FlightDate─┬─Year─┐ │ 3 │ http://www.xxxxx.cn/ │ xxxxx │ 2020-11-28 │ 2020 │ └────┴──────────────────────┴────────┴────────────┴──────┘ 3 rows in set. Elapsed: 0.037 sec. node01 :) select * from cluster3s1r_all; # node03节点被杀掉时 SELECT * FROM cluster3s1r_all ┌─id─┬─website─────────────────┬─wechat─────┬─FlightDate─┬─Year─┐ │ 2 │ http://www.merryyou.cn/ │ javaganhuo │ 2020-11-28 │ 2020 │ └────┴─────────────────────────┴────────────┴────────────┴──────┘ ↘ Progress: 1.00 rows, 59.00 B (8.87 rows/s., 523.62 B/s.) 0% Received exception from server (version 20.8.3): Code: 279. DB::Exception: Received from localhost:9000. DB::Exception: All connection tries failed. Log: Code: 32, e.displayText() = DB::Exception: Attempt to read after eof (version 20.8.3.18) Code: 210, e.displayText() = DB::NetException: Connection refused (node03:9000) (version 20.8.3.18) Code: 210, e.displayText() = DB::NetException: Connection refused (node03:9000) (version 20.8.3.18) : While executing Remote. 1 rows in set. Elapsed: 0.114 sec. 只返回了node01节点上的数据,node03节点上的两条数据丢失。 数据备份 但在ClickHouse中,replica是挂在shard上的,因此要用多副本,必须先定义shard。 最简单的情况:1个分片多个副本。 修改metrika.xml文件 node01 上修改 /etc/clickhouse-server/metrika.xml集群配置文件 <yandex> <!-- 集群配置 --> <clickhouse_remote_servers> <!-- 1分片2备份 --> <cluster_1shards_2replicas> <!-- 数据分片1 --> <shard> <!-- false代表一次性写入所有副本,true表示写入其中一个副本,配合zk来进行数据复制 --> <internal_replication>false</internal_replication> <replica> <host>node01</host> <port>9000</port> </replica> <replica> <host>node02</host> <port>9000</port> </replica> </shard> </cluster_1shards_2replicas> </clickhouse_remote_servers> </yandex> 将修改后的配置分发到node02机器上 [root@node01 clickhouse-server]# scp /etc/clickhouse-server/metrika.xml node02:$PWD metrika.xml 100% 674 618.9KB/s 00:00 如果配置文件没有问题,是不用重启clickhouse-server的,会自动加载配置文件,node01上查看集群信息 [root@node01 clickhouse-server]# clickhouse-client -m ClickHouse client version 20.8.3.18. Connecting to localhost:9000 as user default. Connected to ClickHouse server version 20.8.3 revision 54438. node01 :) select * from system.clusters; SELECT * FROM system.clusters ┌─cluster───────────────────────────┬─shard_num─┬─shard_weight─┬─replica_num─┬─host_name─┬─host_address───┬─port─┬─is_local─┬─user────┬─default_database─┬─errors_count─┬─estimated_recovery_time─┐ │ cluster_1shards_2replicas │ 1 │ 1 │ 1 │ node01 │ 192.168.10.100 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ cluster_1shards_2replicas │ 1 │ 1 │ 2 │ node02 │ 192.168.10.110 │ 9000 │ 0 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards │ 1 │ 1 │ 1 │ 127.0.0.1 │ 127.0.0.1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards │ 2 │ 1 │ 1 │ 127.0.0.2 │ 127.0.0.2 │ 9000 │ 0 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards_localhost │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards_localhost │ 2 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_shard_localhost │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_shard_localhost_secure │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9440 │ 0 │ default │ │ 0 │ 0 │ │ test_unavailable_shard │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_unavailable_shard │ 2 │ 1 │ 1 │ localhost │ ::1 │ 1 │ 0 │ default │ │ 0 │ 0 │ └───────────────────────────────────┴───────────┴──────────────┴─────────────┴───────────┴────────────────┴──────┴──────────┴─────────┴──────────────────┴──────────────┴─────────────────────────┘ 10 rows in set. Elapsed: 0.018 sec. 测试数据备份 在node01和node02上分别创建本地表cluster1s2r_local CREATE TABLE default.cluster1s2r_local ( `id` Int32, `website` String, `wechat` String, `FlightDate` Date, Year UInt16 ) ENGINE = MergeTree(FlightDate, (Year, FlightDate), 8192); 在node01机器上创建分布式表,注意集群名称 CREATE TABLE default.cluster1s2r_all AS cluster1s2r_local ENGINE = Distributed(cluster_1shards_2replicas, default, cluster1s2r_local, rand()); 往分布式表cluster1s2r_all插入数据,cluster1s2r_all 会全部插入到node01和node02节点的cluster1s2r_local里 插入数据 INSERT INTO default.cluster1s2r_all (id,website,wechat,FlightDate,Year)values(1,'https://niocoder.com/','java干货','2020-11-28',2020); INSERT INTO default.cluster1s2r_all (id,website,wechat,FlightDate,Year)values(2,'http://www.merryyou.cn/','javaganhuo','2020-11-28',2020); INSERT INTO default.cluster1s2r_all (id,website,wechat,FlightDate,Year)values(3,'http://www.xxxxx.cn/','xxxxx','2020-11-28',2020); 查询分布式表和本地表 node01 :) select * from cluster1s2r_all; # 查询分布式表 SELECT * FROM cluster1s2r_all ┌─id─┬─website──────────────┬─wechat─┬─FlightDate─┬─Year─┐ │ 3 │ http://www.xxxxx.cn/ │ xxxxx │ 2020-11-28 │ 2020 │ └────┴──────────────────────┴────────┴────────────┴──────┘ ┌─id─┬─website─────────────────┬─wechat─────┬─FlightDate─┬─Year─┐ │ 2 │ http://www.merryyou.cn/ │ javaganhuo │ 2020-11-28 │ 2020 │ └────┴─────────────────────────┴────────────┴────────────┴──────┘ ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ 3 rows in set. Elapsed: 0.018 sec. node01 :) select * from cluster1s2r_local; # node01节点查询本地表 SELECT * FROM cluster1s2r_local ┌─id─┬─website─────────────────┬─wechat─────┬─FlightDate─┬─Year─┐ │ 2 │ http://www.merryyou.cn/ │ javaganhuo │ 2020-11-28 │ 2020 │ └────┴─────────────────────────┴────────────┴────────────┴──────┘ ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ ┌─id─┬─website──────────────┬─wechat─┬─FlightDate─┬─Year─┐ │ 3 │ http://www.xxxxx.cn/ │ xxxxx │ 2020-11-28 │ 2020 │ └────┴──────────────────────┴────────┴────────────┴──────┘ 3 rows in set. Elapsed: 0.015 sec. node02 :) select * from cluster1s2r_local; # node02节点查询本地表 SELECT * FROM cluster1s2r_local ┌─id─┬─website─────────────────┬─wechat─────┬─FlightDate─┬─Year─┐ │ 2 │ http://www.merryyou.cn/ │ javaganhuo │ 2020-11-28 │ 2020 │ └────┴─────────────────────────┴────────────┴────────────┴──────┘ ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ ┌─id─┬─website──────────────┬─wechat─┬─FlightDate─┬─Year─┐ │ 3 │ http://www.xxxxx.cn/ │ xxxxx │ 2020-11-28 │ 2020 │ └────┴──────────────────────┴────────┴────────────┴──────┘ 3 rows in set. Elapsed: 0.007 sec. 查询node01和node02本地表cluster1s2r_local都是全量数据, 即使sotp到其中一个节点数据也不会丢失,数据副本已经生效。 数据副本一致性问题 既然有多副本,就有个一致性的问题:加入写入数据时,挂掉一台机器,会怎样? 模拟写入分布式表是某一个节点down机 停掉node02节点服务 service clickhouse-server stop 在node01节点上向分布式表cluster1s2r_all插入数据 sql INSERT INTO default.cluster1s2r_all (id,website,wechat,FlightDate,Year)values(4,'http://www.yyyyyy.cn/','yyyyy','2020-11-29',2020); 启动node02节点服务 查询验证是否同步 查看node01和node02机器的cluster1s2r_local、以及cluster1s2r_all,发现都是总数据量都增加了1条,说明这种情况下,集群节点之间能够自动同步 上面是通过向分布式表cluster1s2r_all插入数据,如果通过本地表cluster1s2r_local,数据还能同步吗? 在node01上往cluster1s2r_local插入1条数据; 查询node02,cluster1s2r_local数据没有同步 综上所述,通过分布表写入数据,会自动同步数据;而通过本地表表写入数据,不会同步;一般i情况下是没什么大问题。 但是生产情况总比理论复杂的多,以上配置可能会存在数据不一致的问题 官方文档描述如下: Each shard can have the internal_replication parameter defined in the config file. If this parameter is set to true, the write operation selects the first healthy replica and writes data to it. Use this alternative if the Distributed table “looks at” replicated tables. In other words, if the table where data will be written is going to replicate them itself. If it is set to false (the default), data is written to all replicas. In essence, this means that the Distributed table replicates data itself. This is worse than using replicated tables, because the consistency of replicas is not checked, and over time they will contain slightly different data. 翻译如下: 分片可在配置文件中定义 ‘internal_replication’ 参数。 此参数设置为«true»时,写操作只选一个正常的副本写入数据。如果分布式表的子表是复制表(*ReplicaMergeTree),请使用此方案。换句话说,这其实是把数据的复制工作交给实际需要写入数据的表本身而不是分布式表。 若此参数设置为«false»(默认值),写操作会将数据写入所有副本。实质上,这意味着要分布式表本身来复制数据。这种方式不如使用复制表的好,因为不会检查副本的一致性,并且随着时间的推移,副本数据可能会有些不一样。 简单理解如下: 这个为true代表zk会挑选一个合适的节点写入,然后在后台进行多个节点之间数据的同步. 如果是false,则是一次性写入所有节点,以这种重复写入的方法实现节点之间数据的同步. 自动数据备份 自动数据备份是表的行为,引擎为 ReplicatedXXX的表支持自动同步。 Replicated前缀只用于MergeTree系列(MergeTree是最常用的引擎)。 重点说明: Replicated表自动同步与之前的集群自动同步不同,是表的行为,与metrika.xml中的<clickhouse_remote_servers>配置没有关系,只要有zookeeper配置就行了。 node01修改metrika.xml配置 <yandex> <zookeeper-servers> <node index="1"> <host>node01</host> <port>2181</port> </node> <node index="2"> <host>node02</host> <port>2181</port> </node> <node index="3"> <host>node03</host> <port>2181</port> </node> </zookeeper-servers> </yandex> 将修改后的配置分发到node02机器上 [root@node01 clickhouse-server]# scp /etc/clickhouse-server/metrika.xml node02:$PWD metrika.xml 重启`clickhouse-server`,由于之前的表存在导致启动是失败。`error`日志 ​```shell [root@node01 clickhouse-server]# tail -f /var/log/clickhouse-server/clickhouse-server.err.log 7. DB::StorageDistributed::startup() @ 0x10f1bd40 in /usr/bin/clickhouse 8. ? @ 0x1151d922 in /usr/bin/clickhouse 9. ThreadPoolImpl<ThreadFromGlobalPool>::worker(std::__1::__list_iterator<ThreadFromGlobalPool, void*>) @ 0xa43d6ad in /usr/bin/clickhouse 10. ThreadFromGlobalPool::ThreadFromGlobalPool<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda1'()>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda1'()&&...)::'lambda'()::operator()() const @ 0xa43dd93 in /usr/bin/clickhouse 11. ThreadPoolImpl<std::__1::thread>::worker(std::__1::__list_iterator<std::__1::thread, void*>) @ 0xa43cc4d in /usr/bin/clickhouse 12. ? @ 0xa43b3ff in /usr/bin/clickhouse 13. start_thread @ 0x7ea5 in /usr/lib64/libpthread-2.17.so 14. clone @ 0xfe8dd in /usr/lib64/libc-2.17.so (version 20.8.3.18) 2020.11.29 14:43:01.163530 [ 3643 ] {} <Error> Application: DB::Exception: Requested cluster 'cluster_1shards_2replicas' not found: while loading database `default` from path /var/lib/clickhouse/metadata/default 删除之前的建表语句 [root@node01 default]# rm -rf /var/lib/clickhouse/metadata/default/*.sql 启动clickhouse-server 在node01和node02节点上创建数据库表 -- node01 节点 CREATE TABLE `cluster_zk` ( `id` Int32, `website` String, `wechat` String, `FlightDate` Date, Year UInt16 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/cluster_zk', 'replica01', FlightDate, (Year, FlightDate), 8192); -- node02节点 CREATE TABLE `cluster_zk` ( `id` Int32, `website` String, `wechat` String, `FlightDate` Date, Year UInt16 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/cluster_zk', 'replica02', FlightDate, (Year, FlightDate), 8192); node01节点上插入数据 INSERT INTO default.cluster_zk (id,website,wechat,FlightDate,Year)values(1,'https://niocoder.com/','java干货','2020-11-28',2020); node01,node02节点上查询数据 node01 :) select * from cluster_zk; # node01节点 SELECT * FROM cluster_zk ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ 1 rows in set. Elapsed: 0.004 sec. node02 :) select * from cluster_zk; # node02节点 SELECT * FROM cluster_zk ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ 1 rows in set. Elapsed: 0.004 sec. 查询zk信息 [zk: localhost:2181(CONNECTED) 2] ls /clickhouse/tables/cluster_zk/replicas [replica02, replica01] [zk: localhost:2181(CONNECTED) 3] 自动数据备份集群配置 node01修改metrika.xml配置, 注意此处internal_replication为true <yandex> <clickhouse_remote_servers> <perftest_1shards_2replicas> <shard> <internal_replication>true</internal_replication> <replica> <host>node01</host> <port>9000</port> </replica> <replica> <host>node02</host> <port>9000</port> </replica> </shard> </perftest_1shards_2replicas> </clickhouse_remote_servers> <zookeeper-servers> <node index="1"> <host>node01</host> <port>2181</port> </node> <node index="2"> <host>node02</host> <port>2181</port> </node> <node index="3"> <host>node03</host> <port>2181</port> </node> </zookeeper-servers> </yandex> 将修改后的配置分发到node02机器上 [root@node01 clickhouse-server]# scp /etc/clickhouse-server/metrika.xml node02:$PWD metrika.xml 查询集群信息 node01 :) select * from system.clusters; SELECT * FROM system.clusters ┌─cluster───────────────────────────┬─shard_num─┬─shard_weight─┬─replica_num─┬─host_name─┬─host_address───┬─port─┬─is_local─┬─user────┬─default_database─┬─errors_count─┬─estimated_recovery_time─┐ │ perftest_1shards_2replicas │ 1 │ 1 │ 1 │ node01 │ 192.168.10.100 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ perftest_1shards_2replicas │ 1 │ 1 │ 2 │ node02 │ 192.168.10.110 │ 9000 │ 0 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards │ 1 │ 1 │ 1 │ 127.0.0.1 │ 127.0.0.1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards │ 2 │ 1 │ 1 │ 127.0.0.2 │ 127.0.0.2 │ 9000 │ 0 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards_localhost │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards_localhost │ 2 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_shard_localhost │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_shard_localhost_secure │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9440 │ 0 │ default │ │ 0 │ 0 │ │ test_unavailable_shard │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_unavailable_shard │ 2 │ 1 │ 1 │ localhost │ ::1 │ 1 │ 0 │ default │ │ 0 │ 0 │ └───────────────────────────────────┴───────────┴──────────────┴─────────────┴───────────┴────────────────┴──────┴──────────┴─────────┴──────────────────┴──────────────┴─────────────────────────┘ 10 rows in set. Elapsed: 0.018 sec. 创建分布式表 CREATE TABLE default.clusterzk_all AS cluster_zk ENGINE = Distributed(perftest_1shards_2replicas, default, cluster_zk, rand()); 分布式表查询数据 ode01 :) select * from clusterzk_all; SELECT * FROM clusterzk_all ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ 1 rows in set. Elapsed: 0.020 sec. 分布式表写入 上文已经提到,internal_replication为true,则通过分布表写入数据时,会自动找到“最健康”的副本写入,然后其他副本通过表自身的复制功能同步数据,最终达到数据一致。 分片+数据备份整合 ip 主机 clickhouse 分片副本 192.168.10.100 node01 9000 01/01 192.168.10.100 node01 9001 03/02 192.168.10.100 node02 9000 02/01 192.168.10.100 node02 9001 01/02 192.168.10.100 node03 9000 03/01 192.168.10.100 node03 9001 02/02 3分片2副本. 在node01,node02,node03的9001端口再启动一个clickhouse-server实例。 即shard1的两个副本放到node01 9000、node02 9001两个机器上,shard2的两个副本放到node02 9000、node03 9001上,shard3的两个副本放到node03 9000、node01 9001上. node01创建并修改config1.xml [root@node01 clickhouse-server]# cp /etc/clickhouse-server/config.xml /etc/clickhouse-server/config1.xml [root@node01 clickhouse-server]# vim /etc/clickhouse-server/config1.xml 修改以下内容 <?xml version="1.0"?> <yandex> <!--省略其他 --> <http_port>8124</http_port> <tcp_port>9001</tcp_port> <mysql_port>9005</mysql_port> <interserver_http_port>9010</interserver_http_port> <log>/var/log/clickhouse-server/clickhouse-server-1.log</log> <errorlog>/var/log/clickhouse-server/clickhouse-server.err-1.log</errorlog> <!-- Path to data directory, with trailing slash. --> <path>/var/lib/clickhouse1/</path> <!-- Path to temporary data for processing hard queries. --> <tmp_path>/var/lib/clickhouse1/tmp/</tmp_path> <user_files_path>/var/lib/clickhouse1/user_files/</user_files_path> <format_schema_path>/var/lib/clickhouse1/format_schemas/</format_schema_path> <include_from>/etc/clickhouse-server/metrika1.xml</include_from> <!--省略其他 --> </yandex> node01创建并修改metrika.xml <yandex> <!--ck集群节点--> <clickhouse_remote_servers> <!--ck集群名称--> <perftest_3shards_2replicas> <shard> <internal_replication>true</internal_replication> <replica> <host>node01</host> <port>9000</port> </replica> <replica> <host>node02</host> <port>9001</port> </replica> </shard> <shard> <internal_replication>true</internal_replication> <replica> <host>node02</host> <port>9000</port> </replica> <replica> <host>node03</host> <port>9001</port> </replica> </shard> <shard> <internal_replication>true</internal_replication> <replica> <host>node03</host> <port>9000</port> </replica> <replica> <host>node01</host> <port>9001</port> </replica> </shard> </perftest_3shards_2replicas> </clickhouse_remote_servers> <!--zookeeper相关配置--> <zookeeper-servers> <node index="1"> <host>node01</host> <port>2181</port> </node> <node index="2"> <host>node02</host> <port>2181</port> </node> <node index="3"> <host>node03</host> <port>2181</port> </node> </zookeeper-servers> <macros> <shard>01</shard> <!--分ID, 同一分片内的副本配置相同的分ID--> <replica>node01</replica> <!--当前节点主机名--> </macros> <networks> <ip>::/0</ip> </networks> <!--压缩相关配置--> <clickhouse_compression> <case> <min_part_size>10000000000</min_part_size> <min_part_size_ratio>0.01</min_part_size_ratio> <method>lz4</method> <!--压缩算法lz4压缩比zstd快, 更占磁盘--> </case> </clickhouse_compression> </yandex> 复制metrika.xml文件为metrika1.xml,修改macros配置 node01``metrika.xml``macros配置 <macros> <shard>01</shard> <!--分ID, 同一分片内的副本配置相同的分ID--> <replica>node01</replica> <!--当前节点主机名--> </macros> node01``metrika1.xml``macros配置 <macros> <shard>03</shard> <!--分ID, 同一分片内的副本配置相同的分ID--> <replica>node01</replica> <!--当前节点主机名--> </macros> node02``metrika.xml``macros配置 <macros> <shard>02</shard> <!--分ID, 同一分片内的副本配置相同的分ID--> <replica>node02</replica> <!--当前节点主机名--> </macros> node02``metrika1.xml``macros配置 <macros> <shard>01</shard> <!--分ID, 同一分片内的副本配置相同的分ID--> <replica>node02</replica> <!--当前节点主机名--> </macros> node03``metrika.xml``macros配置 <macros> <shard>03</shard> <!--分ID, 同一分片内的副本配置相同的分ID--> <replica>node03</replica> <!--当前节点主机名--> </macros> node03``metrika.1xml``macros配置 <macros> <shard>02</shard> <!--分ID, 同一分片内的副本配置相同的分ID--> <replica>node03</replica> <!--当前节点主机名--> </macros> 创建并修改clickhouse-server-1 [root@node01 clickhouse-server]# cp /etc/rc.d/init.d/clickhouse-server /etc/rc.d/init.d/clickhouse-server-1 You have new mail in /var/spool/mail/root [root@node01 clickhouse-server]# vim /etc/rc.d/init.d/clickhouse-server-1 修改以下内容 CLICKHOUSE_CONFIG=$CLICKHOUSE_CONFDIR/config1.xml CLICKHOUSE_PIDFILE="$CLICKHOUSE_PIDDIR/$PROGRAM-1.pid" 分发配置文件到node02和node03节点 [root@node01 clickhouse-server]# scp /etc/rc.d/init.d/clickhouse-server-1 node02:/etc/rc.d/init.d/ clickhouse-server-1 100% 11KB 4.0MB/s 00:00 You have new mail in /var/spool/mail/root [root@node01 clickhouse-server]# scp /etc/rc.d/init.d/clickhouse-server-1 node03:/etc/rc.d/init.d/ clickhouse-server-1 100% 11KB 4.0MB/s 00:00 [root@node01 clickhouse-server]# scp /etc/clickhouse-server/config1.xml node02:$PWD config1.xml 100% 33KB 10.2MB/s 00:00 [root@node01 clickhouse-server]# scp /etc/clickhouse-server/config1.xml node03:$PWD config1.xml 100% 33KB 9.7MB/s 00:00 [root@node01 clickhouse-server]# scp /etc/clickhouse-server/metrika.xml node02:$PWD metrika.xml 100% 2008 1.0MB/s 00:00 You have new mail in /var/spool/mail/root [root@node01 clickhouse-server]# scp /etc/clickhouse-server/metrika.xml node03:$PWD metrika.xml 100% 2008 1.1MB/s 00:00 [root@node01 clickhouse-server]# [root@node01 clickhouse-server]# scp /etc/clickhouse-server/metrika1.xml node02:$PWD metrika1.xml 100% 2008 1.0MB/s 00:00 [root@node01 clickhouse-server]# scp /etc/clickhouse-server/metrika1.xml node03:$PWD metrika1.xml 修改node02和node03的macros配置 启动ClickHouse实例 node01的clickhouse-server-1实例 node02的clickhouse-server-1实例 node03的clickhouse-server实例 node03的clickhouse-server-1实例 service clickhouse-server restart service clickhouse-server-1 restart 查看集群信息 node01 :) select * from system.clusters; SELECT * FROM system.clusters ┌─cluster───────────────────────────┬─shard_num─┬─shard_weight─┬─replica_num─┬─host_name─┬─host_address───┬─port─┬─is_local─┬─user────┬─default_database─┬─errors_count─┬─estimated_recovery_time─┐ │ perftest_3shards_2replicas │ 1 │ 1 │ 1 │ node01 │ 192.168.10.100 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ perftest_3shards_2replicas │ 1 │ 1 │ 2 │ node02 │ 192.168.10.110 │ 9001 │ 0 │ default │ │ 0 │ 0 │ │ perftest_3shards_2replicas │ 2 │ 1 │ 1 │ node02 │ 192.168.10.110 │ 9000 │ 0 │ default │ │ 0 │ 0 │ │ perftest_3shards_2replicas │ 2 │ 1 │ 2 │ node03 │ 192.168.10.120 │ 9001 │ 0 │ default │ │ 0 │ 0 │ │ perftest_3shards_2replicas │ 3 │ 1 │ 1 │ node03 │ 192.168.10.120 │ 9000 │ 0 │ default │ │ 0 │ 0 │ │ perftest_3shards_2replicas │ 3 │ 1 │ 2 │ node01 │ 192.168.10.100 │ 9001 │ 0 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards │ 1 │ 1 │ 1 │ 127.0.0.1 │ 127.0.0.1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards │ 2 │ 1 │ 1 │ 127.0.0.2 │ 127.0.0.2 │ 9000 │ 0 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards_localhost │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_cluster_two_shards_localhost │ 2 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_shard_localhost │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_shard_localhost_secure │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9440 │ 0 │ default │ │ 0 │ 0 │ │ test_unavailable_shard │ 1 │ 1 │ 1 │ localhost │ ::1 │ 9000 │ 1 │ default │ │ 0 │ 0 │ │ test_unavailable_shard │ 2 │ 1 │ 1 │ localhost │ ::1 │ 1 │ 0 │ default │ │ 0 │ 0 │ └───────────────────────────────────┴───────────┴──────────────┴─────────────┴───────────┴────────────────┴──────┴──────────┴─────────┴──────────────────┴──────────────┴─────────────────────────┘ 14 rows in set. Elapsed: 0.019 sec. 测试分片+副本集群 创建可复制表,node01节点执行即可,其他节点会自动创建。 CREATE TABLE `cluster32r_local` ON cluster perftest_3shards_2replicas ( `id` Int32, `website` String, `wechat` String, `FlightDate` Date, Year UInt16 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/ontime','{replica}', FlightDate, (Year, FlightDate), 8192); node01 :) CREATE TABLE `cluster32r_local` ON cluster perftest_3shards_2replicas :-] ( :-] `id` Int32, :-] `website` String, :-] `wechat` String, :-] `FlightDate` Date, :-] Year UInt16 :-] ) :-] ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/ontime','{replica}', FlightDate, (Year, FlightDate), 8192); CREATE TABLE cluster32r_local ON CLUSTER perftest_3shards_2replicas ( `id` Int32, `website` String, `wechat` String, `FlightDate` Date, `Year` UInt16 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/ontime', '{replica}', FlightDate, (Year, FlightDate), 8192) ┌─host───┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐ │ node03 │ 9001 │ 0 │ │ 5 │ 0 │ │ node03 │ 9000 │ 0 │ │ 4 │ 0 │ │ node01 │ 9001 │ 0 │ │ 3 │ 0 │ │ node01 │ 9000 │ 0 │ │ 2 │ 0 │ │ node02 │ 9000 │ 0 │ │ 1 │ 0 │ └────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘ ┌─host───┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐ │ node02 │ 9001 │ 0 │ │ 0 │ 0 │ └────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘ 6 rows in set. Elapsed: 46.994 sec. 创建分布式表 CREATE TABLE cluster32r_all AS cluster32r_local ENGINE = Distributed(perftest_3shards_2replicas, default, cluster32r_local, rand()); 往第一个shard的副本插入数据(node01 9000),可以在第二个副本中查看数据(node02 9001) INSERT INTO default.cluster32r_local (id,website,wechat,FlightDate,Year)values(1,'https://niocoder.com/','java干货','2020-11-28',2020); INSERT INTO default.cluster32r_local (id,website,wechat,FlightDate,Year)values(2,'http://www.merryyou.cn/','javaganhuo','2020-11-28',2020); 使用客户端链接node02 9001实例查看 [root@node02 ~]# clickhouse-client --port 9001 -m ClickHouse client version 20.8.3.18. Connecting to localhost:9001 as user default. Connected to ClickHouse server version 20.8.3 revision 54438. node02 :) show tables; SHOW TABLES ┌─name─────────────┐ │ cluster32r_local │ └──────────────────┘ 1 rows in set. Elapsed: 0.010 sec. node02 :) select * from cluster32r_local; SELECT * FROM cluster32r_local ┌─id─┬─website─────────────────┬─wechat─────┬─FlightDate─┬─Year─┐ │ 2 │ http://www.merryyou.cn/ │ javaganhuo │ 2020-11-28 │ 2020 │ └────┴─────────────────────────┴────────────┴────────────┴──────┘ ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ 2 rows in set. Elapsed: 0.018 sec. 分布式表查询 node01 :) select * from cluster32r_all; SELECT * FROM cluster32r_all ┌─id─┬─website─────────────────┬─wechat─────┬─FlightDate─┬─Year─┐ │ 2 │ http://www.merryyou.cn/ │ javaganhuo │ 2020-11-28 │ 2020 │ └────┴─────────────────────────┴────────────┴────────────┴──────┘ ┌─id─┬─website───────────────┬─wechat───┬─FlightDate─┬─Year─┐ │ 1 │ https://niocoder.com/ │ java干货 │ 2020-11-28 │ 2020 │ └────┴───────────────────────┴──────────┴────────────┴──────┘ 2 rows in set. Elapsed: 0.030 sec. 所有副本节点均可本地表和分布式表均可读写数据 下载 关注微信公众号java干货回复 【clickhouse】

优秀的个人博客,低调大师

nginx搭建及加固

系统使用的是centos7 Nginx安装及配置 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务 安装 我是用的环境是centos 7,系统默认的yum源没有nginx,找到一个使用nginx官方源地址 首先建立nginx的yum仓库,执行下面的命令 sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 可以看到已经添加上了nginx的源,下面就是下载安装了 下载安装命令也很简单 sudo yum install -y nginx 安装成功^_^ 查看官方安装文档(https://www.nginx.com/resources/wiki/start/topics/tutorials/install/)上的源不一样,不过都是一样的建立本地yum仓库 启动nginx服务 service nginx start 默认是80端口,但测试访问发现并不能进入欢迎页面,查了一下,centos默认是关闭80端口的,我们设置一下防火墙 开启80端口 sudo firewall-cmd --zone=public --permanent --add-service=http 开启443端口 sudo firewall-cmd --zone=public --permanent --add-service=https 必须要重新加载一下防火墙配置才行哦,下面我们再来访问一下 完美。 配置 默认的网站目录为: /usr/share/nginx/html 全局的配置文件为:/etc/nginx/nginx.conf 默认的配置文件为: /etc/nginx/conf.d/default.conf 日志文件目录为:/var/log/nginx/ 我们查看具体的配置文件内容,发现其实nginx.conf是主要的配置文件,新增的都在/etc/nginx/conf.d/,nginx.conf将整个目录的配置文件都include了 配置结构 Nginx配置文件常见结构的从外到内依次是「http」「server」「location」等等,缺省的继承关系是从外到内,也就是说内层块会自动获取外层块的值作为缺省值。 Http http { #文件扩展名与文件类型映射表 include /etc/nginx/mime.types; #默认文件类型 default_type application/octet-stream; #日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # access_log /var/log/nginx/access.log main; #sendfile指令指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度,降低系统uptime。 sendfile on; #此选项允许或禁止使用socket的TCP_CORK的选项,此选项仅在使用sendfile的时候使用 #tcp_nopush on; #长连接超时时间,单位是秒 keepalive_timeout 65; #开启gzip压缩输出 #gzip on; #导入其他配置 include /etc/nginx/conf.d/*.conf; } 整个配置文件结构其实大概是这样的 http { #全局的配置 ………… server{ #虚拟主机的配置 ………… location { #每个请求的处理,如请求转发、静态文件映射、负载均衡等 ………… } } } 下面再具体了解一下每一层的配置 Server 接收请求的服务器需要将不同的请求按规则转发到不同的后端服务器上,在 nginx 中我们可以通过构建虚拟主机(server)的概念来将这些不同的服务配置隔离。不同的url会对应不同的server配置,而转发到相应的后端服务器上做处理。 server { listen 80; #服务监听端口 server_name localhost; #服务的域名或IP root html; #指定服务的页面根目录 index index.html index.htm; #指定访问的默认首页地址 } 通常我们可以配置多个server,像这样 server { listen 80; server_name host1; root html; index index.html index.htm; } server { listen 80; server_name host2; root /data/www/html; index index.html index.htm; } 我们可以将不同的服务在/etc/nginx/conf.d/目录下创建相应的conf以区分,方便管理,而nginx.conf会将这个目录下的conf全部引入的。 Location 每个 url 请求都会对应的一个服务,nginx 进行处理转发或者是本地的一个文件路径,或者是其他服务器的一个服务路径。而这个路径的匹配是通过 location 来进行的。我们可以将 server 当做对应一个域名进行的配置,而 location 是在一个域名下对更精细的路径进行配置。 location [匹配规则] { #具体处理配置,如转发、反向代理、负载均衡等 } location 匹配规则: ~ 波浪线表示执行一个正则匹配,区分大小写 ~* 表示执行一个正则匹配,不区分大小写 ^~ ^~表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录 = 进行普通字符精确匹配 匹配例子: location = / { # 只匹配"/". [ configuration A ] } location / { # 匹配任何请求,因为所有请求都是以"/"开始 # 但是更长字符匹配或者正则表达式匹配会优先匹配 [ configuration B ] } location ^~ /images/ { # 匹配任何以 /images/ 开始的请求,并停止匹配 其它location [ configuration C ] } location ~* \.(gif|jpg|jpeg)$ { # 匹配以 gif, jpg, or jpeg结尾的请求. # 但是所有 /images/ 目录的请求将由 [Configuration C]处理. [ configuration D ] } 请求: / -> 符合configuration A /documents/document.html -> 符合configuration B /images/1.gif -> 符合configuration C /documents/1.jpg ->符合 configuration D 功能配置 主要的功能配置都是在location里面的,下面我们来学习不同功能的配置方法 静态文件映射 访问文件的配置主要有root 和 alias alias后跟的指定目录是准确的,并且末尾必须加 /。 location /c/ { alias /a/; } 如果访问站点http://location/c访问的就是/a/目录下的站点信息。 root后跟的指定目录是上级目录,并且该上级目录下要含有和location后指定名称的同名目录才行。 location /c/ { root /a/; } 这时访问站点http://location/c访问的就是/a/c目录下的站点信息。 配置起来很简单比如我要将所有的请求到转移到真正提供服务的一台机器的 8001 端口,只要这样: location / { proxy_pass 172.16.1.1:8001; } 这样访问host时,就都被转发到 172.16.1.1的8001端口去了。 负载均衡 #负载均衡服务器列表配置在http下面 upstream myserver { ip_hash; server 172.16.1.1:8001; server 172.16.1.2:8002; server 172.16.1.3; server 172.16.1.4; } location / { proxy_pass http://myserver; } 我们在 upstream 中指定了一组机器,并将这个组命名为 myserver,这样在 proxypass 中只要将请求转移到 myserver 这个 upstream 中我们就实现了在四台机器的反向代理加负载均衡。 负载均衡的模式 轮询:默认模式,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。 weight:指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。 upstream bakend { server 192.168.0.14 weight=10; server 192.168.0.15 weight=10; } ip_hash:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 upstream bakend { ip_hash; server 192.168.0.14:88; server 192.168.0.15:80; } fair:按后端服务器的响应时间来分配请求,响应时间短的优先分配。 upstream backend { server server1; server server2; fair; } url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。 #例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法 upstream backend { server squid1:3128; server squid2:3128; hash $request_uri; hash_method crc32; } 负载均衡设备的IP及设备状态 每个设备的状态设置为: 1.down表示单前的server暂时不参与负载 2.weight为weight越大,负载的权重就越大。 3.max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误 4.fail_timeout:max_fails次失败后,暂停的时间。 5.backup: 其它所有的非back up机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。 upstream bakend{#定义负载均衡设备的Ip及设备状态}{ ip_hash; server 127.0.0.1:9090 down; server 127.0.0.1:8080 weight=2; server 127.0.0.1:6060; server 127.0.0.1:7070 backup; } 加固 隐藏服务器版本号 默认我们访问不存在的页面时,报错页面上会有nginx的版本信息,这会向黑客提供信息,以方便查找当前版本的漏洞,加以利用 修改ngixn.conf,http层里面添加server_tokens off; 我们访问不存在的页面试一下 这样没有版本信息了 禁止目录浏览 默认是不允许列出整个目录的,如果不是做下载服务器的,就不要打开这个,避免敏感信息暴露给黑客并下载 如果开启了就会是下面这样的效果 配置关闭即可 autoindex off 限制访问敏感资源 有些资源我们可能不想对外开放,比如一些版本控制的备份文件,如.git/.svn等,这些暴露了可能会将整个项目的结构或是源代码都泄露了, location /my/ { deny all; } 上面我设置了my这个目录下的所有资源都拒绝,效果如下 所以要识别好公开的资源,限制敏感资源的访问 限制HTTP请求方法 关闭没必要的请求方法,一般都是get|post了 下面配置在server里面,预期之外的会返回500状态 if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 500; } 这个要放到最前面 限制IP/域名访问 ngx_http_access_module 模块使有可能对特定IP客户端进行控制. 规则检查按照第一次匹配的顺序 location ~ .*my.html$ { root /usr/share/nginx/html; deny 192.168.0.105; #禁止ip allow 192.168.189.134; #允许ip deny all; #拒绝其他所有 } 限制访问的ip,即限制了服务的客户,防止不允许的人访问,减少风险 控制超时时间 可以缓解dos攻击,避免黑客伪造用户访问服务,造成服务器压力过大,带宽占满,备份nginx.conf配置文件。 编辑配置文件,具体设置如下: client_body_timeout 10; #设置客户端请求主体读取超时时间 client_header_timeout 10; #设置客户端请求头读取超时时间 keepalive_timeout 5 5; #第一个参数指定客户端连接保持活动的超时时间,第二个参数是可选的,它指定了消息头保持活动的有效时间 send_timeout10; #指定响应客户端的超时时间 验证一下设置 错误页面重定向 避免错误页面提供敏感信息,一般我们会定制一些通用的错误页面返回给客户端 我们在http段配置 error_page 500 502 503 504 /50x.html; 类似上面这种配置,将状态码500、502、503、504全部重定向到50x.html nginx降权 如果发生入侵,获取了当前运行nginx的用户,则拥有该用户的全新了,我们应当使用最下权限运行ngixn,绝对禁止root用户运行!!! 备份nginx.conf配置文件。 编辑配置文件,添加如下一行内容: user nobody; 保存,然后后重启nginx服务。 说明:nobody在linux中是一个不能登陆的帐号,一些服务进程如apache,aquid等都采用一些特殊的帐号来运行,比如nobody,news,games等等,这是就可以防止程序本身有安全问题的时候,不会被黑客获得root权限

优秀的个人博客,低调大师

Nacos的环境搭建

Nacos是阿里开源的一款服务治理方案的中间件,提供了服务发现和服务健康监测、动态配置服务、动态 DNS 服务、服务及其元数据管理等特性功能。 Nacos最新版本地址 https://github.com/alibaba/nacos/releases 下载后解压的目录如下 单机部署模式 1.进入到bin目录中 startup.sh -m standalone 2.访问http://ip:8848/nacos 如下,默认登录密码nacos/nacos 登录后管理页面如下 数据库模式 1.修改conf/application.propertis增加配置内容 spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://ip:3306/nacos_config?useUnicode=true&characterEncoding=utf-8 db.user= db.password= 2.创建数据库nacos_config,执行/config/nacos-mysql.sql数据库脚本 2.进入到bin目录中 startup.sh -m standalone 3.访问效果如同上 集群模式(在数据库模式下增加如下操作) 1.复制两个nacos命名为nacos1 nacos2 2.修改application.properties里面的启动端口,分别为8847,8848,8849 3.分别在config目录下创建cluster.config内容如下 10.136.15.122:8848 10.136.15.122:8849 10.136.15.122:8847 4.启动 ./startup.sh 5.查看集群情况

优秀的个人博客,低调大师

DockerSwarm 集群环境搭建

文章首发于公众号《程序员果果》地址:https://mp.weixin.qq.com/s/RSNL-V4jLE8YVMSWZlJ_Vw 一、简介 1. 什么是docker swarm? Swarm 在 Docker 1.12 版本之前属于一个独立的项目,在 Docker 1.12 版本发布之后,该项目合并到了 Docker 中,成为 Docker 的一个子命令。目前,Swarm 是 Docker 社区提供的唯一一个原生支持 Docker 集群管理的工具。它可以把多个 Docker 主机组成的系统转换为单一的虚拟 Docker 主机,使得容器可以组成跨主机的子网网络。 Docker Swarm 是一个为 IT 运维团队提供集群和调度能力的编排工具。用户可以把集群中所有 Docker Engine 整合进一个「虚拟 Engine」的资源池,通过执行命令与单一的主 Swarm 进行沟通,而不必分别和每个 Docker Engine 沟通。在灵活的调度策略下,IT 团队可以更好地管理可用的主机资源,保证应用容器的高效运行。 Swarm的基本架构如下图所示: ![](https://yqfile.alicdn.com/e1fdf3829188f211cc01c1536fda5e283e1434a7.png 2. Docker Swarm 优点 任何规模都有高性能表现对于企业级的 Docker Engine 集群和容器调度而言,可拓展性是关键。任何规模的公司——不论是拥有五个还是上千个服务器——都能在其环境下有效使用 Swarm。经过测试,Swarm 可拓展性的极限是在 1000 个节点上运行 50000 个部署容器,每个容器的启动时间为亚秒级,同时性能无减损。 灵活的容器调度 Swarm 帮助 IT 运维团队在有限条件下将性能表现和资源利用最优化。Swarm 的内置调度器(scheduler)支持多种过滤器,包括:节点标签,亲和性和多种容器部策略如 binpack、spread、random 等等。 服务的持续可用性 Docker Swarm 由 Swarm Manager 提供高可用性,通过创建多个 Swarm master 节点和制定主 master 节点宕机时的备选策略。如果一个 master 节点宕机,那么一个 slave 节点就会被升格为 master 节点,直到原来的 master 节点恢复正常。此外,如果某个节点无法加入集群,Swarm 会继续尝试加入,并提供错误警报和日志。在节点出错时,Swarm 现在可以尝试把容器重新调度到正常的节点上去。 和 Docker API 及整合支持的兼容性 Swarm 对 Docker API 完全支持,这意味着它能为使用不同 Docker 工具(如 Docker CLI,Compose,Trusted Registry,Hub 和 UCP)的用户提供无缝衔接的使用体验。 Docker Swarm 为 Docker 化应用的核心功能(诸如多主机网络和存储卷管理)提供原生支持 开发的 Compose 文件能(通过 docker-compose up )轻易地部署到测试服务器或 Swarm 集群上。Docker Swarm 还可以从 Docker Trusted Registry 或 Hub 里 pull 并 run 镜像。 二、相关概念 1. 节点 有两种类型的节点: managers 和 workers. 管理节点(managers) 管理节点用于 Swarm 集群的管理,docker swarm 命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave 可以在工作节点执行)。一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为 leader,leader 通过 raft 协议实现。 为了利用swarm模式的容错功能,Docker建议您根据组织的高可用性要求实现奇数个节点。当您拥有多个管理器时,您可以从管理器节点的故障中恢复而无需停机。 N个管理节点的集群容忍最多损失 (N-1)/2 个管理节点。 Docker建议一个集群最多7个管理器节点。 重要说明:添加更多管理节点并不意味着可扩展性更高或性能更高。一般而言,情况正好相反。 工作节点(workers) 工作节点是任务执行节点,管理节点将服务 (service) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。下图展示了集群中管理节点与工作节点的关系。 2. 服务和任务 任务 (Task)是 Swarm 中的最小的调度单位,目前来说就是一个单一的容器。服务 (Services) 是指一组任务的集合,服务定义了任务的属性。服务有两种模式: replicated services (复制服务)按照一定规则在各个工作节点上运行指定个数的任务。 global services (全局服务)每个工作节点上运行一个任务。 两种模式通过 docker service create 的 --mode 参数指定。下图展示了容器、任务、服务的关系。 三、Swarm 集群 准备工作 三个可以通过网络进行通信的Linux主机或虚拟机,并安装了Docker,或者使用docker-machine 创建三台虚拟机。 已安装Docker Engine 1.12或更高版本 在主机之间打开端口(2377、7946、4789) 创建一个集群 1. 创建虚拟机(已经有Linux主机或虚拟机的跳过此步) 本文通过docker-machine使用VirtualBox驱动程序创建3个VM (已经有Linux主机或虚拟机的跳过此步): docker-machine create --driver virtualbox myvm-1 docker-machine create --driver virtualbox myvm-2 docker-machine create --driver virtualbox myvm-3 列出虚拟机并获取其IP地址: docker-machine ls 以下是此命令的示例输出: $docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS myvm-1 - virtualbox Running tcp://192.168.99.100:2376 v18.09.1-beta2 myvm-2 - virtualbox Running tcp://192.168.99.101:2376 v18.09.1-beta2 myvm-3 - virtualbox Running tcp://192.168.99.102:2376 v18.09.1-beta2 2. 初始化swarm 把第一台机器myvm-1充当管理节点,第二台myvm-2 、第三台myvm-3为工作节点。 使用 docker-machine ssh 连接 myvm-1,Linux主机直接ssh连接就行。 docker-machine ssh myvm-1 初始化swarm docker swarm init --advertise-addr 192.168.99.100 Swarm initialized: current node (4a8mo8cekpe0vpk0ze963avw9) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u 192.168.99.100:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. 上面输出的这一段就是工作节点加入集群的命令: docker swarm join --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u 192.168.99.100:2377 如果你的 Docker 主机有多个网卡,拥有多个 IP,必须使用 --advertise-addr 指定 IP。 执行 docker swarm init 命令的节点自动成为管理节点。 命令 docker info 可以查看 swarm 集群状态: Server Version: 18.09.1-beta2 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: bridge host macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: active NodeID: ib1498ex2q18i7gznb2zgicqq Is Manager: true ClusterID: fbyxxjzrtcxc53op35jnyzl7t Managers: 3 Nodes: 3 Default Address Pool: 10.0.0.0/8 命令 docker node ls 可以查看集群节点信息: $docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION ib1498ex2q18i7gznb2zgicqq * myvm-1 Ready Active Leader 18.09.1-beta2 3. 工作节点加入 swarm 集群 连接机器myvm-2 docker-machine ssh myvm-2 加入 swarm 集群 $docker swarm join \ --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u \ 192.168.99.100:2377 This node joined a swarm as a worker. 节点myvm-3,执行myvm-2相同的操作加入集群。 集群的大部分命令需要在管理节点中才能运行 我们进入管理节点 myvm-1 ,查看集群的节点信息。 docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION ib1498ex2q18i7gznb2zgicqq * myvm-1 Ready Active Leader 18.09.1-beta2 vels0fe3eh5s5cxj1s573v9wx myvm-2 Ready Active 18.09.1-beta2 obxnnqelh4p16wajrwvyn6j8v myvm-3 Ready Active 18.09.1-beta2 为了高可用,我们升级工作节点为管理节点。 docker node promote myvm-2 docker node promote myvm-3 这时我们再看集群的节点信息 $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION ib1498ex2q18i7gznb2zgicqq * myvm-1 Ready Active Leader 18.09.1-beta2 vels0fe3eh5s5cxj1s573v9wx myvm-2 Ready Active Reachable 18.09.1-beta2 obxnnqelh4p16wajrwvyn6j8v myvm-3 Ready Active Reachable 18.09.1-beta2 myvm-2、myvm-3的 集群状态变为 Reachable(选举者),因为集群中节点Leader只能有一个,这个类似zookeeper,只不过zookeepers用的算法是paxos,Swarm用的算法是raft。 4. 退出 Swarm 集群 如果 Manager 想要退出 Swarm 集群, 在 Manager Node 上执行如下命令: docker swarm leave 如果集群中还存在其它的 Worker Node,还希望 Manager 退出集群,则加上一个强制选项,命令行如下所示: docker swarm leave --force 工作节点进行退出集群,需要在工作节点上执行命令: docker swarm leave 退出后的节点,依然可以使用 上面的 docker swarm join --token 重新加入集群。 集群上部署应用 命令 $ docker service create --replicas 1 --name 别名 镜像ID replicas 指定运行服务的数量。 实例1 创建一个alpine服务(alpine是一个小型liunx系统) #运行一个alpine镜像,并执行ping命令 docker service create --replicas 1 --name test1 alpine ping docker.com 查看集群上的服务 $docker service ls ID NAME MODE REPLICAS IMAGE PORTS rnu10rprrwzv test1 replicated 1/1 alpine:latest 实例2 以下命令将nginx容器中的端口80发布到群集中任何节点的端口8080 docker service create \ --name my-web \ --publish published=8080,target=80 \ --replicas 2 \ nginx 查看集群上的服务 $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS q6wfiizzosmd nginx replicated 3/3 nginx:latest *:8080->80/tcp rnu10rprrwzv test1 replicated 1/1 alpine:latest service 通过 ingress load balancing 来发布服务,且 swarm 集群中所有 node 都参与到 ingress 路由网格(ingress routing mesh) 中,访问任意一个 node+PublishedPort 即可访问到服务。 当访问任何节点上的端口8080时,Docker将您的请求路由到活动容器。在群节点本身,端口8080可能并不实际绑定,但路由网格知道如何路由流量,并防止任何端口冲突的发生。 路由网格在发布的端口上监听分配给节点的任何IP地址。对于外部可路由的IP地址,该端口可从主机外部获得。对于所有其他IP地址,只能从主机内部访问。 所以访问 192.169.99.100:8080、192.169.99.101:8080、192.169.99.102:8080 ,都可以访问到nginx,这样就实现了负载均衡。因为我们指定--replicas 3 启动了3个运行nginx的容器 ,所以三个节点myvm-1、myvm-2、myvm-3 上都运行了一个 nginx 的容器,可以通过改其中一个节点上的nginx的欢迎页 ,然后再访问,来检查是否实现了负载均衡。 可以通过scale 来指定运行容器的数量。 docker service scale nginx=2 我通过docker service ls 可以看出 nginx 的副本变成了2个 $docker service ls ID NAME MODE REPLICAS IMAGE PORTS q6wfiizzosmd nginx replicated 2/2 nginx:latest *:8080->80/tcp overlay 网络 1. 概述 初始化swarm或将Docker主机加入现有swarm时,会在该Docker主机上创建两个新网络: ingress:称为覆盖网络ingress,处理与群集服务相关的控制和数据流量。创建群组服务并且不将其连接到用户定义的覆盖网络时,ingress 是默认连接的网络。 docker_gwbridge:称为桥接网络docker_gwbridge,它将各个Docker守护程序连接到参与该群集的其他守护进程。 在管理节点上查看网络 $ docker network ls NETWORK ID NAME DRIVER SCOPE cb0ccb89a988 bridge bridge local 0174fb113496 docker_gwbridge bridge local 541b62778c0e host host local 8n7xppn5z4j2 ingress overlay swarm 369d459f340d none null local overlay网络驱动程序会创建多个Docker守护主机之间的分布式网络。该网络位于(覆盖)特定于主机的网络之上,允许连接到它的容器(包括群集服务容器)安全地进行通信。Docker透明地处理每个数据包与正确的Docker守护程序主机和正确的目标容器的路由。 2. 自定义 overlay 网络 创建用于swarm服务的overlay网络,使用如下命令: docker network create -d overlay my-overlay 我们再次查看网络,发现可以看到自定义 overlay了。 $docker network ls NETWORK ID NAME DRIVER SCOPE cb0ccb89a988 bridge bridge local 0174fb113496 docker_gwbridge bridge local 541b62778c0e host host local 8n7xppn5z4j2 ingress overlay swarm a23htz7n0pvp my-overlay overlay swarm 369d459f340d none null local 集群中部署了两个服务 nginx、alpine,现在我们进入alpine,去访问nginx。 docker exec -it test1.1.oonwl8c5g4u3p17x8anifeubi bash / # ping nginx ping: bad address 'nginx' wget 192.168.99.100:8080 Connecting to 192.168.99.100:8080 (192.168.99.100:8080) index.html 100% |*************************************************************************************************************| 612 0:00:00 ETA 我们发现集群中的各个服务不能用名称访问的,只能用集群服务发现的路由网络访问,那么集群中的服务怎么能通过名称进行访问呢,这就需要用到上面自定义的 overlay 网络。 删除我们启动的服务,重新创建指定使用自定义网络的服务。 docker service rm nginx test1 docker service create --name nginx -p 8080:80 --network my-overlay --replicas 3 nginx docker service create --name test1 --network my-overlay alpine ping www.baidu.com 进入test1容器中,重新测试下: / # ping nginx PING nginx (10.0.0.2): 56 data bytes 64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.120 ms 64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.094 ms 64 bytes from 10.0.0.2: seq=2 ttl=64 time=0.108 ms / # wget nginx Connecting to nginx (10.0.0.2:80) index.html 100% |*************************************************************************************************************| 612 0:00:00 ETA 发现可以通过名称进行集群中的容器间的访问了。

优秀的个人博客,低调大师

Linux——LNMP环境搭建

一、LNMP环境概述 1、什么是LNMP环境 LNMP 是 Linux + Nginx + MySQL/Mariadb + PHP 的组合缩写。 Nginx:是一个web服务器,提供HTTP 服务。MySQL/MariaDB:关系型数据库,用来存放数据(例如账号信息等)PHP:是一种编程语言。常用来做网站(例如qq.com 、 baidu.com)。 2、网站访问原理 用户通过web浏览器访问网站,即访问Nginx服务。此时会处理图片、js、css(叫做静态请求);接收PHP请求但不处理,会将PHP的请求转发给php-fpm服务,由此服务来处理PHP请求(叫做动态请求) 3、静态请求 & 动态请求 静态请求:指Nginx可以直接处理的图片、js、css、视频、音频、flash等 动态请求:指需要和数据库打交道的请求。例如:用户登录过程,查看文章或者写一篇文章。 二、Mariadb数据库安装 1、Mariadb数据库概述 Mariadb数据库是MySQL的一个分支。MySQL被 SUN公司收购后,又被 Oracle公司收购,因为Oracle公司专门做关系型商业收费数据库,所以很有可能在未来的某年MySQL也会变成商业版收费软件。为了避免这一情况,现在很多公司开始转向使用Mariadb数据库。 Mariadb数据库完全兼容MySQL数据库,包括API和命令行。目前最新的稳定版是10.3版。 2、下载 官方网站 https://mariadb.org/ 下载界面 https://downloads.mariadb.org/ 本次学习使用10.3版本 可以保存对应的下载链接在Linux中使用wget命令获取镜像。 3、解压缩文件 tar zxvf mariadb-10.3.13-linux-x86_64.tar.gz 3.1 常用的解压缩命令 解压.tar.gz文件 tar zxvf mariadb-10.3.13-linux-x86_64.tar.gz解压.tar.bz2文件 tar jxvf mariadb-10.3.13-linux-x86_64.tar.bz2解压.tar.xz文件 tar Jxvf mariadb-10.3.13-linux-x86_64.tar.xz 3.2 常用的压缩打包命令 tar zcvf mariadb-10.tar.gz 123/tar jcvf mariadb-10.tar.bz2 123/命令解析:将目录123/ 压缩打包为mariadb-10.tar.gz/bz2 4、拷贝解压后的文件至对应的目录并改名,方便后期维护 mv mariadb-10.3.13-linux-x86_64 /usr/local/mysql 5、查看安装步骤 [root@JSH-01 local]# cd mysql/[root@JSH-01 mysql]# less INSTALL-BINARY 6、创建目录 mkdir -p /data/mysql (其中参数 -p 是级联创建) 7、创建用户 useradd -M -s /sbin/nologin mysql (其中参数 -M 不创建家目录;-s 指定shell) 8、改变文件的拥有者和群组 chown -R mysql:mysql /data/mysql (其中参数 -R 指定目录以及其子目录下的所有文件) 命令解析: 目录/data/mysql及其子目录下的所有文件的拥有者和群组都是mysql。 8、初始化mariadb 生成自己的库文件 报错信息如下:此时需要安装 yum install -y libaio-devel 安装完依赖包后,再次执行初始化命令。输入 echo $? 查看安装结果 9、拷贝启动脚本并改名为mysqld,编辑拷贝后的文件。 [root@JSH-01 mysql]# cp support-files/mysql.server /etc/init.d/mysqld[root@JSH-01 mysql]# vi /etc/init.d/mysqld basedir=/usr/local/mysql #定义mysql程序存放目录datadir=/data/mysql #定义mysql数据库存放位置 10、系统服务与启动 10.1 chkconfig --list 列出系统所有的服务(针对 CentOS 6系统) 增加mysqld服务至系统服务列表 chkconfig --add mysqld前提:mysqld 在/etc/init.d 目录下;其次mysqld的权限为 755设置其随系统启动而启动:chkconfig mysqld on 10.2 systemctl list-unit-files 列出系统所有的服务(针对 CentOS 7系统) 11、启动mysqld服务 /etc/init.d/mysqld start 或者 service mysqld start(只要将其加入系统服务列表,就可以用后者启动) 报错信息: 编辑默认配置文件 vi /etc/my.cnf 修改对应的参数(如图) 一般讲socket放在 /tmp/ 目录下; 修改完成后,再次启动mysqld 如图所示,表示成功 12、查看进程 ps aux|grep mysql 13、查看3306端口 netstat -lnp 14、连接MySQL/MariaDB服务 15、首次连接需要输入的命令太长,怎么办? 解决方法1:软连接 解决方法2:系统环境变量(重启系统后会失效) 只有存在于/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin里面的命令才可以直接用。 将 /usr/local/mysql/bin 目录添加至系统环境变量中 解决方法3:系统环境变量(永久有效) [root@JSH-01 mysql]# echo "PATH=$PATH:usr/local/mysql/bin" >> /etc/profile 解析:/etc/profile 初始环境系统变量配置文件 16、别名 alias (可以理解为外号) 例如1:定义别名(仅针对当前窗口有效;重启或重新连接后就失效了) [root@JSH-01 ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 [root@JSH-01 ~]# alias vieth0='vi /etc/sysconfig/network-scripts/ifcfg-eth0' ##当重启或重新连接后就失效了 [root@JSH-01 ~]# ls -a . .bash_history .bash_profile .cache .mysql_history .pydistutils.cfg .tcshrc .. .bash_logout .bashrc .cshrc .pip .ssh [root@JSH-01 ~]# vi .bashrc 需要将别名写入当前用户家目录下的 .bashrc 文件中才能永久有效(针对当前用户) 需要将别名写入root用户/etc/bashrc 文件中才能永久有效(针对所有用户) 三、编译安装PHP 1、下载 官网 www.php.net 点击对应的文件格式后,会跳转至镜像站,选择国家后点击下载。复制对应的下载链接,在Linux中使用wget命令获取。 2、解压缩 [root@JSH-01 src]# tar zxvf php-7.3.2.tar.gz [root@JSH-01 src]# ls mariadb-10.3.13-linux-x86_64.tar.gz php-7.3.2 php-7.3.2.tar.gz 3、编译 3.1 编译第一步: ./configure配置编辑参数 进入PHP目录,vi INSTALL 可以看到编译指引链接https://php.net/install 编译参数如下: ./configure --prefix=/usr/local/php-fpm --with-config-file-path=/usr/local/php-fpm/etc --enable-fpm --with-fpm-user=php-fpm --with-fpm-group=php-fpm --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-pdo-mysql=/usr/local/mysql --with-mysql-sock=/tmp/mysql.sock --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-ftp --enable-mbstring --enable-exif --with-pear --with-curl --with-openssl 编译参数详解: --prefix=/usr/local/php-fpm 指定安装路径--with-config-file-path=/usr/local/php-fpm/etc 指定配置文件路径--enable-fpm 开启fpm功能(因为要对接Nginx)--with-fpm-user=php-fpm 指定fpm的用户--with-fpm-group=php-fpm 指定fpm的组--with-mysql=/usr/local/mysql 连接MySQL(兼容老版本)--with-mysqli=/usr/local/mysql/bin/mysql_config 连接MySQL(新版本)--with-pdo-mysql=/usr/local/mysql 连接MySQL的一种方式--with-mysql-sock=/tmp/mysql.sock 指定MySQL的socket 添加PHP的各种模块--with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-ftp --enable-mbstring --enable-exif --with-pear --with-curl --with-openssl 编译过程中的错误与解决方法 错误1: checking for cc ... no checking for gcc ... no 解决方法:安装编译器 yum install -y gcc 错误2: configure: error: libxml2 not found. Please check your libxml2 installation. 解决方法:yum list |grep libxml2(一般都是缺少开发包devel,所以此处安装 yum install -y libxml2-devel ) [root@JSH-01 php-7.3.2]# yum list |grep libxml2 libxml2.x86_64 2.9.1-6.el7_2.3 @anaconda libxml2.i686 2.9.1-6.el7_2.3 base libxml2-devel.i686 2.9.1-6.el7_2.3 base libxml2-devel.x86_64 2.9.1-6.el7_2.3 base libxml2-python.x86_64 2.9.1-6.el7_2.3 base libxml2-static.i686 2.9.1-6.el7_2.3 base libxml2-static.x86_64 2.9.1-6.el7_2.3 base mingw32-libxml2.noarch 2.9.3-1.el7 epel mingw32-libxml2-static.noarch 2.9.3-1.el7 epel mingw64-libxml2.noarch 2.9.3-1.el7 epel mingw64-libxml2-static.noarch 2.9.3-1.el7 epel 错误3: configure: error: Cannot find OpenSSL's <evp.h> 解决方法:yum install -y openssl-devel [root@JSH-01 php-7.3.2]# yum list |grep -i OpenSSL (-i参数:忽略大小写) openssl.x86_64 1:1.0.2k-8.el7 @anaconda openssl-libs.x86_64 1:1.0.2k-8.el7 @anaconda apr-util-openssl.x86_64 1.5.2-6.el7 base globus-gsi-openssl-error.x86_64 4.0-1.el7 epel globus-gsi-openssl-error-devel.x86_64 4.0-1.el7 epel globus-gsi-openssl-error-doc.noarch 4.0-1.el7 epel globus-openssl-module.x86_64 5.0-1.el7 epel globus-openssl-module-devel.x86_64 5.0-1.el7 epel globus-openssl-module-doc.noarch 5.0-1.el7 epel mingw32-openssl.noarch 1.0.2h-1.el7 epel mingw32-openssl-static.noarch 1.0.2h-1.el7 epel mingw64-openssl.noarch 1.0.2h-1.el7 epel mingw64-openssl-static.noarch 1.0.2h-1.el7 epel openssl.x86_64 1:1.0.2k-16.el7 base openssl-devel.i686 1:1.0.2k-16.el7 base openssl-devel.x86_64 1:1.0.2k-16.el7 base openssl-libs.i686 1:1.0.2k-16.el7 base openssl-libs.x86_64 1:1.0.2k-16.el7 base openssl-perl.x86_64 1:1.0.2k-16.el7 base openssl-pkcs11.x86_64 0.4.8-1.el7 epel openssl-static.i686 1:1.0.2k-16.el7 base openssl-static.x86_64 1:1.0.2k-16.el7 base openssl098e.i686 0.9.8e-29.el7.centos.3 base openssl098e.x86_64 0.9.8e-29.el7.centos.3 base perl-Crypt-OpenSSL-Bignum.x86_64 0.04-18.el7 base perl-Crypt-OpenSSL-RSA.x86_64 0.28-7.el7 base perl-Crypt-OpenSSL-Random.x86_64 0.04-21.el7 base perl-Crypt-OpenSSL-X509.x86_64 1.803-4.el7 epel pyOpenSSL.x86_64 0.13.1-4.el7 base pyOpenSSL-doc.noarch 0.13.1-4.el7 base rubygem-openssl_cms_2_0_0.x86_64 0.0.2-1.20140212git7fea071.el7 epel rubygem-openssl_cms_2_0_0-doc.noarch 0.0.2-1.20140212git7fea071.el7 epel xmlsec1-openssl.i686 1.2.20-7.el7_4 base xmlsec1-openssl.x86_64 1.2.20-7.el7_4 base xmlsec1-openssl-devel.i686 1.2.20-7.el7_4 base xmlsec1-openssl-devel.x86_64 1.2.20-7.el7_4 base 错误4: checking for cURL 7.15.5 or greater... configure: error: cURL version 7.15.5 or later is required to compile php with cURL support 解决方法:yum install -y libcurl-devel [root@JSH-01 ~]# yum list |grep curl curl.x86_64 7.29.0-42.el7 @anaconda libcurl.x86_64 7.29.0-42.el7 @anaconda python-pycurl.x86_64 7.19.0-19.el7 @anaconda collectd-curl.x86_64 5.8.1-1.el7 epel collectd-curl_json.x86_64 5.8.1-1.el7 epel collectd-curl_xml.x86_64 5.8.1-1.el7 epel curl.x86_64 7.29.0-51.el7 base curlftpfs.x86_64 0.9.2-14.el7 epel flickcurl.x86_64 1.25-2.el7 epel flickcurl-devel.x86_64 1.25-2.el7 epel libcurl.i686 7.29.0-51.el7 base libcurl.x86_64 7.29.0-51.el7 base libcurl-devel.i686 7.29.0-51.el7 base libcurl-devel.x86_64 7.29.0-51.el7 base mingw32-curl.noarch 7.47.0-1.el7 epel mingw32-curl-static.noarch 7.47.0-1.el7 epel mingw64-curl.noarch 7.47.0-1.el7 epel mingw64-curl-static.noarch 7.47.0-1.el7 epel nbdkit-plugin-curl.x86_64 1.2.7-2.el7 epel ocaml-curl.x86_64 0.7.5-3.el7 epel ocaml-curl-devel.x86_64 0.7.5-3.el7 epel python34-pycurl.x86_64 7.43.0-5.el7 epel uwsgi-alarm-curl.x86_64 2.0.17.1-1.el7 epel uwsgi-plugin-curl-cron.x86_64 2.0.17.1-1.el7 epel [root@JSH-01 ~]# yum install -y libcurl-devel 错误5: configure: error: jpeglib.h not found. 解决方法:yum install -y libjpeg-turbo-devel [root@JSH-01 php-7.3.2]# yum list |grep jpeg jpeginfo.x86_64 1.6.1-2.el7 epel jpegoptim.x86_64 1.4.6-1.el7 epel libjpeg-turbo.i686 1.2.90-6.el7 base libjpeg-turbo.x86_64 1.2.90-6.el7 base libjpeg-turbo-devel.i686 1.2.90-6.el7 base libjpeg-turbo-devel.x86_64 1.2.90-6.el7 base libjpeg-turbo-static.i686 1.2.90-6.el7 base libjpeg-turbo-static.x86_64 1.2.90-6.el7 base libjpeg-turbo-utils.x86_64 1.2.90-6.el7 base mingw32-libjpeg-turbo.noarch 1.3.1-4.el7 epel mingw32-libjpeg-turbo-static.noarch 1.3.1-4.el7 epel mingw64-libjpeg-turbo.noarch 1.3.1-4.el7 epel mingw64-libjpeg-turbo-static.noarch 1.3.1-4.el7 epel openjpeg.x86_64 1.5.1-18.el7 base openjpeg-devel.i686 1.5.1-18.el7 base openjpeg-devel.x86_64 1.5.1-18.el7 base openjpeg-libs.i686 1.5.1-18.el7 base openjpeg-libs.x86_64 1.5.1-18.el7 base openjpeg2.x86_64 2.3.0-6.el7 epel openjpeg2-devel.x86_64 2.3.0-6.el7 epel openjpeg2-devel-docs.noarch 2.3.0-6.el7 epel openjpeg2-tools.x86_64 2.3.0-6.el7 epel turbojpeg.i686 1.2.90-6.el7 base turbojpeg.x86_64 1.2.90-6.el7 base turbojpeg-devel.i686 1.2.90-6.el7 base turbojpeg-devel.x86_64 1.2.90-6.el7 base 错误6: configure: error: png.h not found. 解决方法: yum install -y libpng-devel [root@JSH-01 php-7.3.2]# yum list |grep png|grep devel libpng-devel.i686 2:1.5.13-7.el7_2 base libpng-devel.x86_64 2:1.5.13-7.el7_2 base libpng12-devel.i686 1.2.50-10.el7 base libpng12-devel.x86_64 1.2.50-10.el7 base pnglite-devel.x86_64 0.1.17-1.el7.8 epel 错误7: configure: error: freetype-config not found. 解决方法:yum install -y freetype-devel [root@JSH-01 php-7.3.2]# yum list |grep freetype|grep devel freetype-devel.i686 2.8-12.el7_6.1 updates freetype-devel.x86_64 2.8-12.el7_6.1 updates 错误8:提示mysql的版本不对,即安装的mysql版本太新 configure: error: wrong mysql library version or lib not found. Check config.log for more information. 解决方法:下载一个低版本的MySQL或者MariaDB(不需要安装)在 /usr/local/src/ 目录中下载MySQL5.6版本的二进制包、并解压缩,修改编译参数 [root@JSH-01 src]# wget http://mirrors.163.com/mysql/Downloads/MySQL-5.6/mysql-5.6.43-linux-glibc2.12-x86_64.tar.gz [root@JSH-01 src]# tar zxf mysql-5.6.43-linux-glibc2.12-x86_64.tar.gz [root@JSH-01 src]# mv mysql-5.6.43-linux-glibc2.12-x86_64 /usr/local/mysql5.6 新编译参数:./configure --prefix=/usr/local/php-fpm --with-config-file-path=/usr/local/php-fpm/etc --enable-fpm --with-fpm-user=php-fpm --with-fpm-group=php-fpm --with-mysql=/usr/local/mysql5.6 --with-mysqli=/usr/local/mysql5.6/bin/mysql_config --with-pdo-mysql=/usr/local/mysql5.6 --with-mysql-sock=/tmp/mysql.sock --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-ftp --enable-mbstring --enable-exif --with-pear --with-curl --with-openssl 警告:新版本的编译已经不需要如下的参数。所以可以在编译参数中删除。当然加上也不影响编译。 configure: WARNING: unrecognized options: --with-mysql, --with-mcrypt, --enable-gd-native-ttf 3.2 编译第二步:make将源码文件编译为二进制文件(通过使用GCC编译) Build complete. #看到该提示,表示编译完成 Don't forget to run 'make test'. [root@JSH-01 php-7.3.2]# echo $? #查看编译过程是够成功,如果是0则表示成功 0 3.3 编译第三步:make install 安装 [root@JSH-01 php-7.3.2]# ls /usr/local/php-fpm/ #安装完成后查看该目录的内容 bin etc include lib php sbin var #配置文件在 /etc/目录中 [root@JSH-01 php-7.3.2]# cd /usr/local/php-fpm/etc/ [root@JSH-01 etc]# ls pear.conf php-fpm.conf.default php-fpm.d 4、拷贝生成配置文件 php-fpm.conf 否则PHP无法启动 [root@JSH-01 etc]# cp php-fpm.conf.default php-fpm.conf #复制生成配置文件,否则PHP无法启动 [root@JSH-01 etc]# ls pear.conf php-fpm.conf php-fpm.conf.default php-fpm.d 5、拷贝生成配置文件 php.ini 到 /usr/local/php-fpm/etc/目录下 默认PHP的源码包中有:php.ini-development(开发环境) 和 php.ini-production(生产环境)根据需要拷贝生成。如果用于开发、测试环境则拷贝php.ini-development(开发环境)生成配置文件 php.ini;如果用于生产环境则拷贝php.ini-production(生产环境)生成配置文件 php.ini; [root@JSH-01 php-7.3.2]# cp php.ini-development /usr/local/php-fpm/etc/php.ini 5、配置启动脚本并设置权限 [root@JSH-01 php-7.3.2]# cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm [root@JSH-01 php-7.3.2]# chmod 755 /etc/init.d/php-fpm 6、设置PHP开机启动 [root@JSH-01 php-7.3.2]# chkconfig --add php-fpm [root@JSH-01 php-7.3.2]# chkconfig php-fpm on 7、启动PHP服务 service php-fpm start 报错1: [root@JSH-01 php-7.3.2]# service php-fpm start Starting php-fpm [01-Mar-2019 11:17:58] WARNING: Nothing matches the include pattern '/usr/local/php-fpm/etc/php-fpm.d/*.conf' from /usr/local/php-fpm/etc/php-fpm.conf at line 143. [01-Mar-2019 11:17:58] ERROR: No pool defined. at least one pool section must be specified in config file [01-Mar-2019 11:17:58] ERROR: failed to post process the configuration [01-Mar-2019 11:17:58] ERROR: FPM initialization failed failed 解决方法:在目录 /usr/local/php-fpm/etc/php-fpm.d/ 拷贝生成配置文件 www.conf [root@JSH-01 php-7.3.2]# cd /usr/local/php-fpm/etc/php-fpm.d/ [root@JSH-01 php-fpm.d]# ls www.conf.default [root@JSH-01 php-fpm.d]# cp www.conf.default www.conf 报错2: [root@JSH-01 php-fpm.d]# service php-fpm start Starting php-fpm [01-Mar-2019 11:28:07] ERROR: [pool www] cannot get uid for user 'php-fpm' [01-Mar-2019 11:28:07] ERROR: FPM initialization failed failed 解决方法:创建用户 php-fpm (因为编译的时候未创建) [root@JSH-01 php-fpm.d]# useradd php-fpm 8、再次启动,成功后检查服务及端口 9000 [root@JSH-01 php-fpm.d]# service php-fpm start Starting php-fpm done [root@JSH-01 php-fpm.d]# ps aux |grep php-fpm root 15099 0.0 0.2 127020 4220 ? Ss 11:29 0:00 php-fpm: master process (/usr/local/php-fpm/etc/php-fpm.conf) php-fpm 15100 0.0 0.2 127020 4152 ? S 11:29 0:00 php-fpm: pool www php-fpm 15101 0.0 0.2 127020 4152 ? S 11:29 0:00 php-fpm: pool www root 16510 0.0 0.0 112632 660 pts/0 D+ 11:31 0:00 grep --color=auto php-fpm [root@JSH-01 php-fpm.d]# netstat -lntp 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:22 0.0.0.0:* LISTEN 3207/sshd tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 15099/php-fpm: mast tcp6 0 0 :::3306 :::* LISTEN 19939/mysqld 四、编译安装Nginx 1、Nginx官网 http://nginx.org/ Mainline version:Mainline 是 Nginx 目前主力在做的版本,可以说是开发版Stable version:最新稳定版,生产环境上建议使用的版本Legacy versions:遗留的老版本的稳定版 2、下载 [root@JSH-01 php-fpm.d]# cd /usr/local/src [root@JSH-01 src]# wget http://nginx.org/download/nginx-1.14.2.tar.gz 本次学习安装使用 Stable version 1.14.2 版本 3、解压缩 [root@JSH-01 src]# tar zxvf nginx-1.14.2.tar.gz 4、编译 编译参数如下: ./configure --prefix=/usr/local/nginx --with-http_ssl_module [root@JSH-01 src]# cd nginx-1.14.2 #进入文件目录 [root@JSH-01 nginx-1.14.2]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module #编译 [root@JSH-01 nginx-1.14.2]# echo $? #检查编译过程是否成功,0表示成功 0 5、编译 make 6、编译安装 make install 7、Nginx配置脚本 [root@JSH-01 ~]# ls /usr/local/nginx/conf/nginx.conf 8、启动Nginx服务: /usr/local/nginx/sbin/nginx [root@JSH-01 nginx]# /usr/local/nginx/sbin/nginx [root@JSH-01 nginx]# ps aux|grep nginx #访问网站时使用的为 worker process 进程 root 12167 0.0 0.0 45896 1120 ? Ss 16:10 0:00 nginx: master process /usr/local/nginx/sbin/nginx nobody 12168 0.0 0.1 46344 1896 ? S 16:10 0:00 nginx: worker process root 13114 0.0 0.0 112660 968 pts/0 R+ 16:11 0:00 grep --color=auto nginx [root@JSH-01 nginx]# netstat -lntp |grep nginx #监控的为80端口 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 12167/nginx: master

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册