我应该使用什么消息传递模式来处理来自休息请求的 return 响应?
What messaging pattern should I use to process and return responses from a rest request?
我有一个与此类似的轴辐式架构:
GET 请求进入集线器并将其路由到其中一个分支进行处理。在集线器上,我还将请求放在一个带有 UUID 的映射中,这样当我从处理中取回数据时,我可以 return 做出正确的响应。辐条是相同的,用于平衡负载。然后,我需要将信息从分支传回集线器并 return 正确的响应。
我想使用 JMS 进行消息传递。
integration patterns 的最佳组合是什么?
好吧,如果我正确理解您的设计,这似乎是 request/reply 场景,因为辐条实际上返回了一些响应。如果不是,它将是 publish/subscribe.
您可以将 ActiveMQ 用于 jms 和 request/reply。看这里:
http://activemq.apache.org/how-should-i-implement-request-response-with-jms.html
至于细节,这完全取决于您的要求,会立即发送响应还是需要很长的 运行 过程?
如果这是一个漫长的 运行 过程,您可以避免 request/reply 并使用即刻即弃的方案。
基本上,集线器会在一个队列上触发一条消息,该消息正被其中一个分支组件侦听。后端处理完成后,它 returns 对集线器监控的队列的响应。您可以通过一些 correlationId 关联 request/response。在请求部分,您可以将 correlationId 保存在缓存中以匹配响应。在 request/reply 场景中,这是由基础架构为您完成的,但不会用于较长的 运行 过程。
总结一下:
使用 ActiveMQ 通过 JMS 处理消息。
将 Camel 用于 REST 位。
如果您确定希望得到相当快的响应,请使用 request/reply。
如果您希望响应需要很长时间但必须匹配消息 correlationIds,请使用 fire and forget。
您在 Vert.x 中已经有 Request/Reply,因此您可以使用大约 20 行代码实现此行为:
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
Router router = Router.router(vertx);
router.get("/").handler((request) -> {
// When hub receives request, it dispatches it to one of the Spokes
String requestUUID = UUID.randomUUID().toString();
vertx.eventBus().send("processMessage", requestUUID, (spokeResponse) -> {
if (spokeResponse.succeeded()) {
request.response().end("Request " + requestUUID + ":" + spokeResponse.result().body().toString());
}
// Handle errors
});
});
// We create two Spokes
vertx.deployVerticle(new SpokeVerticle());
vertx.deployVerticle(new SpokeVerticle());
// This is your Hub
vertx.createHttpServer().requestHandler(router::accept).listen(8888);
}
这是 Spoke 的样子:
/**
* Static only for the sake of example
*/
static class SpokeVerticle extends AbstractVerticle {
private String id;
@Override
public void start() {
this.id = UUID.randomUUID().toString();
vertx.eventBus().consumer("processMessage", (request) -> {
// Do something smart
// Reply
request.reply("I'm Spoke " + id + " and my reply is 42");
});
}
}
的浏览器中访问它
您应该看到每次都会生成请求 ID,而两个 Spokes 中只有一个响应您的请求。
如果您想将 Camel 与 JMS 一起使用,那么您应该使用 Request-Reply EIP, and as far as examples go, you have a pretty good one provided via Camel's official examples - 它可能有点旧,但仍然非常有效。
虽然您可以通过 Spring 忽略示例的 Camel 配置,但其路由定义提供了足够的信息:
public class SpokeRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("jms:queue:spoke")
.process(e -> {
Object result = ...; // do some processing
e.getIn().setBody(result); // publish the result
// Camel will automatically reply if it finds a ReplyTo and CorrelationId headers
});
}
}
然后 HUB 需要做的就是调用:
ProducerTemplate camelTemplate = camelContext.createProducerTemplate();
Object response = camelTemplate.sendBody("jms:queue:spoke", ExchangePattern.InOut, input);
我有一个与此类似的轴辐式架构:
GET 请求进入集线器并将其路由到其中一个分支进行处理。在集线器上,我还将请求放在一个带有 UUID 的映射中,这样当我从处理中取回数据时,我可以 return 做出正确的响应。辐条是相同的,用于平衡负载。然后,我需要将信息从分支传回集线器并 return 正确的响应。
我想使用 JMS 进行消息传递。
integration patterns 的最佳组合是什么?
好吧,如果我正确理解您的设计,这似乎是 request/reply 场景,因为辐条实际上返回了一些响应。如果不是,它将是 publish/subscribe.
您可以将 ActiveMQ 用于 jms 和 request/reply。看这里: http://activemq.apache.org/how-should-i-implement-request-response-with-jms.html
至于细节,这完全取决于您的要求,会立即发送响应还是需要很长的 运行 过程?
如果这是一个漫长的 运行 过程,您可以避免 request/reply 并使用即刻即弃的方案。
基本上,集线器会在一个队列上触发一条消息,该消息正被其中一个分支组件侦听。后端处理完成后,它 returns 对集线器监控的队列的响应。您可以通过一些 correlationId 关联 request/response。在请求部分,您可以将 correlationId 保存在缓存中以匹配响应。在 request/reply 场景中,这是由基础架构为您完成的,但不会用于较长的 运行 过程。
总结一下: 使用 ActiveMQ 通过 JMS 处理消息。 将 Camel 用于 REST 位。 如果您确定希望得到相当快的响应,请使用 request/reply。 如果您希望响应需要很长时间但必须匹配消息 correlationIds,请使用 fire and forget。
您在 Vert.x 中已经有 Request/Reply,因此您可以使用大约 20 行代码实现此行为:
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
Router router = Router.router(vertx);
router.get("/").handler((request) -> {
// When hub receives request, it dispatches it to one of the Spokes
String requestUUID = UUID.randomUUID().toString();
vertx.eventBus().send("processMessage", requestUUID, (spokeResponse) -> {
if (spokeResponse.succeeded()) {
request.response().end("Request " + requestUUID + ":" + spokeResponse.result().body().toString());
}
// Handle errors
});
});
// We create two Spokes
vertx.deployVerticle(new SpokeVerticle());
vertx.deployVerticle(new SpokeVerticle());
// This is your Hub
vertx.createHttpServer().requestHandler(router::accept).listen(8888);
}
这是 Spoke 的样子:
/**
* Static only for the sake of example
*/
static class SpokeVerticle extends AbstractVerticle {
private String id;
@Override
public void start() {
this.id = UUID.randomUUID().toString();
vertx.eventBus().consumer("processMessage", (request) -> {
// Do something smart
// Reply
request.reply("I'm Spoke " + id + " and my reply is 42");
});
}
}
的浏览器中访问它
您应该看到每次都会生成请求 ID,而两个 Spokes 中只有一个响应您的请求。
如果您想将 Camel 与 JMS 一起使用,那么您应该使用 Request-Reply EIP, and as far as examples go, you have a pretty good one provided via Camel's official examples - 它可能有点旧,但仍然非常有效。
虽然您可以通过 Spring 忽略示例的 Camel 配置,但其路由定义提供了足够的信息:
public class SpokeRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("jms:queue:spoke")
.process(e -> {
Object result = ...; // do some processing
e.getIn().setBody(result); // publish the result
// Camel will automatically reply if it finds a ReplyTo and CorrelationId headers
});
}
}
然后 HUB 需要做的就是调用:
ProducerTemplate camelTemplate = camelContext.createProducerTemplate();
Object response = camelTemplate.sendBody("jms:queue:spoke", ExchangePattern.InOut, input);