zoukankan      html  css  js  c++  java
  • svn + nginx unit + python3自动化发布web服务方法

      本周将python web服务管理更换成nginx unit以后发现接口性能有了明显的提升,访问速度快了不少。不过有个很大的问题就是使用svn自动化发布以后,服务并没有刷新使用新的代码运行,而又不懂得如何将它弄成服务自动重启,只能用迂回救国的方式来想办法处理。

      试过用kill命令将unit进程杀死,然后启动服务方式,操作后发现会引发很多问题,最后放弃了。而unit有的特点就是配置文件更新以后会自动重启对应的服务,从而达到更新代码服务的效果,针对于这个特点所以想出了一个办法,那就是写个脚本,当代码发布成功以后,通过svn的勾子执行该脚本,从而改变unit配置从而达到想要重启服务的效果。

      要实现这个功能,脚本必须具体以下功能:

      1.读取原始配置文件内容(也可以直接放在脚本代码中)

      2.接收要重启服务的application名称

      3.使用字符串替换操作,将配置中的application名称替换成添加了随机数的新名称

      4.将新配置写入到文件中

      5.执行配置刷新命令,重启unit服务

      下面是完成的脚本代码update_unit_json.py

    #!/usr/bin/env python
    # coding=utf-8
    """
    更新unit配置,重启Python web服务
    """
    
    import logging
    import os
    import sys
    import random
    
    # 获取本脚本所在的路径
    pro_path = os.path.split(os.path.realpath(__file__))[0]
    sys.path.append(pro_path)
    
    # 定义日志输出格式
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        filename="/data/logs/service/update_unit_json.log",
                        filemode='a')
    
    # unit配置信息
    unit_json = """{
        "listeners": {
            "*:51000": {
                "application": "test_app_application"
            }
        },
        "applications": {
            "test_app_application": {
                "type": "python",
                "processes": {
                    "max":20,
                    "spare": 2
                },
                "path": "/data/www/test_app",
                "module": "main"
            }
        },
        "access_log": "/data/logs/www/access.log"
    }
    """
    
    def save_file(file_path, content, mode='a', encoding='utf-8'):
        """保存内容到文件里"""
        try:
            file_object = open(file_path, mode, encoding=encoding)
            file_object.write(content)
            file_object.close()
            return True
        except Exception as e:
            print(str(e.args))
            return False
    
    def get_random():
        """
        获取指定长度的随机字符
        """
        return str(random.randint(1000, 9999))
    
    
    if __name__ == "__main__":
        if len(sys.argv) == 1:
            print('缺少必要参数')
            sys.exit()
    
        # 获取服务名称
        application = sys.argv[1]
        print(application)
    
        try:
            # 设置配置文件存储地址
            file_path = '/data/unit/unit.json'
            # 替换json中的application串
            unit_json = unit_json.replace(application, application + get_random())
            print(unit_json)
            # 写入配置文件
            save_file(file_path, unit_json, 'w')
            # 设置unit配置重载命令(unit.json存储位置可以放到自己喜欢的任何地方;
            # control.unit.sock会根据在不同路径输入unitd启动命令,而直接在该路径下创建该文件,如果想要正常启动必须在build目录下运行unitd启动,另外不同服务器安装方式build位置可能不一样)
            command = 'curl -X PUT -d @/data/unit/unit.json --unix-socket /usr/local/unit/build/control.unit.sock http://localhost/config/'
            print(command)
            os.system(command)
            print('成功')
        except Exception as e:
            print('服务出现异常,异常信息:' + str(e.args))

      执行命令看看效果

    [root@izwz94jx1zymn4ogxqstsxz pre_release]# python3 update_unit_json.py test_app_application
    test_app
    {
        "listeners": {
            "*:51000": {
                "application": "test_app_application261542"
            }
        },
        "applications": {
            "test_app_application261542": {
                "type": "python",
                "processes": {
                    "max":20,
                    "spare": 2
                },
                "path": "/data/www/test_app",
                "module": "main"
            }
        },
            "access_log": "/data/logs/www/access.log"
    }
    
    curl -X PUT -d @/data/unit/unit.json --unix-socket /usr/local/unit/build/control.unit.sock http://localhost/config/
    {
            "success": "Reconfiguration done."
    }
    成功

      写完脚本以后,直接在svn勾子post-commit里添加对应的命令

    #!/bin/sh
    
    export LANG=en_US.UTF-8
    /usr/bin/svn up /data/www/test_app
    chown -R nobody:nobody /data/www/test_app
    python3 /data/service/test/update_unit_json.py test_app_application

      由于unit使用的是nobody用户运行的,所以在勾子中需要添加chown -R nobody:nobody /data/www/test_app命令,将新增或修改的文件的用户和组修改为nobody,不然可能运行会出错

     

      如果是多服务器需要同步发布和更新重启时,以上命令也达不到想要的自动化发布效果,所以可以使用ansible来进行管理,它可以帮我们跨服务器执行我们需要执行的命令,当然代码的跨服务器发布也可以使用rsync来管理

      安装epel源
      yum -y install epel-release

      安装ansible
      yum –y install ansible

      输入命令修改配置vim /etc/ansible/hosts,并添加下面内容:

    [all]
    
    [web1]
    127.0.0.1:22 ansible_ssh_user=root ansible_ssh_pass=****** ansible_sudo_pass=****** ansible_ssh_private_key_file=~/.ssh/id_rsa

      将******替换成你的服务器密码,如果有多台服务器时,这里可以直接添加web2、web3等

      修改/etc/ansible/ansible.cfg配置,将下面内容前面的#去掉,改为对应的内容

    inventory = /etc/ansible/hosts
    forks = 5
    poll_interval = 15
    sudo_user = root
    transport = smart
    remote_port = 22
    module_lang = C
    gathering = implicit
    gather_timeout = 10
    host_key_checking = False
    sudo_exe = sudo
    private_key_file = ~/.ssh/id_rsa
    deprecation_warnings = False

      主控端生成ssh密钥文件:
      ssh-keygen -t rsa -P ''
      添加信任到客户端:
      ssh-copy-id -i ~/.ssh/id_rsa.pub root@127.0.0.1
      显示要求输入密码时,输入目标客户端主机的登录密码
      对所有分组机器执行ping测试
      ansible all -m ping
      就可以看到各台主机返回执行命令成功的信息了。

      重启客户端所有主机的服务,需要将svn服务器的勾子命令修改为下面内容

    #!/bin/sh
    
    export LANG=en_US.UTF-8
    /usr/bin/svn up /data/www/test_app
    /usr/bin/ansible all -s -a "chown -R nobody:nobody /data/www/test_app"
    /usr/bin/ansible all -s -a "python3 /data/service/pre_release/update_unit_json.py test_app_application"

      添加其他需要执行的命令时,只需要按上面的格式,将命令放在/usr/bin/ansible all -s -a ""里就可以了

      当svn提交成功后,就会自动重启目标主机的对应服务了

    版权声明:本文原创发表于 博客园,作者为 AllEmpty 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

    python开发QQ群:669058475(本群已满)、733466321(可以加2群)    作者博客:http://www.cnblogs.com/EmptyFS/

  • 相关阅读:
    echarts中3D地球模型
    面试题68
    Java正确创建对象数组
    8.Arrays类和比较器
    7.Base64类和UUID类
    6.大数字处理类
    3.JVM重要知识点
    2.JVM基础知识点
    1.JVM入门知识
    6.适配器模式
  • 原文地址:https://www.cnblogs.com/EmptyFS/p/10159810.html
Copyright © 2011-2022 走看看