2013-07-31 56 views
2

我正在進行空中預訂項目。在處理無冪等性調用時,我應該使用事件設計嗎?

下圖顯示了我們到目前爲止開發域模型。

enter image description here

我們定義域服務(AirBookService),它封裝了預訂,票務等業務。我們的供應商提供Remote-Procedure-Call API來處理這些請求,所以我們通過添加一個反腐敗層(我們有多個供應商)來實施域服務。與imdenpotent RPC調用,例如獲取價格打交道時

這個解決方案正常工作。但是,在處理非imdenpotent rpc呼叫時存在風險。

例如

public class TransactionalReservationHandlingServiceImpl .... { 
    @Transactional 
    @Override 
    public void modifyTraveler(String resId, String tktId, AirTravler traveler) { 
     AirReservation res = reservationRepository.findBy(resId); 
     res.modify(tktId, traveler); 
     airBookService.modify(res, traveler); 
     reservationRepository.store(res); 
    } 
} 

我把airBookService.modify()後面res.modify(),因此,如果一些本地域邏輯是破碎可以避免RPC調用。但是,如果rpc調用成功並且本地事務失敗會怎麼樣?我們的應用程序中的旅行者與供應商的應用程序之間有差異。

是否值得在處理單獨交易的RPC調用和局部修改?

我擔心的是:

 
a) It will surely introduce some extra complexity if doing so. like messaging. 
b) I don' have much experience in event handling. 
c) The failure chances are very low even if we use rpc call in the transaction boundary, mostly caused by concurrency problem and contetion of AirReservation is relatively low in real world. 

下面是我的事件的嘗試:

@Transactional 
    @Override 
    public void modifyTraveler(String resId, String tktId, AirTravler traveler) { 
     AirReservation res = reservationRepository.findBy(resId); 
     ModifyTravelerEvent event = airBookService.modify(res, traveler); 
     handlingEventRepository.store(event); 
     events.notifyTravelerModified(event);// using messaging 
    } 

    @Transactional 
    @Override 
    public void modifyTraveler(String eventSequence) { 
     ModifyTravelerEvent event = handlingEventRepository.of(eventSequence); 
     AirReservation res = reservationRepository.findBy(resId); 
     event.handle(res); 
     reservationRepository.store(res); 
     handlingEventRepository.store(event); 
    } 

的好處是局部修改從RPC調用分隔。 但這介紹: 1.Multiple資源管理問題(數據源和消息) 2.我必須創造一個修改旅客需求票和任何其他AirBookService操作很多特設的事件。

我左右爲難,不滿意目前的設計但隨着新事件的設計相當猶豫。

任何想法表示讚賞,在此先感謝。

回答

0

在您的第一個示例中,您將本地修改與遠程修改混合使用。您擔心,如果您的本地修改在遠程修改成功後失敗,則無法再回滾遠程修改。所以,解開你的兩個修改肯定是要走的路。

這樣做將是交換線airBookService.modify呼叫和呼叫reservationRepository.store最簡單的方法:

public class TransactionalReservationHandlingServiceImpl .... { 
    @Transactional 
    @Override 
    public void modifyTraveler(String resId, String tktId, AirTravler traveler) { 
     // local modification 
     AirReservation res = reservationRepository.findBy(resId); 
     res.modify(tktId, traveler); 
     reservationRepository.store(res); // <- remember this should not actually store anything until after the commit 

     // remote modification 
     airBookService.modify(res, traveler); 
    } 
} 

因爲你的局部修改是事務性的,只將一個成功的遠程修改後提交。可能發生的任何類型的本地問題都可能已經發生。當然,交易本身失敗的可能性依然很小。因此,爲了確保事務性,您必須能夠回滾您的遠程修改。因爲,我認爲,你無法這樣做,真正的事務性實際上是不可能的。因此,就一致性而言,上述構造在同時進行本地和遠程修改方面是最安全的方式,因爲本地修改本身失敗的可能性是微不足道的。我這樣說,因爲即使您要引入消息傳遞,在遠程修改後仍然沒有提交消息本身的可能性仍然很小。

但是,上述構造確實存在一個大問題:它可能會嚴重影響性能(您不希望交易時間過長)。消息傳遞對於這個問題是一個非常合理的解決方案。它還具有其他優點,如持久性,審覈和重播消息。因此,您的消息傳遞嘗試在這方面是非常合法的。但是,您的代碼會嚴重破壞單個責任規則,因爲消息本身與相同方法調用中的修改混在一起。

如果你關心的消息太多的樣板你應該檢查出akka.io. Spring JMS和ActiveMQ也是一個非常強大的組合,如果你不是在尋找一個完整的範式轉換,而只是一個體面的消息解決方案。使用這兩種技術中的一種,我建議你可以爲本地調用創建一個強大的框架,並與遠程調用進行配對,從而避免使用大量的樣板。

我希望這會有所幫助。祝你好運!

相關問題