javascript
#翻译NO.5# --- Spring Integration Framework
為什么80%的碼農都做不了架構師?>>> ??
???? 本人覺得這一章很重要,那就是 Spring默認的channel 的實現 DirectChannel,這個要大家多按照原文理解,開發者為何提供這樣的一個channel,以及該channel適用的場景。
DirectChannel
TheDirectChannelhas point-to-point semantics(語義) but otherwise is more similar to thePublishSubscribeChannelthan any of the queue-based channel implementations described above. It implements theSubscribableChannelinterface instead of thePollableChannelinterface, so it dispatches(分發) Messages directly to a subscriber(訂閱者). As a point-to-point channel, however, it differs from thePublishSubscribeChannelin that it will only send each Message to a single subscribed(理解這句話,如果有多個訂閱者 該Channel 僅僅選擇其中一個訂閱者發送,而忽略其他訂閱者)MessageHandler.
(PS:DirectChannel 從字面理解是 基于 點對點 傳輸模式。事實上,他更像是一個 PublishSubscribeChannel 的實現,除了內部實現消息隊列機制以外。 該類實現了 SubscribableChannel 接口 而不是 PollableChannel 接口。所以他會直接分發消息給訂閱者。 同時作為 點對點 的傳輸隊列,他有不同于傳統意義的 PublishSubscribeChannel。他每次僅僅發消息發送給訂閱者之一)
In addition to(除了) being the simplest point-to-point channel option, one of its most important features is that it enables a single thread to perform(扮演,充當) the operations on "both sides" of the channel. For example, if a handler is subscribed to aDirectChannel, then sending a Message to that channel will trigger invocation of that handler'shandleMessage(Message)method directly in the sender's thread, before the send() method invocation can return.(這里要是有個時序圖就好了,第一次閱讀這里是無法理解的,NND,坑爹的老外,傷不起的外語水平)
(PS:除了上述提到的點對點傳輸模式是 DirectChannel 的特性外,還有一個比較重要的特征就是,該通道允許單線程同時 充當 發送 與接受的角色,例如:一個訂閱者 注冊到 DirectChannel后,當一個消息發送到該 channel,則直接觸發handleMessage(Message)方法在 send 方法執行完之前。)
The key motivation(動機) for providing a channel implementation with this behavior(行為) is to support transactions(事務) that must span across the channel while still benefiting(受益) from the abstraction and loose coupling that the channel provides. If the send call is invoked within the scope of a transaction, then the outcome of the handler's invocation (e.g. updating a database record) will play a role in determining the ultimate result of that transaction (commit or rollback).
(PS:這樣做的動機是 為了 讓通道兩端的操作能包含在一個事務中。大概意思是這樣子的,其余的讀者自己理解)
| Since theDirectChannelis the simplest option and does not add any additional overhead that would be required for scheduling(調度) and managing the threads of a poller, it is the default channel type within Spring Integration. The general idea is to define the channels for an application and then to consider which of those need to provide buffering or to throttle input, and then modify those to be queue-basedPollableChannels. Likewise, if a channel needs to broadcast messages, it should not be aDirectChannelbut rather aPublishSubscribeChannel. Below you will see how each of these can be configured. (PS:由于 DirectChannel 的簡單性,使其無需增加任何額外的開銷即可提供調度以及管理線程輪詢,這是 Spring Integration 內部默認實現的channel。如果頂一個應用程序的channel,首先需要考慮的是 該channel是否需要提供隊列緩存功能,之后是是否需要提供基于優先級策略的PollableChannels, 如果你僅僅是為了實現消息廣播,則采用PublishSubscribeChannel是正確的選擇而不是DirectChannel。 如下將針對這些配置進行展開描述 ) |
TheDirectChannelinternally delegates to a Message Dispatcher to invoke its subscribed Message Handlers, and that dispatcher can have a load-balancing(負載均衡) strategy. The load-balancer determines how invocations(調用) will be ordered in the case that there are multiple handlers subscribed to the same channel. When using the namespace support described below, the default strategy is "round-robin"(輪詢) which essentially(本質上,基本的) load-balances across the handlers in rotation(輪流).
(PS:DirectChannel 可以充當消息分發的角色定位,并且該分發是基于負載均衡策略。負載均衡實現了對訂閱該通道 的消息訂閱者按照順序循環調用。其內部實現的默認策略是 循環 機制。這個是負載均衡的最基本的一種實現。 )
| The "round-robin" strategy is currently the only implementation available out-of-the-box(開箱即用) in Spring Integration. Other strategy implementations may be added in future versions. (PS:這種循環的負載均衡策略已經被 Spring Integration實現,它屬于開箱即用 的一種功能。其他的策略需要在以后的版本中加入) |
The load-balancer also works in combination with(與.....組 合) a boolean failover(故障轉 移) property. If the "failover" value is true (the default), then the dispatcher will fall back to(回滾到) any subsequent(隨后的) handlers as necessary when preceding(前面的) handlers throw Exceptions. The order is determined by an optional order value defined on the handlers themselves or, if no such value exists, the order in which the handlers are subscribed(訂閱).
(PS:負載均衡 常與 故障轉移 配合使用,對于DirectChannel的 failover 值,默認是 開啟的。當前一個訂閱者調用發生異常 分發器會回滾當前狀態到下一個訂閱者重新處理,其調用的順序是由handlers自身的 order 屬性決定。如果不存在這樣的值 則有訂閱者默認的順序決定。 )
If a certain(某些) situation requires that the dispatcher always try to invoke the first handler, then fallback in the same fixed order sequence every time an error occurs, no load-balancing strategy should be provided. In other words, the dispatcher still supports the failover boolean property even when no load-balancing is enabled. Without load-balancing, however, the invocation of handlers will always begin with the first according to their order. For example, this approach works well when there is a clear definition of primary, secondary, tertiary, and so on. When using the namespace support, the "order" attribute on any endpoint will determine that order.
(PS:假如在某一場景下需要分發器總是嘗試調用第一個 handler,發生異常 回滾也是采用固定的序列,不需要負 載均衡的策略支持。換句話說:分發器支持在關閉負載均衡的模式下仍舊對 failover 有效。因此,調用handlers順序總是 按照第一次排序的順序進行。例如 當清晰的定義了 第一 、第二 、第三 等順序,那么這種工作機制將會很好的運行)
| Keep in mind that load-balancing and failover only apply when a channel has more than one subscribed Message Handler. When using the namespace support, this means that more than one endpoint shares the same channel reference in(引用) the "input-channel" attribute. (PS:值得一提的是,無論是負載均衡 還是 故障轉移 應用的場景至少該通道多于一個訂閱者訂閱,當采用命名空間時, 這意味者至少一個以上的endpoint分享統一 channel 通過 input-channel 屬性。) |
ExecutorChannel
TheExecutorChannelis a point-to-point channel that supports the same dispatcher configuration asDirectChannel(load-balancing strategy and the failover boolean property). The key difference between these two dispatching channel types is that theExecutorChanneldelegates to an instance ofTaskExecutorto perform the dispatch. This means that the send method typically will not block, but it also means that the handler invocation may not occur in the sender's thread. It therefore does not support transactions spanning the sender and receiving handler.
(PS:ExecutorChannel 是 點對點 通道的實現,同時他支持 DirectChannel 的分發器特性,(負載均衡與故障轉移)。 兩者之間一個顯著的不同之處是 ExecutorChannel 內部是通用一個 TaskExecutor 實例實現的。這意味著調用該 通道的 send 方法不會發生阻塞,同時這將意味著 對handler的調用將不會與sender 公用統一線程, 該模式不支持事務,發送與接受分別受限與不同的線程 )
| Note that there are occasions(場合) where the sender may block. For example, when using a TaskExecutor with a rejection-policy(數量限制) that throttles(節 流) back on the client (such as theThreadPoolExecutor.CallerRunsPolicy), the sender's thread will execute the method directly anytime the thread pool is at its maximum capacity and the executor's work queue is full. Since that situation would only occur in a non-predictable way, that obviously(明顯) cannot be relied upon for(依 靠,依賴) transactions. (PS:注意在某些場合下,調用ExecutorChannel 的send 也有可能被阻塞。例如 ,當使用的 TaskExecutor 受管以一個數量限制的客戶端(線程池),當池中沒有可用的線程是,或者執行隊列 當前沒有空位是,則會被阻塞。因為這種情況的發生是不可預測的) |
Scoped Channel
Spring Integration 1.0 provided aThreadLocalChannelimplementation, but that has been removed as of 2.0. Now, there is a more general way for handling the same requirement(需求) by simply adding a "scope" attribute to a channel. The value of the attribute can be any name of a Scope that is available within the context. For example, in a web environment, certain(特定的,這里是指:session、request、goal等) Scopes are available, and any custom Scope implementations can be registered with the context. Here's an example of a ThreadLocal-based scope being applied to a channel, including the registration of the Scope itself.
(PS:在Spring Integration 1.0 版本中,提供了基于線程范圍的 ThreadLocalChannel實例,但是在2.0中被移除了。 現在提供一個更加通用的方法來滿足該需求,那就是通過 channel 的scope的屬性。該屬性的值可以是在Spring 容器中可被識別的任何值。例如在 web環境中,一些特定的Scope 是可用的。 并且這些都已經被注冊到Spring 容器中。如下的代碼 展示了 基于線程 范圍生命周期的配置,包括這側 線程Scope 到Srping容器)
<int:channel id="threadScopedChannel" scope="thread"><int:queue /></int:channel><bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"><property name="scopes"><map><entry key="thread" value="org.springframework.context.support.SimpleThreadScope" /></map></property></bean>The channel above also delegates to a queue internally, but the channel is bound to(綁定) the current thread, so the contents of the queue are as well. That way the thread that sends to the channel will later be able to receive those same Messages, but no other thread would be able to access them. While thread-scoped channels are rarely(很少,極少) needed, they can be useful in situations(場景) whereDirectChannelsare being used to enforce(執行) a single thread of operation but any reply Messages should be sent to a "terminal" channel. If that terminal channel is thread-scoped, the original sending thread can collect its replies from it.
(PS : 上述的channel 同時作用于其內部的隊列。由于channel 綁定了當前的工作線程,所以其內部隊列同樣被作用。 這樣線程不經可以發送,還可以接受這些消息。當時其他線程是無法訪問該channel的。事實上,基于thread-scoped 的channle 很少被用到。一個比較有用的場景是 當通過 DirectChannels 在單線程下執行一個消息發送后任何響應的消息 可以發送到這個終端的 channel 中。如果這個channel 是基于 thread-scoped,那么原先的發送線程可以通過他獲取任何響應的消息)
轉載于:https://my.oschina.net/qfhxj/blog/95369
總結
以上是生活随笔為你收集整理的#翻译NO.5# --- Spring Integration Framework的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 敏捷嘉年华——敏捷之旅2012(上海站)
- 下一篇: 辞职啦!