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

Spring Boot微服务异步触发Python脚本并接收执行完成通知的最优方案

Hey Sudheer,我来给你梳理几个靠谱的实现方案,都是生产环境里常用的,还附了示例代码,你可以参考下~

最优方案推荐:基于消息队列的异步触发+回调(生产环境首选)

这个方案的核心是用消息队列(比如RabbitMQ、Kafka)实现Spring Boot和Python脚本的解耦,既能保证异步触发的可靠性,又能确保脚本执行完成后通知微服务。优势在于消息持久化、自动重试、解耦服务,完全适合生产环境的需求。

实现步骤

  • Spring Boot将触发脚本的请求发送到消息队列的「任务队列」
  • Python端监听「任务队列」,收到消息后执行目标脚本
  • 脚本执行完成后,Python将结果发送到消息队列的「回调队列」
  • Spring Boot监听「回调队列」,接收脚本执行完成的通知

示例代码

1. Spring Boot端(以RabbitMQ为例)

首先添加RabbitMQ依赖到pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

配置RabbitMQ队列和交换机:

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {
    // 任务队列:Spring Boot发送触发消息到这里
    public static final String TASK_QUEUE = "python_script_task_queue";
    // 回调队列:Python发送执行结果到这里
    public static final String CALLBACK_QUEUE = "python_script_callback_queue";

    @Bean
    public Queue taskQueue() {
        return new Queue(TASK_QUEUE, true); // 持久化队列
    }

    @Bean
    public Queue callbackQueue() {
        return new Queue(CALLBACK_QUEUE, true);
    }
}

发送触发消息的服务:

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

@Service
public class ScriptTriggerService {
    private final RabbitTemplate rabbitTemplate;

    public ScriptTriggerService(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    // 异步触发Python脚本
    public void triggerPythonScript(String scriptParam) {
        // 可以传递脚本需要的参数,比如JSON格式
        rabbitTemplate.convertAndSend(RabbitMQConfig.TASK_QUEUE, scriptParam);
        System.out.println("已发送脚本触发请求,参数:" + scriptParam);
    }
}

监听回调队列的消费者:

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class ScriptCallbackListener {

    @RabbitListener(queues = RabbitMQConfig.CALLBACK_QUEUE)
    public void handleScriptResult(String result) {
        // 处理脚本执行完成的通知,比如更新数据库、发送告警等
        System.out.println("Python脚本执行完成,结果:" + result);
        // 这里可以写你的业务逻辑
    }
}

2. Python端(用pika库操作RabbitMQ)

首先安装依赖:

pip install pika

Python监听任务队列并执行脚本的代码:

import pika
import subprocess

# RabbitMQ连接配置
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明队列(和Spring Boot端一致)
channel.queue_declare(queue='python_script_task_queue', durable=True)
channel.queue_declare(queue='python_script_callback_queue', durable=True)

def execute_script(script_param):
    # 执行你的Python脚本,这里示例执行一个简单的脚本
    # 替换成你的脚本路径和参数
    result = subprocess.run(['python', '/path/to/your/script.py', script_param], 
                          capture_output=True, text=True)
    return result.stdout + result.stderr

def callback(ch, method, properties, body):
    script_param = body.decode()
    print(f"收到脚本触发请求,参数:{script_param}")
    
    # 执行脚本
    script_result = execute_script(script_param)
    
    # 发送回调消息到回调队列
    channel.basic_publish(exchange='',
                          routing_key='python_script_callback_queue',
                          body=script_result)
    print(f"脚本执行完成,已发送结果到回调队列:{script_result}")
    
    # 确认消息已处理
    ch.basic_ack(delivery_tag=method.delivery_tag)

# 设置消费者,手动确认消息
channel.basic_consume(queue='python_script_task_queue', on_message_callback=callback)

print("Python监听任务队列中...")
channel.start_consuming()

轻量替代方案:REST API回调模式

如果你的项目不需要复杂的消息中间件,这个轻量方案更适合。核心是Spring Boot调用Python的API触发脚本,同时传递自己的回调URL,Python脚本执行完成后主动调用这个URL通知结果。

实现步骤

  • Spring Boot暴露一个回调接口,用于接收脚本执行结果
  • Spring Boot异步调用Python的触发接口,携带回调URL和脚本参数
  • Python脚本执行完成后,调用Spring Boot的回调接口发送结果

示例代码

1. Spring Boot端

首先添加Web依赖到pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

回调接口:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ScriptCallbackController {

    @PostMapping("/api/script/callback")
    public void handleScriptCallback(@RequestBody String scriptResult) {
        System.out.println("收到Python脚本执行结果:" + scriptResult);
        // 处理结果的业务逻辑
    }
}

异步触发Python脚本的服务:

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ScriptTriggerService {
    private final RestTemplate restTemplate;

    public ScriptTriggerService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Async // 异步调用,不阻塞主线程
    public void triggerPythonScript(String scriptParam) {
        String callbackUrl = "http://localhost:8080/api/script/callback";
        // 构造请求参数,包含回调URL和脚本参数
        String requestBody = String.format("{\"param\":\"%s\", \"callbackUrl\":\"%s\"}", scriptParam, callbackUrl);
        
        // 调用Python的触发接口
        restTemplate.postForObject("http://localhost:5000/api/trigger-script", requestBody, String.class);
        System.out.println("已异步触发Python脚本");
    }
}

别忘了在启动类添加@EnableAsync注解开启异步支持:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

2. Python端(用Flask实现API)

首先安装依赖:

pip install flask requests

Python的API代码:

from flask import Flask, request
import subprocess
import requests

app = Flask(__name__)

def execute_script(script_param):
    # 执行你的脚本
    result = subprocess.run(['python', '/path/to/your/script.py', script_param], 
                          capture_output=True, text=True)
    return result.stdout + result.stderr

@app.route('/api/trigger-script', methods=['POST'])
def trigger_script():
    data = request.get_json()
    script_param = data.get('param')
    callback_url = data.get('callbackUrl')
    
    # 执行脚本
    script_result = execute_script(script_param)
    
    # 调用Spring Boot的回调接口发送结果
    requests.post(callback_url, data=script_result)
    
    return {"status": "success", "message": "脚本已触发执行"}

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

总结
  • 生产环境首选方案一(消息队列):可靠性高、支持重试、服务解耦,适合脚本执行时间长、并发高的场景
  • 轻量场景选方案二(REST回调):不需要中间件,代码简单,适合小型项目或快速原型开发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:14:44