研究了下multiprocessing.managers,略有收获,随笔一篇;

核心思路是构造一个manager进程,这个进程可以通过unix socket或tcp socket与其它进程通信;因为利用了socket,所以通信的进程间不要求具备父子关系,甚至可以跨主机(通过tcp socket);

通过manager进行数据结构共享,可以应用于很多的IPC场景;这里只做一个示例,在manager内维护一个队列,做为生产者消费者模型中的消息队列;

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# coding:utf-8
 
import os
import time
import subprocess
 
from multiprocessing import Process
#from multiprocessing.managers import SyncManager
from multiprocessing.managers import BaseManager
from multiprocessing import JoinableQueue
 
#父进程
pid = os.getpid()
print("parent pid %d" % pid)
 
class TestManager(BaseManager):
  pass
 
#用于共享的队列
jqueue = JoinableQueue()
 
#用于获取队列的方法
def _get_queue():
    return jqueue
 
#启动server(manager)
def make_server(port, authkey):
    # 注册rpc,获取共享的队列(的代理,这段代码的实现很有意思,建议看看源码)
    TestManager.register("get_queue",callable=lambda : _get_queue())
    # 如果要走tcp socket,就用这一行
    #manager = TestManager(address=('', port), authkey=authkey)
    # 如果要走unix socket,就用这一行
    manager = TestManager(authkey=authkey)
    # 启动server(manager)进程
    manager.start()
    return manager
 
# consumer进程的入口
def do_consume(manager):
    print ("consumer pid %d" % os.getpid())
    queue=manager.get_queue()
    count = 0
    while True:
        item = queue.get(block=True)
        #print(item)
        #time.sleep(1)
        queue.task_done()
        if item is None:
            conn = queue._tls.connection
            break
        count += 1
    print ("done consuming %d" % count)
 
#构造新的manager实例做为client连接manager server
def make_client(address, authkey):
    # 注册rpc,用于非父子进程环境时,新构造的manager识别rpc方法
    TestManager.register("get_queue")
    manager = TestManager(address=address, authkey=authkey)
    manager.connect()
    return manager
 
# producer进程的入口
def do_produce(address, authkey):
    print ("producer pid %d" % os.getpid())
    client=make_client(address, authkey)
    queue=client.get_queue()
    for i in range(10000):
        queue.put(i, block=True)
    print ("done producing")
 
# terminator进程的入口
def do_terminate(address, authkey):
    client=make_client(address, authkey)
    queue=client.get_queue()
    queue.put(None, block=True)
 
authkey = b'foo'
manager=make_server(6666, authkey)
address = manager._address
# 查看manager的进程号
print ("manager pid %d" % manager._process.ident)
 
# 通过父子进程变量传递的方式,向consumer进程传递manager
consumer = Process(target=do_consume, args=(manager, ))
consumer.start()
 
# 伪造非父子进程传递address和authkey的方式,向producer进程传递连接manager需要的信息
producer = Process(target=do_produce, args=(address, authkey))
producer.start()
 
# 查看当前的进程树
status, output = subprocess.getstatusoutput('pstree -p %d' % pid)
print (output)
 
producer.join()
 
# 伪造非父子进程传递address和authkey的方式,再启动一个terminator进程结束通信
terminator = Process(target=do_terminate, args=(address, authkey))
terminator.start()
terminator.join()
 
consumer.join()

  

 

以上示例代码的过程如下:

  1. 构造manager server;
  2. 构造一个consumer进程,直接从父进程获取到manager对象;
  3. 再构造一个producer进程,通过传递address和authkey,新构造manager client,并连接manager server;
  4. producer获取到共享队列,生产消息;
  5. consumer获取到共享队列,消费消息;
  6. terminator(producer)生产一个空消息;
  7. consumer获取到空消息,消费结束;

 

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
parent pid 30460
manager pid 30461
consumer pid 30463
producer pid 30464
python(30460)-+-pstree(30465)
              |-python(30461)-+-{python}(30462)
              |               |-{python}(30472)
              |               |-{python}(30474)
              |               `-{python}(30475)
              |-python(30463)
              `-python(30464)
done producing
done consuming 10000

  

可以看到共生成4个子进程,一个manager server、一个consumer、一个producer、还有一个pstree查看进程树;

posted @ 2019-04-25 19:33 ZisZ 阅读(429) 评论(0) 推荐(0) 编辑
摘要: n重复数组,是指数组中的数字都出现n次; 唯一m重复异类数,是指存在唯一一个没出现n次,只出现了m次的数; 这里我简记它为nX+my问题,求解y,其中m < n,数组中都是整数; 3X+y问题 一直没有精力刷leetcode,今天查问题无意中看到了leetcode 137:给定一个非空整数数组,除了 阅读全文
posted @ 2019-02-27 10:56 ZisZ 阅读(313) 评论(0) 推荐(0) 编辑
摘要: 摘抄自hbase ref guide 0.94; 在写本文的时候,hbase ref guide已经更新到1.2及2.0了,但是个人感觉Thrift过滤语法部分写得都没有0.94的好,省掉了example,看起来很不方便,也不便于在hbase shell中进行调试,因而复制一份过来,以免以后找不到; 阅读全文
posted @ 2018-09-18 09:58 ZisZ 阅读(834) 评论(0) 推荐(0) 编辑
摘要: 刚开始接触kubernetes时,对kubelet的--pod-infra-container-image参数非常不能理解,不理解为什么我的业务应用需要依赖一个第三方的容器; 上文入门级kubernetes安装流程中简单提了一句,启动pod后的两个容器会有相同的网络地址,这样,多个容器可以绑定为一个 阅读全文
posted @ 2018-07-02 09:50 ZisZ 阅读(3172) 评论(0) 推荐(0) 编辑
摘要: 前言 翻看了很多的kubernetes的安装教程,也反复做了一些实验,深感教程之复杂,所以决定写一个极简版本的安装教程,目标在于用尽可能少的参数启动服务,并且剖析各组件关系,然后再在此基础上逐步添加参数,实现功能完备; 干什么 在server节点上启动三个主要服务:apiserver、control 阅读全文
posted @ 2018-06-29 10:06 ZisZ 阅读(3623) 评论(0) 推荐(1) 编辑
摘要: 本以为docker准备妥当之后,就可以直接上k8s了,结果yum install kubernetes,报错:Error: docker-ce conflicts with docker-1.9.1 ..... 这才想起来,自己的docker不是从centos官方源获取的,而是用了docker的源安 阅读全文
posted @ 2018-06-22 17:40 ZisZ 阅读(2736) 评论(1) 推荐(0) 编辑
摘要: 本篇做一个没有实用价值的mnist rpc服务,重点记录我在调试整合tensorflow和opencv时遇到的问题; 准备模型 mnist的基础模型结构就使用tensorflow tutorial给的例子,卷积-池化-卷积-池化-全连接-dropout-softmax,然后走常规的优化训练,得到一个 阅读全文
posted @ 2018-06-20 10:54 ZisZ 阅读(602) 评论(1) 推荐(0) 编辑
摘要: 首先需要搞定tensorflow c++库,搜了一遍没有找到现成的包,于是下载tensorflow的源码开始编译; tensorflow的contrib中有一个makefile项目,极大的简化的接下来的工作; 按照tensorflow makefile的说明文档,开始做c++库的编译: 1. 下载依 阅读全文
posted @ 2018-06-06 15:04 ZisZ 阅读(3931) 评论(0) 推荐(0) 编辑
摘要: 用一个非常简单的例子学习导出和加载模型; 导出 写一个y=a*x+b的运算,然后保存graph; 运行 在models目录下生成了test_graph.pb; 注:convert_variables_to_constants操作是将模型参数froze(保存)进graph中,这时的graph相当于是s 阅读全文
posted @ 2018-06-06 14:15 ZisZ 阅读(1427) 评论(0) 推荐(0) 编辑
摘要: 虽然jupyter hub是支持ldap的,见ldapauthenticator; 但是登录成功后似乎要以登录用户名启动notebook,而登录用户在服务器上不存在,于是500了; 在服务器上通过pam/nss进行ldap验证?别逗了,谁要那么干啊。 于是转换思路,核心仿照这篇博客:docker+c 阅读全文
posted @ 2018-06-04 18:05 ZisZ 阅读(976) 评论(2) 推荐(0) 编辑
点击右上角即可分享
微信分享提示