Python:如何在同一时刻触发多个进程

Python:如何在同一时刻触发多个进程,python,Python,我正在尝试运行一个进程,该进程执行http POST,而http POST将向服务器发送警报(发送警报所需的时间为纳秒)。我试图测试服务器在毫秒内处理警报的能力。根据给定的标准,据说服务器每秒可以处理6000个警报 我使用多处理模块创建了一段代码,该模块发送6000个警报,但我使用的是for循环,因此执行for循环所需的时间超过一秒钟。因此,所有6000进程不会同时触发 有没有办法在同一瞬间触发多个(N个)进程 这是我的代码:flowtesting.py,它是一个库。接下来是我在“#####”之

我正在尝试运行一个进程,该进程执行http POST,而http POST将向服务器发送警报(发送警报所需的时间为纳秒)。我试图测试服务器在毫秒内处理警报的能力。根据给定的标准,据说服务器每秒可以处理6000个警报

我使用多处理模块创建了一段代码,该模块发送6000个警报,但我使用的是for循环,因此执行for循环所需的时间超过一秒钟。因此,所有6000进程不会同时触发

有没有办法在同一瞬间触发多个(N个)进程

这是我的代码:flowtesting.py,它是一个库。接下来是我在“#####”之后的脚本

导入json 导入httplib2

类流测试(): definit(自身、公司ID、设备IP): self.companyId=companyId self.deviceIp=deviceIp

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绑定的线程,而且每个现代操作系统都非常擅长启动新线程。”