4

Atmosphere ランタイム 0.6 スナップショットを使用しています。Tomcat 7 は、Http11 Nio コネクタを使用していることを正しく記録しており、BlockingIO が使用されるという警告はありません。

3 種類のチャネルにメッセージを送信しようとしています。

  1. グローバル ブロードキャスター - 中断されたすべてのリソースにブロードキャストします。(全て)
  2. 特定のリソース (パートナーなど) にブロードキャストする
  3. 現在のリソースにブロードキャスト (自己)

ログイン アクションが発生したときに、この種のブロードキャストを実現するには、セッションに何を保存する必要がありますか?

私のコードの詳細は次のとおりです。

  1. 私のハンドラーは AtmosphereHandler を実装します
  2. コンストラクターで、globalBroadcaster を次のようにインスタンス化します。

    globalBroadcaster = new DefaultBroadcaster();

  3. ログインすると、

    resource.getAtmosphereConfig().getServletContext().setAttribute(name, selfBroadcaster); ここで、name はリクエスト パラメーターのユーザー名で、selfBroadcaster は DefaultBroadcaster の新しいインスタンスです。

  4. sendMessageToPartner のコードは次のとおりです。

private synchronized void sendMessageToPartner(Broadcaster selfBroadcaster, AtmosphereResource<HttpServletRequest, HttpServletResponse> resource,String name, String message) {
// this gives the partner's name
String partner= (String) resource.getAtmosphereConfig().getServletContext().getAttribute(name + PARTNER_NAME_TOKEN);
// get partner's broadcaster
Broadcaster outsiderBroadcaster = (Broadcaster) resource
.getAtmosphereConfig().getServletContext()
.getAttribute(partner);
if (outsiderBroadcaster == null) {
sendMessage(selfBroadcaster, "Invalid user " + partner);
return;
}
// broadcast to partner
outsiderBroadcaster.broadcast(" **" + message);

必要な情報をすべて提供したことを願っています。必要に応じて、さらに情報を提供できます。

問題は、グローバル メッセージが送信されることです。パートナーへのメッセージが送信されると、ブロックされる場合があり、メッセージはクライアントでまったく受信されません。これは、3 ~ 4 件のメッセージの後に一貫して発生します。

スレッドの問題はありますか?私は何を間違っていますか?

誰かがこれで私を助けてくれることを願っています。

4

1 に答える 1

6

OK、Atmosphereランタイムでこれをどのように達成できるかを理解しました。まず、0.7 SNAPSHOTにアップグレードしましたが、同じロジックが0.6でも機能すると思います。

したがって、シングルユーザー用のブロードキャスターを作成するには:

GETリクエストでは、

  // Use one Broadcaster per AtmosphereResource             
try {       
atmoResource.setBroadcaster(BroadcasterFactory.getDefault().get());     

} catch (Throwable t) {
                throw new IOException(t);
            }

            // Create a Broadcaster based on this session id.
            selfBroadcaster = atmoResource.getBroadcaster();
            // add to the selfBroadcaster
            selfBroadcaster.addAtmosphereResource(atmoResource);

            atmoResource.suspend();   

ログインアクションが呼び出されると、

//Get this broadcaster from session and add it to BroadcasterFactory.

Broadcaster selfBroadcaster = (Broadcaster) session.getAttribute(sessionId);

BroadcasterFactory.getDefault().add(selfBroadcaster, name);

Now the global broadcaster. The logic here is, you create a broadcaster from the first resource and then add each resource as they log in.

Broadcaster globalBroadcaster;

globalBroadcaster = BroadcasterFactory.getDefault().lookup(DefaultBroadcaster.class, GLOBAL_TOKEN, false);
                if (globalBroadcaster == null) {
                  globalBroadcaster = selfBroadcaster;

                    } else {
                        BroadcasterFactory.getDefault().remove(
                                globalBroadcaster, GLOBAL_TOKEN);
                        AtmosphereResource r = (AtmosphereResource) session
                                .getAttribute("atmoResource");
                        globalBroadcaster.addAtmosphereResource(r);

                    }
                    BroadcasterFactory.getDefault().add(globalBroadcaster,
                            GLOBAL_TOKEN);

最後に、次のように、単一接続またはグローバルにすべての接続にブロードキャストできます。

// Single Connection/Session
Broadcaster singleBroadcaster= BroadcasterFactory.getDefault().lookup(
                            DefaultBroadcaster.class, name);
singleBroadcaster.broadcast("Only for you");

// Global 
Broadcaster globalBroadcaster = BroadcasterFactory.getDefault().lookup(DefaultBroadcaster.class,GLOBAL_TOKEN, false);
globalBroadcaster.broadcast("Global message to all");

パートナーにメッセージを送信するには、パートナーのブロードキャスターを検索し、単一接続について上記と同じようにします。

これが同じことを達成しようとする人に役立つことを願っています。これを行うためのより良い方法があるかもしれません。誰かがより良い解決策を提案するまで、私はこのアプローチを使わなければならないと思います。

于 2010-12-30T12:10:26.870 に答える