py 多进程 引发的 各种数据库连接 消息队列连接 异常问题 简单分析

简介: py 多进程 引发的 各种数据库连接 消息队列连接 异常问题 简单分析

fork 引起的一些问题

multiprocess 建立在 fork 基础上, 所以fork 会引发很多问题,比如 多个进程使用相同的 fd。

如果只是 fd 的话可能冲突概率还不大。 但是 数据库 连接 , 尤其 消息队列的 心跳 连接,肯定会出现问题,


两种解决方法

先 释放 conn ,再 创建


  1. 在 fork 或者 multiprocess 之前 先去,dispose 释放 所有连接。
  2. 再在 数据库 或者 消息队列中实现, 对应的 retry 方法 当 执行前 自行创建 新的连接。


先 创建 proc ,再释放

不推荐

解决思路

当前很多 数据库连接中 以及消息队列连接 中 都有 自带的 dispose 方法

去在 进程拷贝之前 dispose 掉 现有的 连接对象。

dispose 和 close 的差别,

close 以后 ,还可以open 得到 同属性的连接,

但是 dispose 之后 ,会将 对象 彻底释放,下次使用必须 重新 create 连接对象。如此一来 就不会产生进程间的 连接冲突问题。

一些实际工程中的 demo

py3 oslo_service fork 启动子进程

python3.7/site-packages/oslo_service/service.py

_start_child 之前 invoke 了 _child_process

  1. 关闭了写管道
  2. 重置了随机种子
  3. 翻译不好 直接把 代码留下吧
  def _child_process_handle_signal(self):
     # Setup child signal handlers differently
     。。。。

完整代码

class ProcessLauncher(object):
    ......省略
    def _child_process(self, service):
        self._child_process_handle_signal()
        # Reopen the eventlet hub to make sure we don't share an epoll
        # fd with parent and/or siblings, which would be bad
        eventlet.hubs.use_hub()
        # Close write to ensure only parent has it open
        os.close(self.writepipe)
        # Create greenthread to watch for parent to close pipe
        eventlet.spawn_n(self._pipe_watcher)
        # Reseed random number generator
        random.seed()
        launcher = Launcher(self.conf, restart_method=self.restart_method)
        launcher.launch_service(service)
        return launcher
    def _start_child(self, wrap):
        if len(wrap.forktimes) > wrap.workers:
            # Limit ourselves to one process a second (over the period of
            # number of workers * 1 second). This will allow workers to
            # start up quickly but ensure we don't fork off children that
            # die instantly too quickly.
            if time.time() - wrap.forktimes[0] < wrap.workers:
                LOG.info('Forking too fast, sleeping')
                time.sleep(1)
            wrap.forktimes.pop(0)
        wrap.forktimes.append(time.time())
        pid = os.fork()
        if pid == 0:
            self.launcher = self._child_process(wrap.service)
            while True:
                self._child_process_handle_signal()
                status, signo = self._child_wait_for_exit_or_signal(
                    self.launcher)
                if not _is_sighup_and_daemon(signo):
                    self.launcher.wait()
                    break
                self.launcher.restart()
            os._exit(status)
        LOG.debug('Started child %d', pid)
        wrap.children.add(pid)
        self.children[pid] = wrap
        return pid
相关文章
|
2月前
|
关系型数据库 数据库 RDS
【瑶池数据库训练营及解决方案本周精选(探索PolarDB,参与RDS迁移、连接训练营)】(5.30-6.8)
本周精选聚焦数据库迁移训练营、快速连接云数据库RDS训练营及智能多模态搜索解决方案。为用户提供模拟教程与实战演练,学习RDS MySQL实例连接与数据管理技能,助力企业智能化发展。每周解锁数据库实战新场景,抓紧时间,精彩不容错过!
|
4月前
|
关系型数据库 MySQL Java
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
|
3月前
|
安全 Linux 网络安全
YashanDB数据库服务端SSL连接配置
YashanDB支持通过SSL连接确保数据传输安全,需在服务端生成根证书、服务器证书及DH文件,并将根证书提供给客户端以完成身份验证。服务端配置包括使用OpenSSL工具生成证书、设置SSL参数并重启数据库;客户端则需下载根证书并正确配置环境变量与`yasc_env.ini`文件。注意:启用SSL后,所有客户端必须持有根证书才能连接,且SSL与密码认证独立运行。
|
4月前
|
数据库连接 应用服务中间件 PHP
|
3月前
|
Oracle 安全 关系型数据库
【Oracle】使用Navicat Premium连接Oracle数据库两种方法
以上就是两种使用Navicat Premium连接Oracle数据库的方法介绍,希望对你有所帮助!
672 28
|
3月前
|
SQL 数据库连接 数据库
在C++的QT框架中实现SQLite数据库的连接与操作
以上就是在C++的QT框架中实现SQLite数据库的连接与操作的基本步骤。这些步骤包括创建数据库连接、执行SQL命令、处理查询结果和关闭数据库连接。在实际使用中,你可能需要根据具体的需求来修改这些代码。
213 14
|
4月前
|
数据库
【YashanDB知识库】YDC连接数据库报错yasdb return code is zero
【YashanDB知识库】YDC连接数据库报错yasdb return code is zero
|
4月前
|
存储 监控 数据挖掘
消防行业如何借助时序数据库 TDengine 打造高效的数据监控与分析系统
本篇文章来自“2024,我想和 TDengine 谈谈”征文活动的优秀投稿,深入探讨了如何在消防行业中运用 TDengine 进行业务建模。文章重点介绍了如何通过 TDengine 的超级表、标签设计和高效查询功能,有效管理消防监控系统中的时序数据。作者详细阐述了实时监控、报警系统以及历史数据分析在消防行业中的应用,展示了 TDengine 在数据压缩、保留策略和分布式架构下的强大优势。
104 0
|
4月前
|
SQL 关系型数据库 数据库连接
|
4月前
|
数据库
【YashanDB知识库】数据库审计shutdown immediate操作导致数据库异常退出
【YashanDB知识库】数据库审计shutdown immediate操作导致数据库异常退出

热门文章

最新文章