据我所知,像RabbitMQ这样的消息代理可以帮助用不同语言/平台编写的不同应用程序相互通信。因为芹菜可以使用RabbitMQ作为消息代理,我相信我们可以将任务从任何应用程序排队到Celery,即使生产者没有用Python编写。
现在我试图找出如何通过RabbitMQ从C#编写的应用程序将任务排队到Celery。但我还没找到任何这样的例子。
我发现的唯一信息是this SO question
接受的答案建议使用Celery消息格式协议将消息从Java排队到RabbitMQ。但是,答案中给出的链接没有任何示例,只有消息格式。
此外,消息格式表示在此协议中需要任务ID(UUID)进行通信。我的C#应用程序应该如何知道芹菜任务的任务ID?据我所知,它只能知道任务名称,而不是任务ID。
答案 0 :(得分:5)
我不知道这个问题是否仍然具有相关性,但希望答案可以帮助其他人。
以下是我成功将任务发送到Celery example worker的方法。
您需要按照here所述在您的制作人(客户端)与RabbitMQ之间建立连接。
ConnectionFactory factory = new ConnectionFactory();
factory.UserName = username;
factory.Password = password;
factory.VirtualHost = virtualhost;
factory.HostName = hostname;
factory.Port = port;
IConnection connection = factory.CreateConnection();
IModel channel = connection.CreateModel();
在默认的RabbitMQ配置中,只有 Guest 用户只能用于本地连接(来自127.0.0.1)。 this问题的答案解释了如何在RabbitMQ中定义用户。
下一步 - 创建回调以获得结果。此示例使用Direct reply-to,因此答案侦听器将如下所示:
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var ansBody = ea.Body;
var ansMessage = Encoding.UTF8.GetString(ansBody);
Console.WriteLine(" [x] Received {0}", ansMessage);
Console.WriteLine(" [x] Done");
};
channel.BasicConsume(queue: "amq.rabbitmq.reply-to", noAck: true, consumer: consumer);
创建Celery将使用的任务消息:
IDictionary<string, object> headers = new Dictionary<string, object>();
headers.Add("task", "tasks.add");
Guid id = Guid.NewGuid();
headers.Add("id", id.ToString());
IBasicProperties props = channel.CreateBasicProperties();
props.Headers = headers;
props.CorrelationId = (string)headers["id"];
props.ContentEncoding = "utf-8";
props.ContentType = "application/json";
props.ReplyTo = "amq.rabbitmq.reply-to";
object[] taskArgs = new object[] { 1, 200 };
object[] arguments = new object[] { taskArgs, new object(), new object()};
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(object[]));
ser.WriteObject(stream, arguments);
stream.Position = 0;
StreamReader sr = new StreamReader(stream);
string message = sr.ReadToEnd();
var body = Encoding.UTF8.GetBytes(message);
最后,将消息发布到RabbitMQ:
channel.BasicPublish(exchange: "",
routingKey: "celery",
basicProperties: props,
body: body);
答案 1 :(得分:3)
答案 2 :(得分:1)
芹菜与花一起来。 Flower提供了REST API来管理任务。 https://flower.readthedocs.io/en/latest/api.html#post--api-task-async-apply-(.+) 在大多数情况下,这比手动创建任务并将其插入到MQ上更为简单和可靠。