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()
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • LeetCode——Pascal's Triangle

    LeetCode——Pascal's Triangle

  • JavaScript详细解析

    JavaScript详细解析文章目录1、JavaScript详细解析1.1、JavaScript介绍1.2、快速入门引入js的方式一:内部方式引入js的方式一:外部方式1.3、开发环境搭建1.4、快速入门总结2、JavaScript基本语法2.1、注释2.2、输入输出语句2.3、变量和常量2.4、原始数据类型和typeof方法2.4.1、原始数据类型2.4.2、typeof2.5、运算符2.6、流程控制和循环语句2.7、数组2.8、函数2.9、小结3、JavaScriptDOM3.1、DOM介绍3.2、Element元素的获取操作3

  • 分享下Java大数据学习路线图

    分享下Java大数据学习路线图Java大数据学习路线图‘’准备篇适用/适合人群:适合基础小白目标:掌握JavaSE。●技术点小节:1.开发工具的安装配置的介绍    2.JDK安装    3.DOS环境编程    4.Eclipse的安装使用●JAVA基础1.基本的语法规范    2.数据类型    3.流程控制    4.函数●初识JavaOOP1.类,对象,面向编程思想    2…

  • jmeter动态获取token_java比net core性能好

    jmeter动态获取token_java比net core性能好.netcore3.1使用JWT遇到在api控制器中获取不到当前用户信息以及token无效的问题1,在api控制器获取不到当前用户,我的原因是因为该控制器没有做授权验证,加上验证的特性就可以了2,token无效,先检查前端传过来的token是否是我们要验证的token格式,jwt会在token前面添加一个前缀,前端传过来也应该要添加,或者做其他处理这两个问题耽搁了一下午的时间,特地记录一…

  • SQL Server2012新特性概述

    SQL Server2012新特性概述

    2021年11月24日
  • Excel字符串截取(left&right&mid)

    Excel字符串截取(left&right&mid)Excel中字符串截取函数主要有left、right和mid1.left函数  在字符串“wang”中,从左起截取2个字符,结果是“wa”。2.right函数  在字符串“wang”中,从右起截取2个字符,结果是“ng”。3.mid函数  从字符串“wang”第2个位置,截取长度为2的字符串,结果是“an”。

    2022年10月23日

发表回复

您的电子邮箱地址不会被公开。

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