架构和运维技术高峰论坛参会有感

几个关键字:AIops机器人微服务容器

机器人这个概念几年前在巨人的时候,团队就已经提出来了,用robot代替人工巡检,定时批量去完成一些定义好的job,携程的专家说的好,招不下人的时候自己招个"机器人"来完成一些简单的任务,这也是个不错的idea。

微服务最近这两年很热,大小厂及团队都在搞,每个人对微服务的这个理解不太一样,但是基本都是这个模式,按功能模块切分,但要有个度,不能太细,对外提供统一API接口提供服务,语言可以是好几种组合,可以参考下面几个图;
1.jpg


---阅读剩余部分---

PostgreSQL备份与恢复

postgresql数据库的备份和还原命令pg_dump
单个库纯文本SQL格式的备份:

pg_dump -U postgres -d myDBname -f dump.sql

还原:

psql -U username -f filename dbname 

使用pg_dumpall备份:

pg_dumpall -U postgres > alldbs.pgsql

恢复所有数据库:

psql -f filename

备份和恢复单个表
备份:从一个名为mydb的数据库中备份mytable一个表。

pg_dump -U postgres -d mydb -t mytable > mydb-mytable.pgsql

还原:单表备份到数据库中还原。请确保您的备份文件包含要恢复唯一的单表备份。

psql -U postgres -d mydb 
pg_dump 把一个数据库转储为纯文本文件或者是其它格式.

用法:
  pg_dump [选项]... [数据库名字]

一般选项:
  -f, --file=FILENAME          输出文件或目录名
  -F, --format=c|d|t|p         输出文件格式 (定制, 目录, tar)
                               明文 (默认值))
  -j, --jobs=NUM               执行多个并行任务进行备份转储工作
  -v, --verbose                详细模式
  -V, --version                输出版本信息,然后退出
  -Z, --compress=0-9           被压缩格式的压缩级别
  --lock-wait-timeout=TIMEOUT  在等待表锁超时后操作失败
  -?, --help                   显示此帮助, 然后退出

控制输出内容选项:
  -a, --data-only              只转储数据,不包括模式
  -b, --blobs                  在转储中包括大对象
  -c, --clean                  在重新创建之前,先清除(删除)数据库对象
  -C, --create                 在转储中包括命令,以便创建数据库
  -E, --encoding=ENCODING      转储以ENCODING形式编码的数据
  -n, --schema=SCHEMA          只转储指定名称的模式
  -N, --exclude-schema=SCHEMA  不转储已命名的模式
  -o, --oids                   在转储中包括 OID
  -O, --no-owner               在明文格式中, 忽略恢复对象所属者

  -s, --schema-only            只转储模式, 不包括数据
  -S, --superuser=NAME         在明文格式中使用指定的超级用户名
  -t, --table=TABLE            只转储指定名称的表
  -T, --exclude-table=TABLE    不转储指定名称的表
  -x, --no-privileges          不要转储权限 (grant/revoke)
  --binary-upgrade             只能由升级工具使用
  --column-inserts             以带有列名的INSERT命令形式转储数据
  --disable-dollar-quoting     取消美元 (符号) 引号, 使用 SQL 标准引号
  --disable-triggers           在只恢复数据的过程中禁用触发器
  --enable-row-security        启用行安全性(只转储用户能够访问的内容)
  --exclude-table-data=TABLE   不转储指定名称的表中的数据
  --if-exists              当删除对象时使用IF EXISTS
  --inserts                    以INSERT命令,而不是COPY命令的形式转储数据
  --no-security-labels         不转储安全标签的分配
  --no-synchronized-snapshots  在并行工作集中不使用同步快照
  --no-tablespaces             不转储表空间分配信息
  --no-unlogged-table-data     不转储没有日志的表数据
  --quote-all-identifiers      所有标识符加引号,即使不是关键字
  --section=SECTION            备份命名的节 (数据前, 数据, 及 数据后)
  --serializable-deferrable   等到备份可以无异常运行
  --snapshot=SNAPSHOT          为转储使用给定的快照
  --strict-names               要求每个表和/或schema包括模式以匹配至少一个实体
  --use-set-session-authorization
                               使用 SESSION AUTHORIZATION 命令代替
  ALTER OWNER 命令来设置所有权

联接选项:
  -d, --dbname=DBNAME       对数据库 DBNAME备份
  -h, --host=主机名        数据库服务器的主机名或套接字目录
  -p, --port=端口号        数据库服务器的端口号
  -U, --username=名字      以指定的数据库用户联接
  -w, --no-password        永远不提示输入口令
  -W, --password           强制口令提示 (自动)
  --role=ROLENAME          在转储前运行SET ROLE

如果没有提供数据库名字, 那么使用 PGDATABASE 环境变量的数值.

PostgreSQL常用操作命令整理

使用yum安装PostgreSQL:
安装PostgreSQL客户端

yum install postgresql-client -y

安装PostgreSQL服务端:

yum install postgresql -y

安装完成后,PostgreSQL服务器会自动在本机的5432端口开启。
安装图形管理界面(可选)

yum install pgadmin3 -y

启动服务

service postgresql start

安装参考:https://mhl.xyz/PostgreSQL/centos7-4-install-postgresql10-1.html
进入控制台

psql -U dbuser -d exampledb -h 127.0.0.1 -p 5432

退出

postgres=# \q

创建用户

CREATE USER youusername WITH PASSWORD 'youpassword';

创建数据库并赋予用户

postgres=# CREATE DATABASE youdbname OWNER youusername;
postgres=# GRANT ALL PRIVILEGES ON DATABASE youdbname to youusername;
postgres=# \c youdbname;
postgres=# ALTER SCHEMA public OWNER to dbuser;
postgres=# GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO youusername;
postgres=# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO youusername;

查看所有用户

postgres=# \du

更改密码

postgres=# \password youusername

删除用户

postgres=# drop user youusername ;

查看所有库

postgres=# \l

切换数据库

postgres=# \c exampledb

常用控制台命令

\password           设置密码。
\q                  退出。
\h                  查看SQL命令的解释,比如\h select。
\?                  查看psql命令列表。
\l                  列出所有数据库。
\c [database_name]  连接其他数据库。
\d                  列出当前数据库的所有表格。
\d [table_name]     列出某一张表格的结构。
\du                 列出所有用户。
\e                  打开文本编辑器。
\conninfo           列出当前数据库和连接的信息。

基本的 SQL 语句

# 创建新表
CREATE TABLE user_tbl(name VARCHAR(20), signup_date DATE);

# 插入数据
INSERT INTO user_tbl(name, signup_date) VALUES('张三', '2013-12-22');

# 查询记录
SELECT * FROM user_tbl;

# 更新数据
UPDATE user_tbl set name = '李四' WHERE name = '张三';

# 删除记录
DELETE FROM user_tbl WHERE name = '李四' ;

# 添加字段
ALTER TABLE user_tbl ADD email VARCHAR(40);

# 更改字段类型
ALTER TABLE user_tbl ALTER COLUMN signup_date SET NOT NULL;

# 设置字段默认值(注意字符串使用单引号)
ALTER TABLE user_tbl ALTER COLUMN email SET DEFAULT 'example@example.com';

# 去除字段默认值
ALTER TABLE user_tbl ALTER email DROP DEFAULT;

# 重命名字段
ALTER TABLE user_tbl RENAME COLUMN signup_date TO signup;

# 删除字段
ALTER TABLE user_tbl DROP COLUMN email;

# 表重命名
ALTER TABLE user_tbl RENAME TO backup_tbl;

# 删除表
DROP TABLE IF EXISTS backup_tbl;

# 删除库
\c hello2;
DROP DATABASE IF EXISTS hello;

MySQL报错This function has none of DETERMINISTIC解决

创建存储过程出错log

ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)

原因:开启了bin-log就须指函数是否是

1 DETERMINISTIC 不确定的

2 NO SQL 没有SQl语句,当然也不会修改数据

3 READS SQL DATA 只是读取数据,当然也不会修改数据

4 MODIFIES SQL DATA 要修改数据

5 CONTAINS SQL 包含了SQL语句

其中在function里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。
如果开启了 bin-log, 我们就必须为function指定一个参数。
临时设置:

mysql> show variables like 'log_bin_trust_function_creators';
+---------------------------------+-------+
| Variable_name          | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | OFF  |
+---------------------------------+-------+
mysql> set global log_bin_trust_function_creators=1;
mysql> show variables like 'log_bin_trust_function_creators';
+---------------------------------+-------+
| Variable_name          | Value |
+---------------------------------+-------+
| log_bin_trust_function_creators | ON  |

修改配置文件my.cnf在mysqld部分增加

log_bin_trust_function_creators=1
/etc/init.d/mysql restart

重启MySQL服务。

吃芒果过敏了

以前买芒果都是大点的,吃了好多次,也没过敏过;

这次买的小芒果,具体名字忘记了,结果吃了4个以后第二天过敏了,反应出来了,手背、胳膊上和腿上出来了好多小红片,有点痒,手“胖”了不少,冏、冏、冏......

---阅读剩余部分---

kafka报错INFO Reconnect due to socket error: java.nio.channels.ClosedChannelException (kafka.consumer.SimpleConsumer

kafka安装启动以后server.log一直报INFO Reconnect due to socket error: java.nio.channels.ClosedChannelException (kafka.consumer.SimpleConsumer错误信息,如下

[2018-06-19 09:43:29,783] INFO Reconnect due to socket error: java.nio.channels.ClosedChannelException (kafka.consumer.SimpleConsumer)
[2018-06-19 09:43:29,783] WARN [ReplicaFetcherThread-0-1], Error in fetch Name: FetchRequest; Version: 0; CorrelationId: 518500; ClientId: ReplicaFetcherThread-0-1; ReplicaId: 2; MaxWait: 500 ms; MinBytes: 1 bytes; RequestInfo: [a6,5] -> PartitionFetchInfo(0,1048576),[a6,3] -> PartitionFetchInfo(0,1048576),[a6,7] -> PartitionFetchInfo(0,1048576),[a6,1] -> PartitionFetchInfo(0,1048576),[a6,9] -> PartitionFetchInfo(0,1048576). Possible cause: java.nio.channels.ClosedChannelException (kafka.server.ReplicaFetcherThread)
[2018-06-19 09:43:29,783] INFO Reconnect due to socket error: java.nio.channels.ClosedChannelException (kafka.consumer.SimpleConsumer)
[2018-06-19 09:43:29,783] WARN [ReplicaFetcherThread-0-1], Error in fetch Name: FetchRequest; Version: 0; CorrelationId: 518501; ClientId: ReplicaFetcherThread-0-1; ReplicaId: 2; MaxWait: 500 ms; MinBytes: 1 bytes; RequestInfo: [a6,5] -> PartitionFetchInfo(0,1048576),[a6,3] -> PartitionFetchInfo(0,1048576),[a6,7] -> PartitionFetchInfo(0,1048576),[a6,1] -> PartitionFetchInfo(0,1048576),[a6,9] -> PartitionFetchInfo(0,1048576). Possible cause: java.nio.channels.ClosedChannelException (kafka.server.ReplicaFetcherThread)
[2018-06-19 09:43:29,783] INFO Reconnect due to socket error: java.nio.channels.ClosedChannelException (kafka.consumer.SimpleConsumer)
[2018-06-19 09:43:29,783] WARN [ReplicaFetcherThread-0-1], Error in fetch Name: FetchRequest; Version: 0; CorrelationId: 518502; ClientId: ReplicaFetcherThread-0-1; ReplicaId: 2; MaxWait: 500 ms; MinBytes: 1 bytes; RequestInfo: [a6,5] -> PartitionFetchInfo(0,1048576),[a6,3] -> PartitionFetchInfo(0,1048576),[a6,7] -> PartitionFetchInfo(0,1048576),[a6,1] -> PartitionFetchInfo(0,1048576),[a6,9] -> PartitionFetchInfo(0,1048576). Possible cause: java.nio.channels.ClosedChannelException (kafka.server.ReplicaFetcherThread)

原因是/etc/hosts文件里面没有添加kafka集群的机器名,

10.0.28.51 huafadb1
10.0.28.52 huafadb2

10.0.28.51    k1
10.0.28.52    k2
10.0.28.51    k3
                
10.0.28.51    z1
10.0.28.52    z2
10.0.28.51    z3

一般容易忘记前面两个主机名,huafadb1和huafadb2对应的IP,每个集群机器都添加,添加完成以后重启kafka服务即可解决。

Redis高可用方案之sentinel(哨兵集群)

Redis哨兵为Redis提供了高可用性。实际上这意味着你可以使用哨兵模式创建一个可以不用人为干预而应对各种故障的Redis部署。

监控:哨兵不断的检查master和slave是否正常的运行。
通知:当监控的某台Redis实例发生问题时,可以通过API通知系统管理员和其他的应用程序。
自动故障转移:如果一个master不正常运行了,哨兵可以启动一个故障转移进程,将一个slave升级成为master,其他的slave被重新配置使用新的master,并且应用程序使用Redis服务端通知的新地址。
配置提供者:哨兵作为Redis客户端发现的权威来源:客户端连接到哨兵请求当前可靠的master的地址。如果发生故障,哨兵将报告新地址。

Redis哨兵是一个分布式系统:
哨兵自身被设计成和多个哨兵进程一起合作运行。有多个哨兵进程合作的好处有:

当多个哨兵对一个master不再可用达成一致时执行故障检测。这会降低错误判断的概率。
即使在不是所有的哨兵都工作时哨兵也会工作,使系统健壮的抵抗故障。毕竟在故障系统里单点故障没有什么意义。
Redis的哨兵、Redis实例(master和slave)、和客户端是一个有特种功能的大型分布式系统。

部署哨兵之前需要了解的基本事情:

一个健壮的部署至少需要三个哨兵实例。
三个哨兵实例应该放置在客户使用独立方式确认故障的计算机或虚拟机中。例如不同的物理机或不同可用区域的虚拟机。
sentinel + Redis实例不保证在故障期间保留确认的写入,因为Redis使用异步复制。然而有方式部署哨兵使丢失数据限制在特定时刻,虽然有更安全的方式部署它。
你的客户端要支持哨兵,流行的客户端都支持哨兵,但不是全部。
没有HA设置是安全的,如果你不经常的在开发环境测试,在生产环境他们会更好。你可能会有一个明显的错误配置只是当太晚的时候。
Sentinel,Docker,或者其他形式的网络地址交换或端口映射需要加倍小心:Docker执行端口重新映射,破坏Sentinel自动发现其他的哨兵进程和master的slave列表。

机器信息:
192.168.121.40 Master
192.168.121.41 Slave1
192.168.121.42 Slave2
Master(192.168.121.40)机器配置如下:
redis.conf

cat redis.conf | grep -v "#"

bind 127.0.0.1 192.168.121.40

protected-mode yes

port 6879

tcp-backlog 511

timeout 0

tcp-keepalive 300

daemonize yes

supervised no

pidfile "/usr/local/redis-4.0.10_6879/redis_6879.pid"

loglevel notice

logfile "/usr/local/redis-4.0.10_6879/redis_6879.log"

databases 16

always-show-logo yes
save 900 1
save 300 10
save 60 10000

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename "dump.rdb"

dir "/usr/local/redis-4.0.10_6879"

slave-serve-stale-data yes

slave-read-only yes

repl-diskless-sync no

repl-diskless-sync-delay 5

repl-disable-tcp-nodelay no

slave-priority 100

lazyfree-lazy-eviction no

lazyfree-lazy-expire no

lazyfree-lazy-server-del no

slave-lazy-flush no

appendonly yes

appendfilename "appendonly.aof"

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

aof-load-truncated yes

aof-use-rdb-preamble no

lua-time-limit 5000

cluster-node-timeout 15000

slowlog-log-slower-than 10000

slowlog-max-len 128

latency-monitor-threshold 0

notify-keyspace-events ""

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-size -2

list-compress-depth 0

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

hll-sparse-max-bytes 3000

activerehashing yes

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

hz 10

aof-rewrite-incremental-fsync yes

slaveof 192.168.121.41 6879

Slave1和Slave2配置相同,只是bind处需要把IP改成41和42
Master的sentinel.conf哨兵配置文件:
Redis源码发布包包含一个sentinel.conf的文件,Master(192.168.121.40)机器配置如下:

cat sentinel.conf 
port 26879  
#1表示在sentinel集群中只要有两个节点检测到redis主节点出故障就进行切换,单sentinel节点无效(自己测试发现的)  
#如果3s内mymaster无响应,则认为mymaster宕机了  
#如果10秒后,mysater仍没活过来,则启动failover  
sentinel monitor mymaster 192.168.121.40 6879 1  
sentinel down-after-milliseconds mymaster 3000  
sentinel failover-timeout mymaster 10000  
daemonize yes  
#指定工作目录  
dir "/data/redis/sentinel-work"  
protected-mode no  
logfile "/data/redis/sentinellog/sentinel.log"  
# Generated by CONFIG REWRITE

Slave(192.168.121.41-42)机器配置同上
注意:以上配置中不存在的文件路径需要手动创建。哨兵可配置多个,最好是最少3个节点,配置相同。

启动集群
启动192.168.121.40-41--42各机器Redis节点命令如下:

/usr/local/redis-4.0.10_6879/src/redis-server /usr/local/redis-4.0.10_6879/redis.conf 

启动各Redis哨兵节点命令如下:

/usr/local/redis-4.0.10_6879/src/redis-sentinel /usr/local/redis-4.0.10_6879/sentinel.conf 

三台都启动完成以后登陆 列出Slave的信息

[root@wgq_idc_cache_3_40 redis-4.0.10_6879]# /usr/local/redis-4.0.10_6879/src/redis-cli -p 6879
127.0.0.1:6879> info Replication
# Replication
role:slave
master_host:192.168.121.41
master_port:6879
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:2049886
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:50eb71744c1aacc84bd865ff3af7ee1902395634
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2049886
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1001311
repl_backlog_histlen:1048576

查看启动sentinel.log

cat sentinel.log 
4453:X 15 Jun 17:09:41.774 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
4453:X 15 Jun 17:09:41.774 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=4453, just started
4453:X 15 Jun 17:09:41.774 # Configuration loaded
4454:X 15 Jun 17:09:41.779 * Running mode=sentinel, port=26879.
4454:X 15 Jun 17:09:41.779 # Sentinel ID is 5092d7a7096ec024a1d15e0fc903f7c289d4bd8a
4454:X 15 Jun 17:09:41.779 # +monitor master mymaster 192.168.121.40 6879 quorum 1
4454:X 15 Jun 17:12:47.369 # +sdown master mymaster 192.168.121.40 6879
4454:X 15 Jun 17:12:47.369 # +odown master mymaster 192.168.121.40 6879 #quorum 1/1
4454:X 15 Jun 17:12:47.369 # +new-epoch 1
4454:X 15 Jun 17:12:47.369 # +try-failover master mymaster 192.168.121.40 6879
4454:X 15 Jun 17:12:47.370 # +vote-for-leader 5092d7a7096ec024a1d15e0fc903f7c289d4bd8a 1
4454:X 15 Jun 17:12:47.371 # +elected-leader master mymaster 192.168.121.40 6879
4454:X 15 Jun 17:12:47.371 # +failover-state-select-slave master mymaster 192.168.121.40 6879
4454:X 15 Jun 17:12:47.442 # +selected-slave slave 192.168.121.42:6879 192.168.121.42 6879 @ mymaster 192.168.121.40 6879
4454:X 15 Jun 17:12:47.442 * +failover-state-send-slaveof-noone slave 192.168.121.42:6879 192.168.121.42 6879 @ mymaster 192.168.121.40 6879
4454:X 15 Jun 17:12:47.572 * +failover-state-wait-promotion slave 192.168.121.42:6879 192.168.121.42 6879 @ mymaster 192.168.121.40 6879
4454:X 15 Jun 17:12:48.401 # +promoted-slave slave 192.168.121.42:6879 192.168.121.42 6879 @ mymaster 192.168.121.40 6879

到这里我们已经完成了sentinel集群的搭建;
如果启动有此警告信息:

WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

方法1: 临时设置生效:

sysctl -w net.core.somaxconn = 65535
sysctl -w vm.overcommit_memory = 1

方法2: 永久生效: 修改/etc/sysctl.conf文件,增加一行

net.core.somaxconn = 65535
vm.overcommit_memory = 1

然后执行命令

sysctl -p

参考:http://redis.majunwei.com/topics/sentinel.html

ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务

Ucloud云上Oracle数据库服务器,由于物理机宕机重启,造成虚机也重启了,手动启动oracle服务和listen监听以后,PL/SQL客户端和应用都无法连接,提示“ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务”,数据库版本Oracle 11g R2,
初步判断是listener.ora 文件有问题,

# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.28.109.115)(PORT = 1521))
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = /data/app/oracle/product/11.2.0/db_1)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (SID_NAME = earth_m1)
      (ORACLE_HOME = /data/app/oracle/product/11.2.0/db_1)
    )
  )

ADR_BASE_LISTENER = /data/app/oracle

备份原来监听文件:

cp /data/app/oracle/product/11.2.0/db_1/network/admin/listener.ora /tmp/listener.ora

修改为如下:

vim /data/app/oracle/product/11.2.0/db_1/network/admin/listener.ora
# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.28.109.115)(PORT = 1521))
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = powerdes)
      (ORACLE_HOME = /data/app/oracle/product/11.2.0/db_1)
      (SID_NAME = powerdes)
    )
    (SID_DESC =
      (SID_NAME = earth_m1)
      (ORACLE_HOME = /data/app/oracle/product/11.2.0/db_1)
    )
  )

ADR_BASE_LISTENER = /data/app/oracle

Listener主动加载服务

  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = powerdes)
      (ORACLE_HOME = /data/app/oracle/product/11.2.0/db_1)
      (SID_NAME = powerdes)
    )

添加GLOBAL_DBNAME后在使用lsnrctl start监听程序时会将listener的服务注册到进程监视器(pmon)中,如果没有这个配置,则为Listener被动加载服务由实例的pmon进程在listener中注册服务,对listener来讲,就是被动了,也就是为什么先启动监听后启动数据库能够正常连接的,反之不行的原因了。

Kvm虚拟机静态迁移

什么是静态迁移?
静态迁移:也叫做常规迁移、离线迁移(Offline Migration)。就是在虚拟机关机或暂停的情况下从一台物理机迁移到另一台物理机。因为虚拟机的文件系统建立在虚拟机镜像上面,所以在虚拟机关机的 情况下,只需要简单的迁移虚拟机镜像和相应的配置文件到另外一台物理主机上;如果需要保存虚拟机迁移之前的状态,在迁移之前将虚拟机暂停,然后拷贝状态至目的主机,最后在目的主机重建虚拟机状态,恢复执行。这种方式的迁移过程需要显式的停止虚拟机的运行。从用户角度看,有明确的一段停机时间,虚拟机上的服务不可用。这种迁移方式简单易行,适用于对服务可用性要求不严格的场合。

说明
(1)虚拟主机各自使用本地存储存放虚拟机磁盘文件
本文实现基于本地磁盘存储虚拟机磁盘文件的迁移方式

(2)虚拟主机之间使用共享存储存放虚拟机磁盘文件
该方式只是在目标虚拟主机上重新定义虚拟机就可以了

静态迁移过程
1、确定虚拟机关闭状态

[root@dev_test_25 ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 -     c160                           关闭
 -     wangya_win7                    关闭
 -     winxp_test                     关闭

2、准备迁移c160虚拟机,查看该虚拟机配置的磁盘文件

[root@dev_test_25 ~]# virsh domblklist c160
Target     Source
------------------------------------------------
vda        /home/c160
hdc        -

3、导出虚拟机配置文件

virsh dumpxml c160 > /opt/c160.xml

4、拷贝配置文件到目标主机上

scp /opt/c160.xml 192.168.121.200:/etc/libvirt/qemu/

5、拷贝虚拟磁盘文件

scp -r /home/c160 192.168.121.200:/kvm

目标虚拟主机
上面已经将虚拟机磁盘文件与配置文件都已经复制到目标虚拟主机上了。下面开始配置与启动。
1、对虚拟主机进行注册

virsh define /etc/libvirt/qemu/c160.xml

2、查看目标虚拟主机环境

virsh list --all
 Id    Name                           State
----------------------------------------------------
 8     c160                           shut off

3、确认源地址和迁移后的磁盘路径一致,如果不一致做个软连接即可,否则不能启动
如原来的路径在/home/c160,迁移以后的地址在/kvm/c160 做下软连接即可:

ln -s /kvm/c160 /home/c160

4、最后启动虚拟机

virsh start c160

启动完成以后可以ssh登陆上去检查下,至此kvm静态迁移完毕。
若把虚拟机静态迁移到不同平台(不同型号的cpu)的主机上,启动的时候报错,根据错误提示修改/etc/libvirt/qemu/下面的虚拟配置文件即可。

Keepalived构建高可用MySQL互为主从自动切换

关于MySQL-HA,目前有多种解决方案,比如heartbeat、drbd、mmm、共享存储,但是它们各有优缺点。heartbeat、drbd配置较为复杂,需要自己写脚本才能实现MySQL自动切换,对于不会脚本语言的人来说,这无疑是一种脑裂问题;对于mmm,生产环境中很少有人用,且mmm管理端需要单独运行一台服务器上,要是想实现高可用,就得对mmm管理端做HA,这样增加了硬件开支;对于共享存储,数据还是放在本地较为安全,存储设备毕竟存在单点隐患。

Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7交换机制软件,具备我们平时说的第3层、第4层和第7层交换机的功能。主要提供loadbalancing(负载均衡)和 high-availability(高可用)功能,负载均衡实现需要依赖Linux的虚拟服务内核模块(ipvs),而高可用是通过VRRP协议实现多台机器之间的故障转移服务。
keepalived.jpg
上图是Keepalived的功能体系结构,大致分两层:用户空间(user space)和内核空间(kernel space)。
内核空间:主要包括IPVS(IP虚拟服务器,用于实现网络服务的负载均衡)和NETLINK(提供高级路由及其他相关的网络功能)两个部份。
用户空间:

WatchDog:负载监控checkers和VRRP进程的状况
VRRP Stack:负载负载均衡器之间的失败切换FailOver,如果只用一个负载均稀器,则VRRP不是必须的。
Checkers:负责真实服务器的健康检查healthchecking,是keepalived最主要的功能。换言之,可以没有VRRP Stack,但健康检查healthchecking是一定要有的。
IPVS wrapper:用户发送设定的规则到内核ipvs代码
Netlink Reflector:用来设定vrrp的vip地址等。

使用MySQL双master+keepalived是一种非常好的解决方案,在MySQL-HA环境 中,MySQL互为主从关系,这样就保证了两台MySQL数据的一致性,然后用keepalived实现虚拟IP,通过keepalived自带的服务监控功能来实现MySQL故障时自动切换。

实现过程如下:
1、机器网络拓扑等信息:

MySQL-VIP:10.10.200.30    
mysqldb1:10.10.200.11    
mysqldb2:10.10.200.12   
   
OS版本:CentOS 7.4    
MySQL版本:5.7.22    
Keepalived版本:1.4.5

2、MySQL配置文件修改:
db1和db2互为主从,需要修改server-id为不同,具体参考基于GTID的主从复制过程实现:https://mhl.xyz/MySQL/gtid-master-slave.html
如上述均正确配置,现在任何一台MySQL上更新数据都会同步到另一台MySQL,即互为主从,MySQL同步在此叙述。
3、keepalived安装及配置

yum install popt popt-devel libnl libnl-devel libnfnetlink-devel -y #安装基础库文件
wget http://www.keepalived.org/software/keepalived-1.4.5.tar.gz
tar xvf keepalived-1.4.5.tar.gz
cd keepalived-1.4.5.tar.gz
./configure --prefix=/usr/local/keepalived --sbindir=/usr/local/keepalived/sbin
make && make install
ln -s /usr/local/sbin/keepalived /usr/sbin/  
ln -s /usr/local/keepalived/etc/keepalived/ /etc/keepalived
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/init.d/  
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
chmod +x /etc/init.d/keepalived  
chkconfig keepalived on   #CentOS6执行
systemctl enable keepalived

配置keepalived
默认情况下keepalived启动时会去/etc/keepalived目录下找配置文件

#vi /etc/keepalived/keepalived.conf  
global_defs {  
     notification_email {  
         xxx@xxx.com
     }  
     notification_email_from xxx@xxx.com  
     smtp_server x.x.x.x
     smtp_connect_timeout 30  
     router_id MySQL-ha  
}  
 
vrrp_instance VI_1 {  
     state BACKUP   #两台配置此处均是BACKUP  
     interface eth0  
     virtual_router_id 51  
     priority 100   #优先级,另一台改为90  
     advert_int 1  
     nopreempt  #不抢占,只在优先级高的机器上设置即可,优先级低的机器不设置  
     authentication {  
         auth_type PASS  
         auth_pass 1111  
     }  
     virtual_ipaddress {  
         10.10.200.30  
     }  
}  
 
virtual_server 10.10.200.30 3306 {  
     delay_loop 2   #每个2秒检查一次real_server状态  
     lb_algo wrr   #LVS算法  
     lb_kind DR    #LVS模式  
     persistence_timeout 60   #会话保持时间  
     protocol TCP  
     real_server 10.10.200.11 3306 {  
         weight 3  
         notify_down /usr/local/mysql/bin/mysql.sh  #检测到服务down后执行的脚本  
         TCP_CHECK {  
             connect_timeout 10    #连接超时时间  
             nb_get_retry 3       #重连次数  
             delay_before_retry 3   #重连间隔时间  
             connect_port 3306   #健康检查端口
         }
     }  
} 

检测服务down后所要执行的脚本

#!/bin/sh    
killall keepalived    

赋予执行权限

chmod +x /usr/local/mysql/bin/mysql.sh  

此脚本是上面配置文件notify_down选项所用到的,keepalived使用notify_down选项来检查real_server 的服务状态,检测到real_server服务故障时,执行强制杀死keepalived进程,从而实现MySQL故障自动转移。
操作完成以后启动keepalived服务

systemctl start keepalived 
或
/usr/local/keepalived/sbin/keepalived –D 

mysqldb2:10.10.200.12 机器上也依此安装keeplaived服务
配置keepalived文件,优先级为90、无抢占设置、real_server为本机IP这三个地方不同:

vi /etc/keepalived/keepalived.conf
global_defs {  
     notification_email {  
         xxx@xxx.com  
     }  
     notification_email_from xxx@xxx.com  
     smtp_server x.x.x.x  
     smtp_connect_timeout 30  
     router_id MySQL-ha  
}  
 
vrrp_instance VI_1 {  
     state BACKUP  
     interface eth0  
     virtual_router_id 51  
     priority 90  
     advert_int 1  
     authentication {  
         auth_type PASS  
         auth_pass 1111  
     }  
     virtual_ipaddress {  
         10.10.200.30
     }  
}  
 
virtual_server 10.10.200.30 3306 {  
     delay_loop 2  
     lb_algo wrr  
     lb_kind DR  
     persistence_timeout 60  
     protocol TCP  
     real_server 10.10.200.12 3306 {  
         weight 3  
         notify_down /usr/local/mysql/bin/mysql.sh  
         TCP_CHECK {  
             connect_timeout 10  
             nb_get_retry 3  
             delay_before_retry 3  
             connect_port 3306  
         }
     }
}

复制mysql.sh脚本、启动keepalived服务
测试
停止MySQL服务,看keepalived健康检查程序是否会触发我们编写的脚本,然后登录VIP,看是否能登录,在登录之两台MySQL服务器都要授权允许从远程登录,在切换时执行了一个MySQL查询命令,从执行show databases到显示出结果时间为2-3秒,会有

ERROR 2006 (HY000): MySQL server has gone away

报错信息,是因为keepalived切换大概为1-3秒左右,这3秒左右VIP是空白期,代码里面最好能实现多次重连数据库,从而规避,keepalived只能做到对3306的健康检查,但是做不到比如像 MySQL复制中的slave-SQL、slave-IO进程的检查,总之Keeplavied+Mysql互为主从是一个低廉的负载均衡解决方案。

Nginx中虚拟目录alias和root目录说明

Nginx的配置中,alias目录和root目录是有区别的:
1、alias指定的目录是准确的,即location匹配访问的path目录下的文件直接是在alias目录下查找的;
2、root指定的目录是location匹配访问的path目录的上一级目录,这个path目录一定要是真实存在root指定目录下的;
3、使用alias标签的目录块中不能使用rewrite的break(具体原因不明);另外,alias指定的目录后面必须要加上"/"符号!!
4、alias虚拟目录配置中,location匹配的path目录如果后面不带"/",那么访问的url地址中这个path目录后面加不加"/"不影响访问,访问时它会自动加上"/";
如果location匹配的path目录后面加上"/",那么访问的url地址中这个path目录必须要加上"/",访问时它不会自动加上"/"。如果不加上"/",访问就会失败!
5、root目录配置中,location匹配的path目录后面带不带"/",都不会影响访问。

nginx指定文件路径有两种方式root和alias,指令的使用方法和作用域:
[root]
语法:root path
默认值:root html
配置段:http、server、location、if
[alias]
语法:alias path
配置段:location

root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。
root的处理结果是:root路径+location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的定义。

还有一个重要的区别是alias后面必须要用“/”结束,否则会找不到文件的,而root则可有可无。
所以,一般情况下,在nginx配置中的良好习惯是:
在location /中配置root目录;
在location /path中配置alias虚拟目录。
alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用。

CentOS上部署rsync同步文件

rsync特点:
快速:第一次同步时 rsync 会复制全部内容,但在下一次只传输修改过的文件。rsync在传输数据过程中可以实行压缩及解压缩操作,以使用更少的带宽。   
安全:可以使用rcp、ssh等方式来传输文件,也可以用直接的socket连接。
安装rsync:

yum install rsync -y

安装xinetd启停rsync

yum install xinetd -y

安装完后要修改以下配置文件:

vi /etc/xinetd.d/rsync
# default: off
# description: The rsync server is a good addition to an ftp server, as it \
#       allows crc checksumming etc.
service rsync
{
        disable = no
        flags           = IPv6
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/bin/rsync
        server_args     = --daemon --config=/etc/rsyncd.conf
        log_on_failure  += USERID
}

默认disable = yes,这里需要把yes改成no,保存退出。
配置rsync的主配置文件及密码文件:

cat /etc/rsyncd.conf 
pid file = /var/run/rsync.pid
port = 873
log file = /var/log/rsyncd.log
lock file = /var/run/rsync.lock 
 
[resources]
path = /data/rsync_file/
secrets file = /etc/rsyncd.pass
#设置运行链接的IP地址
hosts allow = 10.10.100.2
hosts deny = *
list = true
uid = 0
gid = 0
#rsync连接时的用户名,要和客户端rsync的命令一致
auth users = imguser
# 该目录是否只读
read only = no
transfer logging = yes
log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes.  
timeout = 600

创建密码文件

touch /etc/rsyncd.pass

权限修改、密码文件

chown root:root /etc/rsyncd.pass
chmod 600 /etc/rsyncd.pass
cat /etc/rsyncd.pass
imguser:ysxxx            #账号:密码(名字随便写,只要和上边配置文件里的一致即可),格式(一行一个用户)

在每个模块(如以上的[resources])后指定path路径时,路径后不能留空格;
将rsync添加为系统服务并在系统3和5级别下启动:

# chkconfig --add rsync
# chkconfig --level 35 rsync on
# /etc/init.d/xinetd restart
Stopping xinetd:                                           [  OK  ]
Starting xinetd:                                           [  OK  ]

查看是否启动:

netstat -tpln | grep 873
tcp        0      0 :::873                      :::*                        LISTEN      23737/xinetd  

到此,服务器端的配置已完成。

客户端安装

yum install rsync -y

创建一个密码文件:

cat /etc/rsyncd.pass
ysxxx

chmod 600 /etc/rsyncd.pass   #设置权限

同步/data/test下面所有文件到resources

rsync -avzrP /data/test/* --password-file=/etc/rsyncd.pass imguser@10.1.151.241::resources

rsync -avz 同步目录|文件 用户名@IP::模块名

-a 参数,相当于-rlptgoD,-r 是递归 -l 是链接文件,意思是拷贝链接文件;-p 表示保持文件原有权限;-t 保持文件原有时间;-g 保持文件原有用户组;-o 保持文件原有属主;-D 相当于块设备文件;
-z 传输时压缩;
-P 传输进度;
-v 传输时的进度等信息,和-P有点关系,自己试试。可以看文档;

另外:
定制欢迎信息文件rsyncd.motd
如:

[root@211 rsync]# cat rsyncd.motd
+++++++++++++++++++++++++++
+       wellcome rsyncd    +
+++++++++++++++++++++++++++

注意:rsync密码服务端格式为usrname:pwd 但客户端格式为pwd

BASH脚本:/bin/sh^M:bad interpreter: No such file or directory解决

在Linux中执行.sh脚本,异常/bin/sh^M: bad interpreter: No such file or directory。
分析:这是不同系统编码格式引起的:在windows系统中编辑的.sh文件可能有不可见字符,所以在Linux系统下执行会报以上异常信息。
解决:1)在windows下转换:
利用一些编辑器如UltraEdit或EditPlus等工具先将脚本编码转换,再放到Linux中执行。转换方式如下(UltraEdit):File-->Conversions-->DOS->UNIX即可。
2)也可在Linux中转换:
首先要确保文件有可执行权限

chmod a+x filename 

然后修改文件格式

vi filename 

利用如下命令查看文件格式

:set ff 或 :set fileformat 

可以看到如下信息
fileformat=dos 或 fileformat=unix
利用如下命令修改文件格式

:set ff=unix 或 :set fileformat=unix 
:wq (存盘退出)

最后再执行即可

FastDFS 一个tracker配置多个Storage Group

一个tracker配置多个Storage Group步骤如下:
1、修改相应storage的storage_group2.conf配置文件,以下三个参数需注意:

group_name=group2
port=23001
base_path=/data/fastdfs_group2
store_path0=/data/fastdfs_group2

2、修改storage的mod_fastdfs.conf

group_count = 2   #storage的个数
[group2]
group_name=group2
storage_server_port=23001
store_path_count=1
store_path0=/data/fastdfs_group2

注释掉mod_fastdfs.conf 中的下面两项,要么访问会报502错误。


---阅读剩余部分---

MySQL命令行参数整理

一、MySQL命令行参数:

Usage: mysql [OPTIONS] [database]   //命令方式  
 -?, --help          //显示帮助信息并退出  
 -I, --help          //显示帮助信息并退出  
 --auto-rehash       //自动补全功能,就像linux里面,按Tab键出提示差不多,下面有例子  
  
 -A, --no-auto-rehash  //默认状态是没有自动补全功能的。-A就是不要自动补全功能  
 -B, --batch         //ysql不使用历史文件,禁用交互  
 (Enables --silent)  
 --character-sets-dir=name   //字体集的安装目录                      
 --default-character-set=name    //设置数据库的默认字符集  
 -C, --compress      //在客户端和服务器端传递信息时使用压缩  
 -#, --debug[=#]     //bug调用功能  
 -D, --database=name //使用哪个数据库  
 --delimiter=name    //mysql默认命令结束符是分号,下面有例子  
 -e, --execute=name  //执行mysql的sql语句  常用于配合shell脚本
 -E, --vertical      //垂直打印查询输出  
 -f, --force         //如果有错误跳过去,继续执行下面的  
 -G, --named-commands  
 /*Enable named commands. Named commands mean this program's 
 internal commands; see mysql> help . When enabled, the 
 named commands can be used from any line of the query, 
 otherwise only from the first line, before an enter. 
 Disable with --disable-named-commands. This option is 
 disabled by default.*/  
 -g, --no-named-commands  
 /*Named commands are disabled. Use \* form only, or use 
 named commands only in the beginning of a line ending 
 with a semicolon (;) Since version 10.9 the client now 
 starts with this option ENABLED by default! Disable with 
 '-G'. Long format commands still work from the first 
 line. WARNING: option deprecated; use 
 --disable-named-commands instead.*/  
 -i, --ignore-spaces //忽视函数名后面的空格.  
 --local-infile      //启动/禁用 LOAD DATA LOCAL INFILE.  
 -b, --no-beep       //sql错误时,禁止嘟的一声  
 -h, --host=name     //设置连接的服务器名或者Ip  
 -H, --html          //以html的方式输出  
 -X, --xml           //以xml的方式输出  
 --line-numbers      //显示错误的行号  
 -L, --skip-line-numbers  //忽略错误的行号  
 -n, --unbuffered    //每执行一次sql后,刷新缓存  
 --column-names      //查寻时显示列信息,默认是加上的  
 -N, --skip-column-names  //不显示列信息  
 -O, --set-variable=name  //设置变量用法是--set-variable=var_name=var_value  
 --sigint-ignore     //忽视SIGINT符号(登录退出时Control-C的结果)  
 -o, --one-database  //忽视除了为命令行中命名的默认数据库的语句。可以帮跳过日志中的其它数据库的更新。  
 --pager[=name]      //使用分页器来显示查询输出,这个要在linux可以用more,less等。  
 --no-pager          //不使用分页器来显示查询输出。  
 -p, --password[=name] //输入密码  
 -P, --port=#        //设置端口  
 --prompt=name       //设置mysql提示符  
 --protocol=name     //使用什么协议  
 -q, --quick         //不缓存查询的结果,顺序打印每一行。如果输出被挂起,服务器会慢下来,mysql不使用历史文件。  
 -r, --raw           //写列的值而不转义转换。通常结合--batch选项使用。  
 --reconnect         //如果与服务器之间的连接断开,自动尝试重新连接。禁止重新连接,使用--disable-reconnect。  
 -s, --silent        //一行一行输出,中间有tab分隔  
 -S, --socket=name   //连接服务器的sockey文件  
 --ssl               //激活ssl连接,不激活--skip-ssl  
 --ssl-ca=name       //CA证书  
 --ssl-capath=name   //CA路径  
 --ssl-cert=name     //X509 证书  
 --ssl-cipher=name   //SSL cipher to use (implies --ssl).  
 --ssl-key=name      //X509 密钥名  
 --ssl-verify-server-cert //连接时审核服务器的证书  
 -t, --table         //以表格的形势输出  
 --tee=name          //将输出拷贝添加到给定的文件中,禁时用--disable-tee  
 --no-tee            //根--disable-tee功能一样  
 -u, --user=name     //用户名  
 -U, --safe-updates  //Only allow UPDATE and DELETE that uses keys.  
 -U, --i-am-a-dummy  //Synonym for option --safe-updates, -U.  
 -v, --verbose       //输出mysql执行的语句  
 -V, --version       //版本信息  
 -w, --wait          //服务器down后,等待到重起的时间  
 --connect_timeout=# //连接前要等待的时间  
 --max_allowed_packet=# //服务器接收/发送包的最大长度  
 --net_buffer_length=# //TCP / IP和套接字通信缓冲区大小。  
 --select_limit=#    //使用--safe-updates时SELECT语句的自动限制  
 --max_join_size=#   //使用--safe-updates时联接中的行的自动限制  
 --secure-auth       //拒绝用(pre-4.1.1)的方式连接到数据库  
 --server-arg=name   //Send embedded server this as a parameter.  
 --show-warnings     //显示警告  

提取jks证书配置Nginx使其支持https

证书配置在nginx上,对外提供https服务,内部和tomcat做反向代理走http,提取jks证书步骤如下:
提取jks证书(keytool命令安装jdk以后就默认安装了)
查看jks文件中的entry

keytool -list -keystore server.jks

查看是否有entries,如果有下个命令需要加 -srcalias 参数指定entry

转换jks文件为p12

keytool -importkeystore -srckeystore server.jks -destkeystore server.p12 -deststoretype PKCS12

查看新格式(pkcs12)证书库

keytool -deststoretype PKCS12 -keystore server.p12 -list

使用openssl提取证书并合并

openssl pkcs12 -in server.p12 -nokeys -clcerts -out server-ssl.crt
openssl pkcs12 -in server.p12 -nokeys -cacerts -out gs_intermediate_ca.crt

server-ssl.crt是SSL证书,gs_intermediate_ca.crt是中级证书,合并到一起才是nginx所需要的证书

cat server-ssl.crt gs_intermediate_ca.crt > server.crt

提取私钥及免密码

openssl pkcs12 -nocerts -nodes -in server.p12 -out server.key

避免重启是总是要输入私有key的密码

openssl rsa -in server.key -out server.key.unsecure

配置nginx


worker_processes  8;

error_log  logs/error.log  notice;

pid        logs/nginx.pid;


events {
    worker_connections  65535;
}


http {
    include       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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout 300;
    proxy_read_timeout 300;
    add_header Access-Control-Allow-Origin *;
    client_max_body_size    1000m;
    client_header_buffer_size 100m;
    large_client_header_buffers 4 102400k;
    set_real_ip_from  10.201.21.199;
    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;
    ssl_certificate   /etc/pki/cn/server.crt;
    ssl_certificate_key /etc/pki/cn/server.key;
    include gzip.conf;
    include apmweb_upstream.conf;


    server {
        listen       80;
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate   /etc/pki/cn/server.crt;
        ssl_certificate_key /etc/pki/cn/server.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers "EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
        ssl_prefer_server_ciphers on;
        ssl_session_timeout 1d;
        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security max-age=15768000;

        #proxy_redirect http:// $scheme://;
        proxy_redirect ~^http://inamp.xxx.com/(.*)$  https://inamp.xxx.com/$1;

        port_in_redirect on;
        proxy_set_header Host $host:$server_port;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;

        location / {
            root   /data/apm_static;
            index  index.html index.htm;
        }

       location ~*  ^/$ {
        rewrite ^/$ http://inamp.xxx.com/enrolment_web/enrolment/index.htm ;
       }

        include apmweb_tomcat.conf;

        error_page  404              /404.html;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }


    }

}

apmweb_tomcat.conf内容

           location ~* ^/management_service.*$ {
           include deny.conf;

           proxy_pass http://apmserapp6300;
           include proxy.conf;

           error_log  logs/apm_management_service_error.log error;
           access_log  logs/apm_management_service_access.log  main;
       

apmweb_upstream.conf内容

    upstream apmwebapp6300 {
      server 10.101.1.160:6300 weight=1 max_fails=2 fail_timeout=10s;
      server 10.101.1.161:6300 weight=1 max_fails=2 fail_timeout=10s;
      server 10.101.1.162:6300 weight=1 max_fails=2 fail_timeout=10s;
    }
.......

gzip.conf

gzip on;
gzip_comp_level 2;
gzip_http_version 1.1;
gzip_proxied any;
gzip_min_length 1;
gzip_buffers 16 8k;
gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/jsp application/html application/htm;

Tomcat查看占用CPU过高的原因

应用服务器服务起来以后占用CPU一直很高,排查方法如下:
1、使用top命令查看使用CPU过高的进程的pid,按“shift+P”键按照cpu从高到低排列,按“shift+M”键按照内存用高到低排列。
2、根据pid定位占用cpu的线程,并按照占用从高到低排列

#此处的pid为15217
$ ps -mp 15254 -o THREAD,tid,time|sort -rn|head -10 
USER     %CPU PRI SCNT WCHAN  USER SYSTEM   TID     TIME
tomcat   99.9   -    - -         -      -     - 05:10:34
tomcat   99.8  19    - -         -      - 15820 05:10:05
tomcat    0.0  19    - poll_s    -      - 15921 00:00:00
tomcat    0.0  19    - poll_s    -      - 15917 00:00:00
tomcat    0.0  19    - poll_s    -      - 15257 00:00:05
tomcat    0.0  19    - futex_    -      - 15922 00:00:00
tomcat    0.0  19    - futex_    -      - 15920 00:00:00
tomcat    0.0  19    - futex_    -      - 15919 00:00:00
tomcat    0.0  19    - futex_    -      - 15918 00:00:00

3、将占用cpu高的线程id转换为16进制格式

printf "%x\n" 15820
3dcc

4、打印线程的堆栈信息

jstack 15254 | grep 3dcc -A 30

"Thread-2" prio=10 tid=0x00007fe7745cc800 nid=0x3dcc runnable [0x00007fe744c4a000]
   java.lang.Thread.State: RUNNABLE
        at com.yueworldframework.core.support.EventHelper$1.run(EventHelper.java:50)
        at java.lang.Thread.run(Thread.java:745)

"GC Daemon" daemon prio=10 tid=0x00007fe774347800 nid=0x3d04 in Object.wait() [0x00007fe7459dd000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000fd7b8530> (a sun.misc.GC$LatencyLock)
        at sun.misc.GC$Daemon.run(GC.java:117)
        - locked <0x00000000fd7b8530> (a sun.misc.GC$LatencyLock)

"Service Thread" daemon prio=10 tid=0x00007fe7740aa000 nid=0x3bdd runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=10 tid=0x00007fe7740a7800 nid=0x3bdb waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=10 tid=0x00007fe7740a4800 nid=0x3bd9 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x00007fe77409a800 nid=0x3bd8 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=10 tid=0x00007fe774083800 nid=0x3bb9 in Object.wait() [0x00007fe746dec000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000fd7b0da0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
        - locked <0x00000000fd7b0da0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)

根据输出信息定位或将结果发给开发。

Nginx目录浏览功能autoindex设置

Nginx默认是不允许列出整个目录的。如需此功能,打开nginx.conf文件或你要启用目录浏览虚拟主机的配置文件,在server或location 段里添加上autoindex on;来启用目录流量,下面会分情况进行说明。

另外Nginx的目录流量有两个比较有用的参数,可以根据自己的需求添加:

autoindex_exact_size off;
默认为on,显示出文件的确切大小,单位是bytes。
改为off后,显示出文件的大概大小,单位是kB或者MB或者GB

autoindex_localtime on;
默认为off,显示的文件时间为GMT时间。
改为on后,显示的文件时间为文件的服务器时间

1、整个虚拟主机开启目录流量

在server段添加

location / {
autoindex on;
autoindex_localtime on; #之类的参数写这里
}

2、单独目录开启目录流量
2.1:直接二级目录开启目录流量

location /down {
autoindex on;
}

2.2:虚拟目录开启目录流量

location /tools {
alias /data/tools/;
autoindex on;
}

详细参照:http://nginx.org/en/docs/http/ngx_http_autoindex_module.html

dd创建测试文件

使用dd这个linux命令可以创建一定大小文件。

linux创建文件命令:dd命令
把指定的输入文件拷贝到指定的输出文件中,并且在拷贝的过程中可以进行格式转换。语法:
CODE:[Copy to clipboard]dd 〔选项〕
QUOTE:

if =输入文件(或设备名称)。
of =输出文件(或设备名称)。
ibs = bytes 一次读取bytes字节,即读入缓冲区的字节数。
skip = blocks 跳过读入缓冲区开头的ibs*blocks块。
obs = bytes 一次写入bytes字节,即写 入缓冲区的字节数。
bs = bytes 同时设置读/写缓冲区的字节数(等于设置obs和obs)。
cbs = bytes 一次转换bytes字节。
count = blocks 只拷贝输入的blocks块。
conv = ASCII 把EBCDIC码转换为ASCII码。
conv = ebcdic 把ASCII码转换为EBCDIC码。
conv = ibm 把ASCII码转换为alternate EBCDIC码。
conv = blick 把变动位转换成固定字符。
conv = ublock 把固定们转换成变动位
conv = ucase 把字母由小写变为大写。
conv = lcase 把字母由大写变为小写。
conv = notrunc 不截短输出文件。
conv = swab 交换每一对输入字节。
conv = noerror 出错时不停止处理。
conv = sync 把每个输入记录的大小都调到ibs的大小(用ibs填充)。
fdformat命令
低级格式化软盘。

创建一个2G的文件

dd if=/dev/zero  of=/tmp/test bs=1M count=2048

得到最恰当的block size
通过比较dd指令输出中所显示的命令执行时间,即可确定系统最佳的block size大小:

dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.filedd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file
dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file
dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file

测试硬盘读写速度
通过两个命令输出的执行时间,可以计算出测试硬盘的读/写速度:

dd if=/root/1Gb.file bs=64k | dd of=/dev/null
dd if=/dev/zero of=/root/1Gb.file bs=1024 count=1000000

MySQL的max_allowed_packet参数说明

max_allowed_packet 定义的是所允许的单条sql语句的大小。
引用官方的说法: http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_allowed_packet

You must increase this value if you are using large BLOB columns or long strings. It should be as big as the largest BLOB you want to use. The protocol limit for max_allowed_packet is 1GB. The value should be a multiple of 1024; nonmultiples are rounded down to the nearest multiple.

Property    Value
Command-Line Format    --max-allowed-packet=#
System Variable    max_allowed_packet
Scope    Global, Session
Dynamic    Yes
Type    integer
Default Value    4194304
Minimum Value    1024
Maximum Value    1073741824

解释:
该值的类型为integer,允许的最大值为1G (理论上4个字节的表达能力的上限是4G,也或许协议实现上硬编码了吧),修改
该变量的默认值为4MB,一般来讲是够的,如果存储大的BLOB列,可能不够,需要修改该配置
该值总是1KB的整数倍,最小值为1KB;修改的值应该是1024的整数倍,如果不是整数倍,则会按照小于该值的最接近的那个1024的整数倍进行截断处理,并产生1个warning;(注意: 如果设置的值小于1024,则自动调整为1024)如下:

将max_allowed_packet 设置为比 net_buffer_length 小的意义不大,所以,这里同样会出现一个warning,只是不会强制将max_allowed_packet修改为大于等于net_buffer_length的
比较专业的设置该值的方法为:
set global max_allowed_packet=102410241024;
session的max_allowed_packet是不允许修改的,修改了全局配置对当前session也不会生效的,只有重新连接才能看到变化,一般设置为1024M即可;

最新

分类

归档

评论

其它