什么样的"EventBus"?在春季使用?内置反应堆,Akka? [英] What kind of "EventBus" to use in Spring? Built-in, Reactor, Akka?

查看:98
本文介绍了什么样的"EventBus"?在春季使用?内置反应堆,Akka?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们将在几周内启动一个新的Spring 4应用程序.而且我们想使用一些事件驱动的体系结构.今年,我到处都读到有关反应堆"的信息,在网上寻找它时,偶然发现了"Akka".

We're going to start a new Spring 4 application in a few weeks. And we'd like to use some event-driven architecture. This year I read here and there about "Reactor" and while looking for it on the web, I stumbled upon "Akka".

因此,到目前为止,我们有3种选择:

So for now we have 3 choices:

  • Spring's ApplicationEvent: http://docs.spring.io/spring/docs/4.0.0.RELEASE/javadoc-api/org/springframework/context/ApplicationEvent.html
  • Reactor: https://github.com/reactor/reactor#reactor
  • Akka: http://akka.io/

我找不到这些的真实比较.

I couldn't find a real comparison of those.

目前,我们只需要以下内容:

For now we just need something like:

  • X注册以侦听Event E
  • Y注册以侦听Event E
  • Z发送一个Event E
  • X registers to listen for Event E
  • Y registers to listen for Event E
  • Z sends an Event E

然后XY将接收并处理该事件.

And then X and Y will receive and handle the event.

我们很可能会以异步方式使用它,但是可以肯定的是,还会有一些同步场景.而且我们很可能总是发送类作为事件. (Reactor示例大部分使用Strings和String模式,但它也支持Objects.)

We will most likely use this in a async way, but for sure there will be also some synchronous scenarios. And we most likely send always a class as event. (The Reactor samples mostly make use of Strings and String patterns, but it also supports Objects).

据我了解,ApplicationEvent在默认情况下是同步工作的,而Reactor在异步方式下工作.并且Reactor还允许使用await()方法使其有点同步. AkkaReactor大致相同,但也支持Remoting.

As far as I understood, ApplicationEvent works synchronous by default and Reactor works the async way. And Reactor also allows to use the await() method to make it kinda synchronous. Akka provides more or less the same as Reactor, but also supports Remoting.

关于Reactor的await()方法:它可以等待多个线程完成吗?甚至可能是这些线程的一部分?如果我们以上面的示例为例:

Concerning Reactor's await() method: Can it wait for multiple threads to complete? Or maybe even a partial set of those threads? If we take the example from above:

  • X注册以侦听Event E
  • Y注册以侦听Event E
  • Z发送一个Event E
  • X registers to listen for Event E
  • Y registers to listen for Event E
  • Z sends an Event E

可以通过以下方式使其同步:等待X Y完成.是否有可能让它仅等待X,而不等待Y?

Is it possible to make it synchronous, by saying: Wait for X and Y to complete. And is it possible to make it wait just for X, but not for Y?

也许还有其他选择?例如JMS呢?

Maybe there are also some alternatives? What about for example JMS?

很多问题,但希望您能提供一些答案!

Lot of questions, but hopefully you can provide some answers!

谢谢!

  1. 当特定事件被触发时,我想创建10000封电子邮件.每封电子邮件都必须使用用户特定的内容生成.因此,我会创建很多线程(最多=系统cpu内核)来创建邮件,并且不会阻塞调用者线程,因为这可能需要几分钟的时间.

  1. When a specific event gets fired, I'd like to create 10000 emails. Every email has to get generated with user specific content. So I'd create a lot of threads (max = system cpu cores) which create the mails and do not block the caller thread, 'cause this can take some minutes.

当特定事件被触发时,我想从未知数量的服务中收集信息.每次提取大约需要100毫秒.在这里我可以想象使用Reactor的await,因为我需要这些信息来继续在主线程中工作.

When a specific event gets fired, I'd like to collect information from an unknown number of services. Each fetch takes about 100ms. Here I could imagine using Reactor's await, 'cause I need those information for continuing my work in the main thread.

当触发特定事件时,我想根据应用程序配置执行一些操作.因此,应用程序必须能够动态(取消)注册消费者/事件处理程序.他们会在活动中做自己的事情,我不在乎.因此,我将为每个处理程序创建一个线程,然后继续在主线程中继续工作.

When a specific event gets fired, I'd like to perform some operations based on application configuration. So the application must be able to dynamically (un)register comsumers/event handlers. They'll do their own stuff with the Event and I don't care. So I would create a thread for every of those handlers and just continue doing my work in the main thread.

简单的去耦:我基本上知道所有接收者,但是我只是不想调用代码中的每个接收者.多数情况下,这应该是同步完成的.

Simple decoupling: I basically know all receivers, but I just don't want to call every receiver in my code. This should mostly get done synchronously.

听起来像我需要一个ThreadPool或RingBuffer.这些框架是否具有动态的RingBuffer,如果需要,它们会增大大小?

Sound like I need a ThreadPool or a RingBuffer. Do those frameworks have dynamic RingBuffers, which grow in size if needed?

推荐答案

我不确定我能否在这个狭小的空间中充分回答您的问题.但我会试一试! :)

I'm not sure I can adequately answer your question in this small space. But I'll give it a shot! :)

就功能而言,Spring的ApplicationEvent系统和Reactor确实非常不同. ApplicationEvent路由基于ApplicationListener处理的类型.除此之外,您还必须自己实现逻辑(但这不一定是一件坏事).但是,Reactor提供了一个全面的路由层,该路由层也非常轻巧且完全可扩展.两端在订阅和发布事件的能力上在功能上有任何相似之处,这实际上是任何事件驱动系统的功能.另外,不要忘记Spring 4附带了新的spring-messaging模块.它是Spring Integration中可用工具的子集,并且还提供了围绕事件驱动的体系结构进行构建的抽象.

Spring's ApplicationEvent system and Reactor are really quite distinct as far as functionality goes. ApplicationEvent routing is based on the type handled by the ApplicationListener. Anything more complicated than that and you'll have to implement the logic yourself (that's not necessarily a bad thing, though). Reactor, however, provides a comprehensive routing layer that is also very lightweight and completely extensible. Any similarity in function between the two ends at their ability to subscribe and publish events, which is really a feature of any event-driven system. Also don't forget the new spring-messaging module out with Spring 4. It's a subset of the tools available in Spring Integration and also provides abstractions for building around an event-driven architecture.

Reactor将帮助您解决几个关键问题,否则您将不得不自行管理:

Reactor will help you solve a couple key problems that you would otherwise have to manage yourself:

选择器匹配:Reactor进行Selector匹配,包括一系列匹配-从简单的.equals(Object other)调用到更复杂的URI模板匹配(允许占位符提取).您还可以使用自己的自定义逻辑扩展内置选择器,以便可以将丰富对象用作通知键(例如域对象).

Selector matching: Reactor does Selector matching, which encompasses a range of matches--from a simple .equals(Object other) call, to a more complex URI templating match which allows for placeholder extraction. You can also extend the built-in selectors with your own custom logic so you can use rich objects as notification keys (like domain objects, for instance).

Stream and Promise API :您已经参考.await()方法提到了Promise API,该方法实际上是针对期望阻塞行为的现有代码.当使用Reactor编写新代码时,使用组合和回调通过不阻塞线程来有效地利用系统资源并不能承受太大的压力.在依赖少量线程来执行大量任务的体系结构中,阻塞调用者几乎从来不是一个好主意.期货根本无法实现云扩展,这就是为什么现代应用程序利用替代解决方案的原因.

Stream and Promise APIs: You mentioned the Promise API already with reference to the .await() method, which is really meant for existing code that expects blocking behavior. When writing new code using Reactor, it can't be stressed highly enough to use compositions and callbacks to effectively utilize system resources by not blocking threads. Blocking the caller is almost never a good idea in an architecture that depends on a small number of threads to execute a large volume of tasks. Futures are simply not cloud-scalable, which is why modern applications leverage alternative solutions.

您的应用程序可以使用Streams或Promises来构建,尽管说实话,我认为您会发现Stream更加灵活. API的主要好处是可组合性,它使您可以将动作链接到一个依赖链中而不会阻塞.作为基于电子邮件用例的现成示例,您描述:

Your application could be architected with Streams or Promises either one, though honestly, I think you'll find the Stream more flexible. The key benefit is the composability of the API, which allows you to wire actions together in a dependency chain without blocking. As a completely off-the-cuff example based on your email use-case you describe:

@Autowired
Environment env;
@Autowired
SmtpClient client;

// Using a ThreadPoolDispatcher
Deferred<DomainObject, Stream<DomainObject>> input = Streams.defer(env, THREAD_POOL);

input.compose()
  .map(new Function<DomainObject, EmailTemplate>() {
    public EmailTemplate apply(DomainObject in) {
      // generate the email
      return new EmailTemplate(in);
    }
  })
  .consume(new Consumer<EmailTemplate>() {
    public void accept(EmailTemplate email) {
      // send the email
      client.send(email);
    }
  });

// Publish input into Deferred
DomainObject obj = reader.readNext();
if(null != obj) {
  input.accept(obj);
}

Reactor还提供了 Boundary ,它基本上是CountDownLatch用于阻止任意使用者(因此,如果您要做的只是阻止Consumer完成,则不必构造Promise).在这种情况下,您可以使用原始的Reactor并使用on()notify()方法来触发服务状态检查.

Reactor also provides the Boundary which is basically a CountDownLatch for blocking on arbitrary consumers (so you don't have to construct a Promise if all you want to do is block for a Consumer completion). You could use a raw Reactor in that case and use the on() and notify() methods to trigger the service status checking.

但是,对于某些事情,您似乎想要的是从ExecutorService返回的Future,不是吗?为什么不简单地做简单的事情呢?只有在吞吐量性能和开销效率很重要的情况下,Reactor才会真正受益.如果您阻塞了调用线程,那么您可能会抹去Reactor会给您带来的效率提升,因此在这种情况下,使用更传统的工具集可能会更好.

For some things, however, it seems like what you want is a Future returned from an ExecutorService, no? Why not just keep things simple? Reactor will only be of real benefit in situations where your throughput performance and overhead effeciency is important. If you're blocking the calling thread, then you're likely going to be wiping away the effeciency gains that Reactor will give you anyway, so you might be better off in that case using a more traditional toolset.

关于Reactor开放性的好处是,没有什么可以阻止两者进行交互.您可以自由地将FuturesConsumers混合而不使用静态.在这种情况下,请记住,您的速度只会与最慢的组件一样快.

The nice thing about the openness of Reactor is that there's nothing stopping the two from interacting. You can freely mix Futures with Consumers without static. In that case, just keep in mind that you're only ever going to be as fast as your slowest component.

这篇关于什么样的"EventBus"?在春季使用?内置反应堆,Akka?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆