Xiaoxia[PG] Yesterday is history, tomorrow is mistery, today is a gift!

28九/1133

如何让多个进程监听同一个TCP端口

通常我的服务器上都会启用多个php-cgi程序,有时候这样做是很必要的

1. 可以同时让多个进程处理请求,负载均衡。
2. 避免一个进程崩溃时,在重新启动前,无法及时提供服务。

启用多个相同服务进程必然需要考虑共用一个socket。对于php-cgi程序来说,是通过stdin文件描述符来传递这个socket。

工作原理如下:

下面是一个示例代码,演示如何启动多个子进程监听同一个端口。

Parent Proecess:

import os, socket, sys

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("", 8000))
s.listen(10)

for i in xrange(3):
    pid = os.fork()
    if pid == 0:
        os.dup2(s.fileno(), sys.stdin.fileno())
        os.execv("/usr/bin/python", ("python", "child.py"))
    else:
        print "fork", i, "process id =", pid

print "Parent exited"
sys.exit()

Child Process:

import socket, os, sys

print "Child", os.getpid(), "started"
s = socket.fromfd(sys.stdin.fileno(), socket.AF_INET, socket.SOCK_STREAM)
fd, address = s.accept()

print "Accept from", address

sys.exit()

执行parent.py后,启动了三个child.py的进程,这三个进程都等待来自8000端口的连接,当有连接时打印对方地址并结束进程。通过终端运行

telnet localhost 8000

可以测试child.py进程的响应。连续telnet三次,则让三个进程都完全结束。

若有更好地方法或者建议,请与我交流 :)

喜欢这个文章吗?

考虑订阅我们的RSS Feed吧!

评论 (33) 引用 (0)
  1. Haproxy的第四层模式可以参考

  2. 能不能写个C版本的呢?

  3. 提一点小意见:加强算法和设计模式,并将其付诸实践,这才是王道。其他一切都是浮云,,,

    • 嗯,这个可能是每个软件工程师的基本要求吧!
      不过说实话呢,我以后的方向不一定是做软件开发的,所以我自己对算法和模式的要求并不高,只要大部分人能看懂我的代码,能从我的代码学到东西,就很不错啦!

  4. 三个进程同时listen同一个端口,那么遇到连接的时候是怎么决定由哪一个进程accept呢?求解
    另外,在Linux上的子进程不是可以共享父进程的fd么?为什么要通过stdin去传递呢?

    • 这个处理方式,Linux和Windows好像不同的吧。Linux好像是随机寻找空闲的分配。
      为什么要通过stdin去传递呢?因为调用了exec系统调用,已经装载了新的程序,应该只有标准文件描述符被保留下来吧,你觉得呢?

  5. 這個site每日traffic ip系幾多?有1000沒?

  6. 用stdin发送fd?!?把stdin覆盖了呀……

    话说,UNIX域套接字发送fd正统一点……

    —删— 我以为你是自己写的,原来是fork exec到php进程的。。怪不得。。

    • 把我的想法贴出来(貌似乃用graphviz啊)
      digraph G
      {
      “Request” -> “Daemon”
      “Daemon” -> “Service 1″ [label="fork"]
      “Daemon” -> “Service 2″ [label="fork"]
      “Service 1″ -> “Subprocess #1″ [label="same fd"]
      “Service 1″ -> “Subprocess #2″ [label="same fd"]
      “Service 1″ -> “Subprocess #3″ [label="same fd"]

      “Service 2″ -> ” Subprocess #1″ [label="same fd"]
      “Service 2″ -> ” Subprocess #2″ [label="same fd"]
      “Service 2″ -> ” Subprocess #3″ [label="same fd"]
      }

      • 嗯,原来你也用graphviz哦!
        这个想法跟我想的差不多啊,我也是有计划写一个Daemon,用它来运行和守护我用python写的一堆服务程序。
        unix domain socket还没真正使用过,所以通常都用stdin来传递,没有觉得正统不正统的,只想简简单单点解决问题。

    • 恩,这个是学习了fcgi进程管理器的做法,可以spawn php-cgi的进程,也可以让自己写的服务进程也使用这种模式进行工作 :)


Leave a comment

(required)

还没有引用.