Python:如何在同一时刻触发多个进程
我正在尝试运行一个进程,该进程执行http POST,而http POST将向服务器发送警报(发送警报所需的时间为纳秒)。我试图测试服务器在毫秒内处理警报的能力。根据给定的标准,据说服务器每秒可以处理6000个警报 我使用多处理模块创建了一段代码,该模块发送6000个警报,但我使用的是for循环,因此执行for循环所需的时间超过一秒钟。因此,所有6000进程不会同时触发 有没有办法在同一瞬间触发多个(N个)进程 这是我的代码:flowtesting.py,它是一个库。接下来是我在“#####”之后的脚本 导入json 导入httplib2 类流测试(): definit(自身、公司ID、设备IP): self.companyId=companyId self.deviceIp=deviceIpPython:如何在同一时刻触发多个进程,python,Python,我正在尝试运行一个进程,该进程执行http POST,而http POST将向服务器发送警报(发送警报所需的时间为纳秒)。我试图测试服务器在毫秒内处理警报的能力。根据给定的标准,据说服务器每秒可以处理6000个警报 我使用多处理模块创建了一段代码,该模块发送6000个警报,但我使用的是for循环,因此执行for循环所需的时间超过一秒钟。因此,所有6000进程不会同时触发 有没有办法在同一瞬间触发多个(N个)进程 这是我的代码:flowtesting.py,它是一个库。接下来是我在“#####”之
def generate_savedSearchName(self, randNum):
self.randMsgId = randNum
self.savedSearchName = "TEST %s risk31 more than 3" % self.randMsgId
def def_request_body_dict(self):
self.reqBody_dict = \
{ "Header" : {"agid" : "Agent1",
"mid": self.randMsgId,
"ts" : 1253125001
},
"mp":
{
"host" : self.deviceIp,
"index" : self.companyId,
"savedSearchName" : self.savedSearchName,
}
}
self.req_body = json.dumps(self.reqBody_dict)
def get_default_hdrs(self):
self.hdrs = {'Content-type': 'application/json',
'Accept-Language': 'en-US,en;q=0.8'}
def send_request(self, sIp, method="POST"):
self.sIp = sIp
self.url = "http://%s:8080/agent/splunk/messages" % self.sIp
http_cli = httplib2.Http(timeout=180, disable_ssl_certificate_validation=True)
rsp, rsp_body = http_cli.request(uri=self.url, method=method, headers=self.hdrs, body=self.req_body)
print "rsp: %s and rsp_body: %s" % (rsp, rsp_body)
# My testScript
from flowTesting import flowTesting
import random
import multiprocessing
deviceIp = "10.31.421.35"
companyId = "CPY0000909"
noMsgToBeSent = 1000
sIp = "10.31.44.235"
uniq_msg_id_list = random.sample(xrange(1,10000), noMsgToBeSent)
def runner(companyId, deviceIp, uniq_msg_id):
proc = flowTesting(companyId, deviceIp)
proc.generate_savedSearchName(uniq_msg_id)
proc.def_request_body_dict()
proc.get_default_hdrs()
proc.send_request(sIp)
process_list = []
for uniq_msg_id in uniq_msg_id_list:
savedSearchName = "TEST-1000 %s risk31 more than 3" % uniq_msg_id
process = multiprocessing.Process(target=runner, args=(companyId,deviceIp,uniq_msg_id,))
process.start()
process.join()
process_list.append(process)
print "Process list: %s" % process_list
print "Unique Message Id: %s" % uniq_msg_id_list
您需要使用进程间同步原语。在Linux上使用Sys-V信号量,在Windows上使用Win32事件
您的6000个进程将等待此信号量/事件,并从另一个进程触发它,从而将所有6000个进程从等待状态释放到就绪状态,然后操作系统将尽快开始执行它们。让它们同时发生显然是不可能的,除非你有一台6000核的机器和一个调度程序能够完美地处理它们的操作系统内核(你没有),否则你不可能一次运行6000段代码 而且,即使你这样做了,他们都在试图通过套接字发送消息。即使你的内核是如此疯狂的并行,除非你有6000个独立的NIC,否则它们最终会在NIC缓冲区中序列化。这就是IP的工作方式:一个接一个的包。当然,路径上有所有的路由器,服务器的NIC,服务器的操作系统等等。即使IP没有阻挡,字节也需要时间通过电缆传输。因此,在同一时刻实现这一点的唯一方法,即使在理论上,是在每一侧安装6000个NIC,并用相同的光纤将它们直接连接到彼此 然而,你并不真的需要他们在同一瞬间,只是彼此比他们更接近。您没有向我们显示您的代码,但可能您刚刚开始6000个
过程
es,所有人都会立即尝试发送消息。这意味着您将进程启动时间包括在倾斜时间中,该时间可能非常慢(特别是在Windows上)
您可以通过使用线程而不是进程来减少这种情况。这似乎有悖常理,但Python非常擅长处理I/O绑定线程,而且每个现代操作系统都非常擅长启动新线程
但实际上,您需要的是对您的线程或进程进行测试,让所有线程或进程在尝试执行任何工作之前完成所有设置工作(包括进程启动)
它可能仍然不够紧,但它会比你现在可能有的更紧
您将面临的下一个限制是上下文切换时间。现代操作系统非常擅长调度任务,但并不擅长同时执行6000个任务。所以,实际上,您希望将其减少到N个进程,每个进程只需以尽可能快的速度顺序发送6000/N连接。这将使它们进入内核/NIC的速度比一次尝试6000次并让操作系统为您执行序列化要快得多。(事实上,在某些平台上,根据硬件的不同,一个进程连续运行6000次可能比N运行6000/N要好。请用两种方法进行测试。)
套接字库本身仍有一些开销。为了解决这个问题,您需要预先制作所有IP数据包,然后创建一个原始套接字并发送这些数据包。从每个连接发送第一个数据包,然后从每个连接发送第二个数据包,以此类推。简短回答:否。除非您的服务器有6000个内核同时运行6000个任务。如果您想以快速顺序执行它们(但不一定同时执行),那么有几种方法。首先,你能在这里发布代码的相关部分吗?即使你的机器有6000个内核,并且你的操作系统可以完美地调度它们,并且你使用,例如,a使它们一次触发…它们仍然会被你的NIC、你的路由器、路上的所有路由器排队,对于这样的IO操作,您甚至不需要多个进程。您只需要在异步事件循环中从单个程序打开多个套接字。尽管编写代码要复杂一点。@Adal:GIL不会对I/O绑定代码(至少在3.2+中)造成严重问题,只会对CPU绑定代码造成严重问题。仍然有一些开销,但与进程启动开销相比,它可能要少得多。这就是我所说的“这似乎有悖常理,但Python非常擅长处理I/O绑定的线程,而且每个现代操作系统都非常擅长启动新线程。”