Rootop 服务器运维与web架构

2019-03-12
发表者 Venus
linux下查找java占用cpu高的原因已关闭评论

linux下查找java占用cpu高的原因

目的:排查java程序占用cpu高的步骤。

1、首先使用top查到占用cpu最高的java进程 pid

可以看到占cpu最高的是pid为16156的进程,也是java的进程。通过ps查就是我启动的jar包。

2、查此进程的线程

通过ps的 -m (显示线程) -p(pid进程使用的cpu时间)两个参数,配合自定义格式 -o 打印出来线程TID。

由上图可以看到线程16157占用cpu达27%,接下来查找此线程在做什么动作导致这么高。

3、使用jdk自带的 jstack 工具根据进程pid查找并通过线程id(TID)的十六进制过滤堆栈跟踪信息

线程tid转十六进制:

[root@localhost ~]# printf "%x" 16157
3f1d[root@localhost ~]# 

16157的十六进制为3f1d

-A -B参数是打印过滤线程十六进制值的上下20行数据。

可以看到是DemoApplication.java中的19行代码导致的cpu占用高。

java代码:

这个地方循环打印数据导致的。记录此过程,便于以后排查问题。

2019-02-25
发表者 Venus
解决spring cloud 中config配置中心经常需要重启的问题已关闭评论

解决spring cloud 中config配置中心经常需要重启的问题

问题现象:spring cloud项目,一定时间后更新某个微服务,启动时去config配置中心查找配置时报错。重启config可以解决,但是没找到具体原因。
后来发现/tmp目录下有tomcat.和config-repo开头的文件,推测是config生成的配置信息存在这里。tmp目录会被系统自动清理导致。
然后特意查了下资料解决。

关于tmp目录清理的资料来自:https://blog.51cto.com/kusorz/2051877
CentOS6以下系统(含)使用watchtmp + cron来实现定时清理临时文件的效果,这点在CentOS7发生了变化,在CentOS7下,系统使用systemd管理易变与临时文件,与之相关的系统服务有3个:

systemd-tmpfiles-setup.service  :Create Volatile Files and Directories
systemd-tmpfiles-setup-dev.service:Create static device nodes in /dev
systemd-tmpfiles-clean.service :Cleanup of Temporary Directories

# 相关的配置文件也有3个地方:

/etc/tmpfiles.d/*.conf
/run/tmpfiles.d/*.conf
/usr/lib/tmpfiles.d/*.conf

# 清理/tmp目录规则配置文件路径:

[root@node7 ~]# cat /usr/lib/tmpfiles.d/tmp.conf
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# See tmpfiles.d(5) for details

# Clear tmp directories separately, to make them easier to override
v /tmp 1777 root root 10d
v /var/tmp 1777 root root 30d

# Exclude namespace mountpoints created with PrivateTmp=yes
x /tmp/systemd-private-%b-*
X /tmp/systemd-private-%b-*/tmp
x /var/tmp/systemd-private-%b-*
X /var/tmp/systemd-private-%b-*/tmp

# 查看详细帮助文档执行下面命令

[root@node7 ~]# man tmpfiles.d
v
   Create a subvolume if the path does not exist yet and the file system supports this (btrfs). Otherwise create a
   normal directory, in the same way as d.
x
   Ignore a path during cleaning. Use this type to exclude paths from clean-up as controlled with the Age parameter.
   Note that lines of this type do not influence the effect of r or R lines. Lines of this type accept shell-style
   globs in place of normal path names.       
X
   Ignore a path during cleaning. Use this type to exclude paths from clean-up as controlled with the Age parameter.
   Unlike x, this parameter will not exclude the content if path is a directory, but only directory itself. Note that
   lines of this type do not influence the effect of r or R lines. Lines of this type accept shell-style globs in place
   of normal path names.   

通过帮助文档可以看到v参数用来创建一个不存在的目录,x参数用来忽略清理的文件or目录,X参数用来忽略目录,但目录下的文件还会被清理。
通过上面规则可见/tmp是10天清理一次,spring cloud的config服务运行后会在/tmp下生成tomcat.和config-repo开头的目录(我不确定命名是否为固定的还是开发人员可以自己修改),超过10天后就会被清理。
当其他服务模块启动时会去config服务查配置信息,但是目录被清理就会报错,此时重启config,再启动服务即可。

最终解决方法有2个,第一忽略清理/tmp/下指定开头的文件,第二修改jar包运行时的临时目录。
1、编辑/usr/lib/tmpfiles.d/tmp.conf 追加:

x /tmp/tomcat.*
x /tmp/config-repo*

2、采用修改jar包运行时-Djava.io.tmpdir参数实现(我所采用的方法):

java -jar -Djava.io.tmpdir=./tmp # 在当前jar包目录下手动创建一个tmp目录,用于保存config配置信息。

问题才解决。

2019-02-20
发表者 Venus
通过mutate插件对原日志进行分割已关闭评论

通过mutate插件对原日志进行分割

需求:通过filter中mutate插件实现将原java日志分割,取出日志等级字段。
当判断为ERROR级别后提交到指定url进行下一步处理。

input {
    file {
        type => "api"
        path => "/home/jar/api/logs/*-error.log"
        codec => multiline {
            pattern => "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}"
            negate => true
            what => previous
        }
    }
}

filter {
        mutate {
                copy => {
                        "message" => "source_message"
                }
        }
}

filter {
        mutate {
                split => ["message", " "]
                add_field => {
                        "level" => "%{[message][2]}"
                }
        }
}

output {
 
    if [level] == "ERROR" {
        http {
            http_method => "post"
            url => "http://xxx/logstash.php"
        }
    }
 
    stdout {
        codec => rubydebug
    }
 
}

关键配置注解:

如一条日志为:2019-02-20 15:55:47.273 ERROR [http-nio-8081-exec-32] io.renren.service.impl.CertificateServiceImpl.notify:840 – 支付宝回调返回不成功

# 保留原日志 (后来发现这种方式是错误的,原日志中的空格会被逗号代替,影响了原格式)
add_field => {
“source_message” => “%{message}”
}
需要换成下面配置
filter {
mutate {
copy => {
“message” => “source_message”
}
}
}
这样才能保留原先格式。

# 添加字段level,值为原日志第3个字段(分割后的第2个字段)
add_field => {
“level” => “%{[message][2]}”
}

2019-02-14
发表者 Venus
python实现批量添加windows用户已关闭评论

python实现批量添加windows用户

需要在windows下做共享,要添加全部门的人用于访问共享文件夹的权限认证。
如果一个个添加账号太麻烦,所以采用python调用cmd命令实现。
代码如下:

#!/usr/bin/python
# coding=utf-8
import os
import random

# 用户名、姓名、部门列表
user_dict = [
{"name":"user1", "realname":"用户1", "group":"业务支撑部"},
{"name":"user2", "realname":"用户2", "group":"业务支撑部"},
]

# 临时保存用户名及密码
user_list = []

for i in user_dict:
	username = i["name"]
	realname = i["realname"]
	group = i["group"]
    # 生成4位随机数
	randstr = random.randint(1000,9999)
    # 密码用用户名加随机4位数
	password = username + str(randstr)
	
	user_list.append(username + ' : ' + password)
	
	# 创建用户并设置密码及禁止修改密码
	command = "net user %s %s /passwordchg:no /expires:never /FULLNAME:%s /add" %(username, password, realname)
	os.system(command)

	# 设置密码永不过期
	command = "wmic useraccount where \"name='%s'\" set passwordexpires=false"%(username)
	os.system(command)
	
	# 设置属组
	command = "net localgroup %s %s /add" %(group, username)
	os.system(command)

	# 删除默认Users组
	command = "net localgroup Users %s /del" %(username)
	os.system(command)
	
# 打印用户名密码
for i in user_list:
	print i

2019-01-18
发表者 Venus
mysql数据同步到elasticsearch,用于实现产品搜索功能。已关闭评论

mysql数据同步到elasticsearch,用于实现产品搜索功能。

logstash、elasticsearch、kibana安装略,这里用的版本为6.5.1

# 安装jdbc插件 logstash5.X已经集成此插件

[root@localhost ~]# cd /usr/share/logstash/bin

# 查看是否安装jdbc插件

[root@localhost bin]# ./logstash-plugin list | grep jdbc

# 安装jdbc插件

[root@localhost bin]# ./logstash-plugin install logstash-input-jdbc

# 配置logstash,mysql数据同步到elasticsearch

1、创建logstash配置文件 mysql-sync-es.conf :

input {
  stdin {
  }
  
  jdbc {
      jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/test"
      jdbc_user => "root"
      jdbc_password => "root"
      # 这里需要设置正确的mysql-connector-java jar包路径,从 https://search.maven.org/search?q=mysql-connector 可以下载
      jdbc_driver_library => "/etc/logstash/mysql-connector-java-8.0.13.jar"
      jdbc_default_timezone =>"Asia/Shanghai"
      # the name of the driver class for mysql
      jdbc_driver_class => "com.mysql.jdbc.Driver"
      jdbc_paging_enabled => "true"
      # 最多取50000条更新的数据
      jdbc_page_size => "50000"
      # 以下对应着要执行的sql的绝对路径
      statement_filepath => "/etc/logstash/sql.sql"
      # 记录上一次运行的时间,用于sql中where条件过滤出新数据。
      last_run_metadata_path => "/root/dockermount/last_value"
      # 定时字段 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
      schedule => "* * * * *"
      # 设定ES索引类型
      type => "doc"
  }
}

output {
  elasticsearch {
      # ES IP地址与端口
      hosts => "192.168.10.17:9200"
      # ES索引名称(自己定义的)
      index => "user"
      # 唯一列名,保证更新后的mysql数据同步到es时,es中不会出现重复数据,类似mysql中更新数据的where条件。
      document_id => "%{id}"
  }
  stdout {
      # 以JSON格式输出到控制台
      codec => json_lines
  }
}

2、sql脚本,注意sql不能以分号结束:

SELECT * FROM `user` where `time` >= :sql_last_value

其中:sql_last_value的值就对应last_run_metadata_path => “/root/dockermount/last_value”这个参数的值。

3、最后启动logstash测试:

/usr/share/logstash/bin/logstash -f mysql-sync-es.conf

去kibana中添加user索引就可以查看同步过来的数据了。
测试结果:
logstash每分钟会执行一次sql脚本中的语句,其次logstash会计算下更新的数据条数是否超过配置文件中定义的值。
数据同步及数据更新功能测试通过。

参考过的资料:
http://hi.ktsee.com/697.html
https://blog.csdn.net/laoyang360/article/details/51747266
https://blog.csdn.net/laoyang360/article/details/51793301
https://blog.csdn.net/opera95/article/details/78553743
https://wenchao.ren/archives/393 # 数据重复问题 主键解决