You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP客户端向Python后台守护进程传输user_id并实现多请求队列处理

解决方案:PHP向后台Python守护进程传参并实现多任务队列处理

我来给你一套落地的实现方案,既能让PHP把user_id传递给后台运行的Python守护进程,还能通过队列机制处理多个并发的user_id请求。核心思路是让Python守护进程监听一个Unix域套接字(比TCP套接字更轻量,适合本地进程通信),PHP通过这个套接字发送user_id,Python内部用线程安全的队列+线程池来异步处理任务。


1. Python守护进程实现(带队列+套接字监听)

这个脚本会在后台一直运行,监听Unix套接字接收user_id,把任务放到队列里,用线程池并行处理:

import socket
import threading
from concurrent.futures import ThreadPoolExecutor
import os
import sys

# 配置项
UNIX_SOCKET_PATH = "/tmp/python_php_socket.sock"
MAX_WORKERS = 3  # 同时处理的任务数
LOG_FILE = "/tmp/python_daemon.log"

# 线程安全的任务队列
task_queue = []
queue_lock = threading.Lock()

def log(message):
    """记录日志到文件"""
    with open(LOG_FILE, "a") as f:
        f.write(f"{message}\n")

def process_user_id(user_id):
    """处理单个user_id的业务逻辑,这里替换成你的实际操作"""
    log(f"开始处理user_id: {user_id}")
    # 示例操作:模拟耗时任务
    import time
    time.sleep(5)
    log(f"完成处理user_id: {user_id}")

def queue_worker():
    """队列消费线程,不断从队列取任务交给线程池处理"""
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        while True:
            user_id = None
            # 加锁取队列元素
            with queue_lock:
                if task_queue:
                    user_id = task_queue.pop(0)
            if user_id:
                executor.submit(process_user_id, user_id)
            # 短暂休眠,避免空轮询占用CPU
            threading.Event().wait(0.1)

def daemonize():
    """将进程转为守护进程"""
    # 第一次fork
    try:
        if os.fork() > 0:
            sys.exit(0)
    except OSError as e:
        log(f"第一次fork失败: {e}")
        sys.exit(1)
    
    # 脱离父进程环境
    os.chdir("/")
    os.setsid()
    os.umask(0)
    
    # 第二次fork
    try:
        if os.fork() > 0:
            sys.exit(0)
    except OSError as e:
        log(f"第二次fork失败: {e}")
        sys.exit(1)
    
    # 重定向标准输入输出到/dev/null
    sys.stdout.flush()
    sys.stderr.flush()
    with open('/dev/null', 'r') as f:
        os.dup2(f.fileno(), sys.stdin.fileno())
    with open('/dev/null', 'w') as f:
        os.dup2(f.fileno(), sys.stdout.fileno())
        os.dup2(f.fileno(), sys.stderr.fileno())

def main():
    # 转为守护进程
    daemonize()
    log("Python守护进程已启动")
    
    # 启动队列消费线程
    threading.Thread(target=queue_worker, daemon=True).start()
    
    # 创建并监听Unix套接字
    try:
        # 如果套接字文件已存在,先删除
        if os.path.exists(UNIX_SOCKET_PATH):
            os.unlink(UNIX_SOCKET_PATH)
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.bind(UNIX_SOCKET_PATH)
        # 设置权限,让PHP进程能访问
        os.chmod(UNIX_SOCKET_PATH, 0o777)
        sock.listen(5)
        log(f"正在监听Unix套接字: {UNIX_SOCKET_PATH}")
        
        while True:
            conn, addr = sock.accept()
            log("收到新连接")
            # 读取PHP发送的user_id(注意编码和换行)
            data = conn.recv(1024).decode('utf-8').strip()
            if data:
                log(f"收到user_id: {data}")
                # 加锁把任务加入队列
                with queue_lock:
                    task_queue.append(data)
            conn.close()
    except Exception as e:
        log(f"守护进程出错: {e}")
        # 清理套接字文件
        if os.path.exists(UNIX_SOCKET_PATH):
            os.unlink(UNIX_SOCKET_PATH)
        sys.exit(1)

if __name__ == "__main__":
    main()

2. PHP端发送user_id的代码

PHP通过Unix套接字连接到Python守护进程,发送user_id:

<?php
$socket_path = '/tmp/python_php_socket.sock';
$user_id = 123; // 这里替换成你的实际user_id

// 连接Unix套接字
$socket = fsockopen("unix://{$socket_path}", -1, $errno, $errstr, 5);
if (!$socket) {
    die("连接失败: $errstr ($errno)");
}

// 发送user_id(注意加换行,方便Python端接收)
fwrite($socket, "{$user_id}\n");
fclose($socket);

echo "user_id {$user_id} 已发送";
?>

3. 部署与测试步骤

  1. 启动Python守护进程:

    nohup python3 script.py &
    

    可以通过查看日志文件/tmp/python_daemon.log确认进程是否启动成功。

  2. 测试PHP调用:
    直接访问你的PHP脚本,或者在命令行运行:

    php send_user_id.php
    

    然后查看Python的日志,会看到任务被接收并处理的记录。

  3. 处理多个并发请求:
    可以同时调用多次PHP脚本,Python会把多个user_id加入队列,用线程池并行处理,不会阻塞新的请求。


关键细节说明

  • Unix套接字权限:必须设置0o777权限,确保PHP进程(通常是www-data用户)能访问套接字文件。
  • 队列线程安全:用threading.Lock()确保多个线程操作队列时不会出现数据混乱。
  • 守护进程化:通过两次fork的标准方法实现守护进程,脱离终端后台运行。
  • 日志记录:所有操作都记录到日志文件,方便排查问题。

内容的提问来源于stack exchange,提问作者Savage Panda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:25:30