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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM