美文网首页
python重启java项目

python重启java项目

作者: 后山小鲨鱼 | 来源:发表于2020-03-31 22:09 被阅读0次

github地址:https://github.com/a1546240512/pythonReloadJavaProject.git
场景:公司有一个java项目不太稳定,经常会挂,是一个已上线的项目,暂时还没找到挂掉的原因。现在想我写一个脚本,当java项目挂掉的时候可以自动重启它,并短信通知。另外,有可能是要部署项目,这时不用重启,报警。重启的项目可能是多个。短信的模板可以配置。
所以,我要实现的功能有:

1.自动重启
2.发送短信
3个配置文件

3.1配置是否在部署项目,不用通知。
3.2多个重启项目的配置信息。
3.3短信模板的配置。

怎么判断java项目是不是挂了?可以用python的requests模块去访问它的接口,看是否超时,规定超过多少次超时就认为它挂掉了。所以python程序的流程图是这样的

用到的环境

1.系统:Linux version 3.10.0-862.14.4.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-28)
2.python3.6(3.7要升级一些东西,建议用3.6版本的),centos安装python3.6的方法。
https://www.jianshu.com/p/e88e0e2d5a69
3.安装完python后,需要安装一些包。
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install aliyun-python-sdk-core-v3 (发短信会用到)
注意pip安装是啥版本的,要3的

项目的结构如下

开始写代码
配置文件projectMessage:
中间用$分割,可配置多个项目
java项目访问地址端口$重启java项目的命令$项目名称(发短信要用到的)

{
    "requestUrlsAndJarPath": ["http://127.0.0.1:8123$/usr/bin/sh /opt/jar/read/startService.sh$项目名称1","http://127.0.0.1:8666$/usr/bin/sh /opt/jar/adSystem/startService.sh$项目名称1"]
}

配置文件shortMessage,这里用的是阿里云短信平台:

{
    "SignName":"网络公司",
    "PhoneNumbers":["164651895255$小新"],
    "TemplateCode":"SMS_561955852",
    "ACCESSKEYID":"LTAIpLOA7dOIniun",
    "ACCESSSECRET":"stO4jIiUyPgNwWXEDUdxHr6j98ebKC",
    "TemplateParam":{"returnDomain": ""}
}

配置文件runConfig:
1启用重启和发短信,其他不启用。

{
    "run": ["http://127.0.0.1:8123$1","http://127.0.0.1:8666$1"]
}

要引入的模块

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
import requests
import time
import os
import logging
import datetime
import json
import threading

初始化并创建日志文件


# filename:设置日志输出文件,以天为单位输出到不同的日志文件,以免单个日志文件日志信息过多,
# 日志文件如果不存在则会自动创建,但前面的路径如log文件夹必须存在,否则会报错
log_file = '/opt/python_file/py_web_%s.log' % datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d')
# log_file = '/opt/python_file/py_web.log'
# level:设置日志输出的最低级别,即低于此级别的日志都不会输出
# 在平时开发测试的时候可以设置成logging.debug以便定位问题,但正式上线后建议设置为logging.WARNING,既可以降低系统I/O的负荷,也可以避免输出过多的无用日志信息
log_level = logging.INFO
# format:设置日志的字符串输出格式
log_format = '%(asctime)s[%(levelname)s]: %(message)s'
logging.basicConfig(filename=log_file, level=logging.INFO, format=log_format)
logger = logging.getLogger()

要用到的一些工具函数

# 将配置文件读取并转换成json格式数据返回
def changeReadFileToJson(path):
    with open(path,encoding="UTF-8") as file_object:
        contends = file_object.read()
    return json.loads(contends)

# --------发送短信--------
def send_sms(shortMessageConfig,projectName):
    logging.info("进入发送短信")
    PhoneNumbers = shortMessageConfig.get("PhoneNumbers")
    SignName = shortMessageConfig.get("SignName")
    TemplateParams = shortMessageConfig.get("TemplateParam")
    logging.info("TemplateParams1"+str(TemplateParams))
    for templateParam in TemplateParams:
        TemplateParams[templateParam] = TemplateParams[templateParam] = projectName
    logging.info("TemplateParams2"+str(TemplateParams))
    TemplateCode = shortMessageConfig.get("TemplateCode")
    ACCESSKEYID = shortMessageConfig.get("ACCESSKEYID")
    ACCESSSECRET = shortMessageConfig.get("ACCESSSECRET")
    for PhoneNumber in PhoneNumbers:
        # client = AcsClient('<accessKeyId>', '<accessSecret>', 'default')
        client = AcsClient(ACCESSKEYID, ACCESSSECRET, 'default')
        request = CommonRequest()
        request.set_accept_format('json')
        request.set_domain('dysmsapi.aliyuncs.com')
        request.set_method('POST')
        request.set_protocol_type('https')  # https | http
        request.set_version('2017-05-25')
        # 以上部分是公用的不变
        request.set_action_name('SendSms')
        # set_action_name 这个是选择你调用的接口的名称,如:SendSms,SendBatchSms等
        request.add_query_param('RegionId', "default")
        # 这个参数也是固定的
        try:
            request.add_query_param('PhoneNumbers', str(PhoneNumber).split("$")[0])  # 发给谁
        except Exception as e:
            pass
        request.add_query_param('SignName', SignName)  # 签名
        request.add_query_param('TemplateCode', TemplateCode)  # 模板编号
        request.add_query_param('TemplateParam', f"{TemplateParams}")  # 发送验证码内容
        response = client.do_action_with_exception(request)
        logging.info(str(response, encoding='utf-8'))
        return str(response, encoding='utf-8')

全局变量

#读取配置文件
#短信配置信息
shortMessageConfig = changeReadFileToJson("./config/shortMessage")
#项目配置信息
projectMessageConfig = changeReadFileToJson("./config/projectMessage")

主要逻辑

def doListen(projectMessage,shortMessageConfig):
    requestUrl = projectMessage.split("$")[0]
    jarUrl = projectMessage.split("$")[1]
    projectName = projectMessage.split("$")[2]
    logging.info("projectName:"+projectName)

    # 起始时间戳
    time1 = time.time()
    #是否已经发送短信的标志
    send = 0
    while True:
        i = 0
        while i<=3:
            try:
                time.sleep(5)
                r = requests.get(requestUrl, timeout=(3, 5))
                if r.status_code == 200:
                    time2 = time.time()
                    #每20分钟打印成功的日志
                    if time2 - time1 >= 1200 or send == 1:
                        logging.info(requestUrl +"  服务器正常")
                        logging.info(requestUrl +"  访问结果"+str(r.status_code))
                        time1 = time2
                    i = 4
                    send = 0
                    continue
                else:
                    if send == 0:
                        logging.info(requestUrl +"  访问结果:"+str(r.status_code)+"-当前次数" + str(i) + "次")
                    else:
                        time2 = time.time();
                        if time2 - time1 >= 1200:
                            logging.info(requestUrl +"  服务器未启动")
                            logging.info(requestUrl +"  访问结果:" + str(r.status_code))
                            time1 = time2
                    i = i + 1
                if i >= 4 and send == 0:
                    runConfig = changeReadFileToJson("./config/runConfig")
                    runs = runConfig.get("run")
                    nowRun = 1
                    for run in runs:
                        adress = run.split("$")[0]
                        if adress == requestUrl:
                            nowRun = run.split("$")[1]
                    if nowRun == 1:
                        logger.info(requestUrl + "  检测到服务挂了,重启服务!!!")
                        os.system(jarUrl)
                        logger.info(requestUrl + "  短信通知!!!")
                        send_sms(shortMessageConfig,projectName)
                    else:
                        logger.info(requestUrl + "  正在部署,不用重启")
                        time.sleep(5)
                        i = 0
                        break

                    send = 1
                    i = 0
                    break
            except Exception as e:
                i = i + 1
                if send == 0:
                    logging.info(requestUrl +"  访问结果:超时" + str(i)+"次")
                else:
                    time2 = time.time();
                    if time2 - time1 >= 1200:
                        logging.info(requestUrl +"  服务器未启动,访问超时!!!")
                        time1 = time2
                if i >= 4 and send == 0:
                    runConfig = changeReadFileToJson("./config/runConfig")
                    runs = runConfig.get("run")
                    nowRun = 1
                    for run in runs:
                        adress = run.split("$")[0]
                        if adress == requestUrl:
                            nowRun = run.split("$")[1]
                    if nowRun == "1":
                        logger.info(requestUrl + "  检测到服务挂了,重启服务!!!")
                        os.system(jarUrl)
                        logger.info(requestUrl + "  短信通知!!!")
                        send_sms(shortMessageConfig,projectName)
                    else:
                        logger.info(requestUrl + "  正在部署,不用重启")
                        time.sleep(5)
                        i = 0
                        break
                    i = 0
                    send = 1
                    break

因为可能要监听多个java项目,所以要用到多线程。

# 线程处理
class myThread(threading.Thread):
    def __init__(self,projectMessage,shortMessageConfig):
        threading.Thread.__init__(self)
        self.projectMessage = projectMessage
        self.shortMessageConfig = shortMessageConfig


    def run(self):
        try:
            doListen(self.projectMessage,self.shortMessageConfig)
        except Exception as e:
            print(e)

主函数

#入口
if __name__ == '__main__':
    logging.info("------------------------------")
    projectMessages = projectMessageConfig.get("requestUrlsAndJarPath")
    for projectMessage in projectMessages:
        logging.info(projectMessage.split("$")[0]+"  开启脚本")
        myThread(projectMessage,shortMessageConfig).start()
        time.sleep(2)

接下来就部署到java项目运行的机器上。
我是用MobaXterm连接的
在/opt下新建目录python_file
把写好的代码和配置文件夹放到python_file目录下

cd /opt/python_file
后台进程运行python程序
nohup python3 send.py >/dev/null 2>&1 &
查看python进程
ps -ef | grep python

要终止进程

kill -9 3543

查看java进程

ps -ef | grep java

查看日志

tail -f 200 py_web_2020-03-31.log


要测试的话,可以kill掉一个java项目试试(不要在正式服kill,手动滑稽)

kill -9 3587

打开日志

在看看java项目有没有重启

ps -ef | grep java


正常重启了

相关文章

  • python重启java项目

    github地址:https://github.com/a1546240512/pythonReloadJavaP...

  • Android Studio 2.3 配置Kotlin

    1. 安装Kotlin插件, 安装完成之后重启AS 2. 将Java项目转换成Kotlin项目 操作 : Code...

  • 如何退出Gunicorn

    在使用Gunicorn部署python项目时,有时需要重启或者关闭项目,这时候就会发现gunicorn的进程怎么也...

  • idea 热加载

    方案1 方法内的修改java代码,不需要重启,只需要重新编译即可非常适合SpringBoot项目热加载 java的...

  • JRebel for IDEA 下载/安装/注册

    JRebel 用于项目的热部署,每次修改java类文件后无需重启项目,方便实用 1.下载 1.IDEA中进入设置 ...

  • python学习笔记四(python组织结构)

    python项目组织结构 包、模块、类,是python项目组织结构,文件夹是包组织形式(如jar为java的组织形...

  • 使用nodemon让node自动重启

    在我们开发php,java等web项目的时候,修改了项目代码,服务器都会自动重启,让我们的改动生效,但是node并...

  • 收藏,Github最有名的200个Python中文项目

    Github中有非常多的Python项目,如果你去搜Python关键字,会发现相关项目已经超过两百万个,比Java...

  • py4j

    python -> java java -> python

  • 5个提升性能的项目

    Python的运行速度确实没有C或者Java快,但是有一些项目正在努力让Python变得更快。 Python代码简...

网友评论

      本文标题:python重启java项目

      本文链接:https://www.haomeiwen.com/subject/urvmuhtx.html