python程序的热部署实现[通俗易懂]

python程序的热部署实现[通俗易懂]pytho程序的热部署知乎上面的回答真正意义上的代码热部署应该是类似erlang那样的,将代码更新到节点后不停服务,不断连接的自动应用新代码。autoreload(代表django的autoreload)什么的还是会造成业务瞬间中断。我感觉是可以从wsgi容器级别上实现,比如更新代码后检测到文件变更,然后通知容器创建新的wsgiapplication的实例,之后所有新的请求都发送到新的wdgi…

大家好,又见面了,我是你们的朋友全栈君。

pytho程序的热部署

知乎上面的回答

真正意义上的代码热部署应该是类似erlang那样的,将代码更新到节点后不停服务,不断连接的自动应用新代码。auto reload(代表django的autoreload)什么的还是会造成业务瞬间中断。我感觉是可以从wsgi容器级别上实现,比如更新代码后检测到文件变更,然后通知容器创建新的wsgi application的实例,之后所有新的请求都发送到新的wdgi application实例上。等旧wsgi application实例的最后一个请求返回后就将其回收掉。不过貌似没有看到类似的实现

爬虫程序的热部署的原理

主要使用了:reload ,importlib 两个模块

爬虫程序,尤其是多爬虫系统,比如自动同步系统(实时爬虫),需要经常修改爬虫规则(代码),如果使用重启的方式,对于实时爬虫来说,运维工作量大,而且还会造成服务中断。所以可以使用python的reload方法来实现热部署。


但是,由于对reloa的机制不是很了解,暂时还不清楚reload对程序的负面影响,尤其对于高并发程序的影响。

实现

实现很简单,程序使用多线程,热部署线程负责监听mq消息,收到消息,reload对应的模块。

代码

新建hotupdate包 修改__init__.py文件

# coding=utf-8
"""实现热更新功能"""
import importlib
import json
import sys
import threading
import logging

from hotupdate.hot_update import HotUpdateEventDriven, HotUpdateMessage

driven = HotUpdateEventDriven()


def _callback(ch, method, properties, body):
    """收到消息执行的回调函数"""
    try:
        msg = json.loads(body.decode('utf-8'))
        message = HotUpdateMessage(model_path=msg['model_path'], is_append_path=msg['is_append_path'], physical_path=msg['physical_path'])
        # 物理路径加入pythonPath
        if message.is_append_path:
            sys.path.append(message.physical_path)

        # 动态的引入该模块
        import_module = importlib.import_module(message.model_path)
        reload(import_module)
        # 打印热更新信息
        logging.warning('%s模块已经更新' % (message.model_path))
    except Exception, e:
        logging.warning('热部署失败,收到的消息%s,异常信息%s' % (body, e.message))
    # 消息确认
    driven.input_channel.basic_ack(delivery_tag=method.delivery_tag)


def _run():
    """线程的执行方法"""
    driven.receive(_callback)


def auto_reload_module():
    """reload a module. 新开一个线程来进行reload操作 动态更新python模块代码,依赖事件驱动,就是需要有人或者程序发送消息通知程序 """
    t = threading.Thread(target=_run, name='autoReloadThread')
    t.start()


新增hot_update.py文件

# encoding=utf-8
# ---------------------------------------
# 语言:Python2.7
# 功能:事件驱动,触发热部署动作
# ---------------------------------------
import uuid

import pika

from queues import queueBase
from settings import MQ


class HotUpdateEventDriven(object):
    """监听mq消息,收到消息,自动reload"""

    def __init__(self):
        credentials = pika.PlainCredentials(MQ['userName'], MQ['password'])
        parameters = pika.ConnectionParameters(MQ['host'], MQ['port'], '/', credentials=credentials)
        self.connection = pika.BlockingConnection(parameters)
        self.__init_input__()

    def __init_input__(self):
        ''' 初始化入口通道 '''
        self.input_channel = self.connection.channel()
        input_exchange = 'python.ppmoney.hotupdate'
        input_exchange_type = 'fanout'
        input_routing_key = '#'
        # 消息入口的队列
        self.input_queue = 'python.hotupdate.%s' % (uuid.uuid1())
        # 声明路由,如果存在就什么也不会做
        self.input_channel.exchange_declare(exchange=input_exchange, exchange_type=input_exchange_type, durable=True)
        # 声明队列
        self.input_channel.queue_declare(queue=self.input_queue, auto_delete=True)
        # 通过routing_key 将交换机与queue绑定起来
        self.input_channel.queue_bind(exchange=input_exchange, queue=self.input_queue, routing_key=input_routing_key)

    def receive(self, callback):
        ''' 入口通道:接受自动同步服务发送的任务消息 '''
        # 入口通道订阅消费者
        self.input_channel.basic_consume(consumer_callback=callback, queue=self.input_queue, consumer_tag='hotupdate_client')
        self.input_channel.start_consuming()


class HotUpdateMessage(object):
    """收到的mq消息"""

    def __init__(self, model_path, is_append_path, physical_path):
        # 模块名称
        self.model_path = model_path
        # 是否需要添加到pythonPath
        self.is_append_path = is_append_path
        # 如果需要添加到PythonPath中,需要提供模块的物理路径
        self.physical_path = physical_path

使用起来很简单,只需要增加一行代码即可

# 开启热更新
hotupdate.auto_reload_module()
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143670.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • discuz!

    discuz!

    2021年10月8日
    69
  • c++中fstream是什么意思_c++形式参数

    c++中fstream是什么意思_c++形式参数初学C++fstream最近出于学习需要,接触了一些C++的程序,对于文件的操作,在C++中的实现方法与C中有些不同,现归纳如下:C++中对文件的操作,是围绕三种类型的文件流(ifstream,ofstream,ftream)进行的.而这三种流事实上是系统定义的类.操作中,首先使流与文件相关联,通过流(也就是类成员)来完成对文件的操作.文件使用完毕,一定要关闭,从而切断流…

    2026年1月24日
    3
  • 约瑟夫环问题递归解法的一点理解

    约瑟夫环问题递归解法的一点理解约瑟夫环递归解法代码的一点理解。约瑟夫生者死者游戏约瑟夫游戏的大意:30个游客同乘一条船,因为严重超载,加上风浪大作,危险万分。因此船长告诉乘客,只有将全船一半的旅客投入海中,其余人才能幸免于难。无奈,大家只得同意这种办法,并议定30个人围成一圈,由第一个人数起,依次报数,数到第9人,便把他投入

    2022年6月4日
    29
  • SM4加密运算_数据加密标准des采用的密码类型是

    SM4加密运算_数据加密标准des采用的密码类型是javaSM4加密运算自己的理解:sm4加密,其实就是将字符串转成byte数组,再设置一个与解密相同的字符串,将byte的数据再转成二级制的数据,进行异或的运算,得到一组没有规则的字符串!案例上面是一些算法下面是应用方法这是自己的认知,有什么不同建议可以留言,XXXX是自己加密的字符串…

    2022年10月6日
    4
  • Windows下的labelme数据标注工具安装教程[通俗易懂]

    Windows下的labelme数据标注工具安装教程[通俗易懂]前言因为最近要做一个目标检测的比赛,需要用到labelme这款开源标注工具,所以安装了下具体的的安装步骤可参考:https://github.com/wkentaro/labelme因为我是在Windows下使用的,所以这里只介绍了Windows的安装方法,Ubuntu、macOS等其他系统在上面的github都有详细介绍,大家自行查看哈 一、安装AnacondaWindo…

    2025年10月27日
    3
  • PHP二维数组(或任意维数组)转换成一维数组的方法汇总(实用)

    PHP二维数组(或任意维数组)转换成一维数组的方法汇总(实用)

    2021年11月8日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号