2010-01-10 76 views
3

我正在使用Google AppEngine,與PyAMF一起提供RemoteObject支持。在我的Flex代碼中,我一次創建了多個RemoteObject方法調用,這往往會將AMF消息批量化爲單個HTTP請求。如何防止RemoteObject將AMF消息集中在一起?

大多數情況下,這很好,但AppEngine會對每個請求限制應用一些嚴格的限制(在這種情況下,我正在觸發DeadlineExceededError - 最多30秒)。預計許多服務方法需要10秒以上的時間,並且如果這些方法通過RemoteObject分配到1個HTTP中,您可以看到這是怎麼回事。

現在你可以說重構你的服務調用,這也正在進行,但不是真的在這裏問的問題。有沒有辦法阻止Flex RemoteObject對這種情況的AMF請求進行批處理?

我已經做了相當多的谷歌搜索這個問題,並拿出bupkis。在我看來,我需要實現一個自定義版本mx.messaging.channels.AMFChannel或這種性質的東西,這似乎太硬核這樣的功能..

任何人有任何指針/見解?

回答

1

檢查RemoteObject上的concurrency property

+0

看着這些文檔(並糾正我,如果我錯了)我的問題似乎有微妙的不同 - 我想確保通過RemoteObject發送的每個AMF消息發送一個HTTP請求(並且能夠無誤地進行多個呼叫)。 我挖通過Flex SDK,它似乎沒有看到Messaging RPC正在批量請求,這導致我認爲它發生在底層NetConnection中? – njoyce

+2

是的。你是對的。 Flash Player等待幀結束以發送所有排隊的網絡請求。如果您將每個請求移動到不同的框架上(如使用callLater),那麼它將確保每個請求實際使用不同的HTTP網絡請求。 –

+0

謝謝!這些信息足以讓我能夠將我的電話放入隊列並相應地錯開。 – njoyce

0

您可以創建一個連接池,並創建另一個觸發連接的類。您的應用程序不會建立連接,只會提供池。

+0

你能舉一個這個樣子的例子嗎?我是一個n00b當涉及到Flex .. – njoyce

0

我認爲njoyce喜歡做的是防止AMF配料。這就是說。適用於多個小型呼叫,但如果您的服務器密集型呼叫非常繁忙,則應避免AMF批處理。爲什麼?在服務器端

  • 一個AMF呼叫=>一個線程
  • 多個AMF調用=>所有的請求獲得通過多線程處理

僞代碼:

private static var _collectionFillIndex:int; 
    private static var _collectionsToFill:Array = []; 

    public function doFillCollections():void { 
     _collectionFillIndex = _collectionsToFill.length; 
     Application.application.addEventListener(Event.ENTER_FRAME, onFrameEventHandler); 
    } 

    private function onFrameEventHandler(event:Event):void { 
     --_collectionFillIndex; 
     if(_collectionFillIndex < 0) { 
      Application.application.removeEventListener(Event.ENTER_FRAME, onFrameEventHandler); 
      return; 
     } 
     _collectionsToFill[ _managerFillIndex ].fill(); 
    } 
1

的配料AMF對HTTP的請求發生在NetConnection級別。所以不幸的是,停止批量處理AMF請求的最好方法是實現mx.messaging.channels.AMFChannel的定製版本。然而,這很容易做到,並且可能更容易排隊請求並稍後調用它們。

不使用默認的AMFChannel改用如下:

package services 
{ 
    import flash.events.AsyncErrorEvent; 
    import flash.events.IOErrorEvent; 
    import flash.events.NetStatusEvent; 
    import flash.events.SecurityErrorEvent; 
    import flash.net.NetConnection; 

    import mx.messaging.MessageResponder; 
    import mx.messaging.channels.AMFChannel; 

    public class NonBatchingAMFChannel extends mx.messaging.channels.AMFChannel 
    { 
     public function NonBatchingAMFChannel(id:String = null, uri:String = null) 
     { 
      super(id, uri); 
     } 

     override protected function internalSend(msgResp:MessageResponder):void 
     { 
      // AMFChannel internalSend 
      super.internalSend(msgResp); 
      // Reset the net connection. 
      _nc = new NetConnection(); 
      _nc.addEventListener(NetStatusEvent.NET_STATUS, statusHandler); 
      _nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); 
      _nc.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); 
      _nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler); 
      _nc.connect(this.url); 
     } 
    } 
} 

,奇蹟發生了通過覆蓋internalSend方法。在運行super internalSend方法(將消息響應者排隊)之後,我們將重置NetConnection及其所有事件處理程序。這爲新的NetConnection準備好了下一個遠程消息。

注意: 需要注意的是,這是一個自定義非批處理AMFChannel,如果您想要安全地發送AMF消息,則需要複製此類並擴展mx.messaging.channels.SecureAMFChannel類。

Credit: 感謝Nick Joyce,他在另一個論壇上回答了他的問題。