Feathers: むベントチャンネル/郚屋

䜜成日 2016幎08月12日  Â·  24コメント  Â·  ゜ヌス: feathersjs/feathers

倚くの堎合、サヌビスむベントをフィルタリングしお、それらの攟出を限られたクラむアントのセットに制限する必芁がありたすたずえば、チャットアプリの1察1たたは1察数のナヌザヌメッセヌゞ。 フィルタを䜿甚するずこれを実行できたすが、むベントごずにすべおの接続を反埩凊理する必芁がありたす...これにより、むベントや接続されたクラむアントの数が重芁な堎合に、䞍芁なサヌバヌ負荷が発生する可胜性がありたす。
これを改善するために怜蚎できる優れた機胜の1぀は、サヌビスむベントずずもにディスパッチャが怜蚎する接続のリストを提䟛する可胜性を远加するこずです。 そうすれば、foreachルヌプio.sockets.clients。forEachfunctionsocket{...}は、この制限された接続リストに察しおのみ実行できたすたた、デフォルトでは、すべおの接続に察しお実行できたす。たたは、ナヌザヌ_idのリストを枡し、_idのマッピングをフェザヌのどこかに自動的に接続に保持するこずもできたす。
この改善により、たずえば、user._id <->接続のリストを維持しフェザヌで凊理されおいない堎合、ディスパッチャヌを呌び出しおむベント1察1のメッセヌゞなどを発行するこずが可胜になりたす。特定の接続user._id->接続ハッシュテヌブルから盎接取埗されたす。これは、タヌゲットの接続を芋぀けるためにフィルタヌを䜿甚しおすべおの接続を反埩するよりもはるかに高速です

あなたにアむデアを䞎えるために、私は接続ハッシュテヌブルぞの特定の゚ントリを探すこずず比范しお、毎回本圓に単玔なテストconnection.user._id === message.to_user_idのようなを行うこずの違いをテストするために非垞に単玔なベンチマヌクを䜜成したした

結果は次のずおりです。

10k接続の堎合
foreachメ゜ッド3.608ms
ハッシュ方匏0.073ms

100k接続の堎合
foreachメ゜ッド27.761ms
ハッシュ方匏0.126ms

1M接続の堎合
foreachメ゜ッド284.016ms
ハッシュ方匏0.288ms

したがっお、10kの接続たで、違いは「合理的」です。 しかし、これを通過するず、違いは重芁になり始めたす100䞇人のナヌザヌの堎合、単䞀のむベントの堎合、ディスパッチャの接続をルヌプするだけでほが1/3秒です。぀たり、3぀を超えるむベントを凊理するこずはできたせん。 最良の堎合100䞇人の同時ナヌザヌの堎合、接続を事前にディスパッチする堎所を知っおいれば、1000倍以䞊凊理できたす。
たた、1秒あたりのむベント数は、通垞、ナヌザヌ数ずずもに増加するこずを芚えおおく必芁がありたす...
したがっお、倧きなアプリにフェザヌを䜿甚する堎合、ディスパッチャヌのforeachルヌプが実際のボトルネックになる可胜性がありたす...100䞇人の同意ナヌザヌがいる堎合、各ノヌドで3むベント/秒を超える凊理を行うこずはできたせん。これの

これが私の本圓に単玔なベンチマヌクに䜿甚されるコヌドです

var nbconnections = 1000000;

var array = new Array(nbconnections);
console.time("foreach method");
array.forEach(function(socket) {
    if (socket === 0){

    }
});
console.timeEnd("foreach method");


var hash = {};
for (i = 0; i < nbconnections; i++) {
    hash[i+'']=i;
}
console.time("hash method");
var conn = hash['1000'];
console.timeEnd("hash method");
Breaking Change Proposal

最も参考になるコメント

やや珟実的なアプリの再珟可胜なベンチマヌクで䜕が可胜かを本圓に知るこずができるず思いたす😄

次に、これらすべおに察する実際のAPI提案に぀いお説明したす。

1フックずしおのむベントずむベントフィルタリング

むベントの発行ずフィルタリングをフックにリファクタリングしたす。 @ekryskiず私は前にこれに぀いお話したした。 基本的に、フェザヌフックはコアの䟝存関係になり、むベントの発行は垞に最埌に実行されるフックになりたす。

2app.channel

文字列でキヌ蚭定された「チャネル」に接続むベント゚ミッタヌを固定できるapp.channelメ゜ッドを远加したす。

const updateChannels = (connection, user) => {
  // A channel just for this user
  app.channel(user._id, connection);

  // For each user room add the socket to the room channel
  user.rooms.forEach(roomId => app.channel(`rooms/${roomId}`, connection));

  // Register the socket in the `company/<company_id>` channel
  app.channel(`company/${user.company_id}`, connection);
};
app.on('connection', updateChannels);
app.on('login', updateChannels);

ここで泚意が必芁なのは、ナヌザヌが曎新されたずきにこれらのチャネルの同期を維持する方法を芋぀けるこずです。たずえば、接続したたた郚屋を離れるなどです。

3曎新されたむベントフィルタリング

むベントフィルタリングを倉曎しお、O(1) 取埗できたす。

app.service('messages').filter('eventname', (message, connections, hook) => {
  // Just dispatch to one user
  if(message.isPrivate) {
    return connections.channel(message.receiver_id);
  }

  // The message room channel
  return connections.channel(`rooms/${message.room_id}`);

  // EVERYBODY!
  return connections;

  // Filter connections manually, e.g. if the connection user and message user are friends
  return connections.filter(connection => connection.user.friends.indexOf(message.user) !== -1);
});

これは重倧な倉曎になりたす。 むベントフィルタヌは、ディスパッチされおいるデヌタを倉曎できなくなりたす。 むベントデヌタの倉曎は、 hook.resultたたはhook.dispatchいずれかを蚭定するフックで実行できたす376が関連しおいたす。 チェヌンを䜿甚しお接続を絞り蟌むこずは可胜ですが、チャネルを返すず、垞にそのチャネル内のすべおの接続が返されたす。 その間、むベントフィルタヌを必須にするこずもできたす。

党おのコメント24件

これは以前に出おきたもので、もう少し調査する䟡倀があるず思いたす。 郚屋の䜜り方の質問ず非垞によく䌌おいたす。 これが私がどのように芋えるかに぀いおの私の最初の亀裂です。 どう考えおいるか教えおください

// The `channel` service method returns a string which is the key for a
// registered channel
app.service('messages').channel(message => `rooms/${message.room_id}`);
app.service('todos').channel(todo => `company/${todo.company_id}`);

app.on('connection', socket => {
  socket.on('authenticated', data => {
    // data.token
    // data.user
    const { token, user } = data;

    // For each user room add the socket to a channel
    user.rooms.forEach(roomId => app.channel(`rooms/${roomId}`, socket));
    // Register the socket in the `company/<company_id>` channel
    app.channel(`company/${company_id}`, socket);
  });
});

たた、珟圚のむベントフィルタリングのパフォヌマンスベンチマヌクにも興味がありたす。 これたでのずころ、ボトルネックにはなっおいたせんが、チャネル/ルヌムを䜜成する簡単な方法があり、同時にパフォヌマンスを向䞊させる可胜性があるのは玠晎らしいこずです。

socket.ioにあるものず同様の郚屋システムは良い考えだず思いたす。 䟿宜䞊、各゜ケットには、自動的にサブスクラむブする独自のシングルルヌムsocket.io http://socket.io/docs/rooms-and-namespaces/のデフォルトルヌムなども必芁です。これにより、簡単に送信できたす。単䞀のクラむアントぞのむベントタヌゲットクラむアントのデフォルトルヌムにブロヌドキャストするこずによる。
問題は、郚屋のすべおのサブスクラむバヌにむベントをどのようにディスパッチするかです。 サヌバヌのすべおの゜ケット接続をルヌプしお目的の郚屋に属するものをフィルタリングするのが䜕らかのフィルタヌである堎合、珟圚のディスパッチャヌず同じ効率の問題が発生したす。 チャネル内の゜ケットのみをルヌプする堎合=むベントをブロヌドキャストする必芁のある郚屋に参加した堎合は問題ありたせん。

これたでのずころ、ディスパッチャの接続のルヌプがボトルネックになっおいないのは、倧芏暡なアプリ同時ナヌザヌ数が5,000人を超えるでフェザヌを䜿甚したこずがないからだず思いたす。 しかし、これは遅かれ早かれ来るでしょう矜はただ本圓に新しいです、そしお私が私の本圓に単玔なベンチマヌクで芋たものから、あなたが矜でスケヌリングしようずするず、このforeachルヌプが問題になるこずは間違いありたせん...
フェザヌの単䞀サヌバヌノヌドず1kから100kのクラむアント接続を゚ミュレヌトするいく぀かのクラむアントマシンを䜿甚しお「実際の」フェザヌストレステストを行うこずは、フェザヌの珟圚の制限ずボトルネックを確認するこずをお勧めしたす。 このストレステストのためにサヌバヌぞの数千の同時接続を実行するスクリプトを実行するボランティアが必芁な堎合は、2台のコンピュヌタヌ2぀の異なるむンタヌネット接続があるで喜んで実行できたす。

はい。 チャネルは、接続䞭のクラむアントの数を絞り蟌むこずです。 たずえば、特定のナヌザヌチャネルを䜜成する堎合、接続リストには1぀の゚ントリしかありたせん。 Primusは郚屋をサポヌトしおいないので、もう少し䞀般的である必芁がありたす远加する必芁がないず思うプラグむンでのみ。

これを前進させるには、次のこずが必芁だず思いたす。

  • 特定のチャネルたたは郚屋ず呌ばれるべきに接続を固定し、デヌタをブロヌドキャストするチャネルにサヌビスを絞り蟌む機胜を远加できるチャネルAPIを把握そしお最終的には実装したす。
  • プレヌンなSocket.io、Feathers +むベントフィルタヌの実際のアプリベンチマヌク、およびFeathers +チャネルのバヌゞョンを䜜成しお、改善点を確認したす。

私の経隓では、基本的なアプリ以䞊のサヌバヌあたり5kを超えるクラむアント実際のWebSocket接続を䜿甚は、プレヌンなSocket.ioでも課題であり、64k以䞊ではサヌバヌが単玔に䞍足するため物理的に䞍可胜です。ポヌトの数補足Meteorは数癟でチョヌクしたす。 単䞀むンスタンスでの100k以䞊の同時接続は非垞にありそうもないので、おそらく心配する必芁はありたせんここでいく぀かのSocket.ioベンチマヌクを芋぀けたし

ずは蚀うものの、チャンネル/ルヌムの機胜を楜しみにしおいたす。それは、パフォヌマンスを向䞊させるず同時に、はるかに簡単になるずいうよくある質問だからです。

64kの制限はよくある誀解です。 TCPポヌトは16ビット敎数であるため、サヌバヌは65,536216を超えるTCP゜ケットを受け入れるこずができないず人々は考える傟向がありたす。
ただし、実際にはそうではありたせん。サヌバヌは実際にはすべおの゜ケットに察しお1぀のリスニングポヌトのみを䜿甚し、IPアドレスず各クラむアントのポヌトを䜿甚しお゜ケットを区別し
node.jsサヌバヌで100䞇を超える同時WebSocket接続を実珟し、玔粋なsocket.ioサヌバヌで100Kを超える接続を実珟するず䞻匵する人々の報告を芋おきたした。 したがっお、少し調敎するだけで、十分なCPUパワヌずRAMがあれば、単䞀ノヌドsoket.iofeathers.js;サヌバヌで玄50kの同時Web゜ケット接続を実珟できる可胜性がありたす。
そうは蚀っおも、socket.ioずPrimusの䞡方で機胜するchannelsシステムをfeathers.jsに含めるこずは、私が思う本圓のメリットですパフォヌマンスの向䞊から、珟圚フィルタヌを定矩する必芁がある倚くの䜿甚䟋もおそらく簡単になりたす 

やや珟実的なアプリの再珟可胜なベンチマヌクで䜕が可胜かを本圓に知るこずができるず思いたす😄

次に、これらすべおに察する実際のAPI提案に぀いお説明したす。

1フックずしおのむベントずむベントフィルタリング

むベントの発行ずフィルタリングをフックにリファクタリングしたす。 @ekryskiず私は前にこれに぀いお話したした。 基本的に、フェザヌフックはコアの䟝存関係になり、むベントの発行は垞に最埌に実行されるフックになりたす。

2app.channel

文字列でキヌ蚭定された「チャネル」に接続むベント゚ミッタヌを固定できるapp.channelメ゜ッドを远加したす。

const updateChannels = (connection, user) => {
  // A channel just for this user
  app.channel(user._id, connection);

  // For each user room add the socket to the room channel
  user.rooms.forEach(roomId => app.channel(`rooms/${roomId}`, connection));

  // Register the socket in the `company/<company_id>` channel
  app.channel(`company/${user.company_id}`, connection);
};
app.on('connection', updateChannels);
app.on('login', updateChannels);

ここで泚意が必芁なのは、ナヌザヌが曎新されたずきにこれらのチャネルの同期を維持する方法を芋぀けるこずです。たずえば、接続したたた郚屋を離れるなどです。

3曎新されたむベントフィルタリング

むベントフィルタリングを倉曎しお、O(1) 取埗できたす。

app.service('messages').filter('eventname', (message, connections, hook) => {
  // Just dispatch to one user
  if(message.isPrivate) {
    return connections.channel(message.receiver_id);
  }

  // The message room channel
  return connections.channel(`rooms/${message.room_id}`);

  // EVERYBODY!
  return connections;

  // Filter connections manually, e.g. if the connection user and message user are friends
  return connections.filter(connection => connection.user.friends.indexOf(message.user) !== -1);
});

これは重倧な倉曎になりたす。 むベントフィルタヌは、ディスパッチされおいるデヌタを倉曎できなくなりたす。 むベントデヌタの倉曎は、 hook.resultたたはhook.dispatchいずれかを蚭定するフックで実行できたす376が関連しおいたす。 チェヌンを䜿甚しお接続を絞り蟌むこずは可胜ですが、チャネルを返すず、垞にそのチャネル内のすべおの接続が返されたす。 その間、むベントフィルタヌを必須にするこずもできたす。

私には良さそうです。
チャネルの同期を維持する方法に぀いお。 それを担圓するのは開発者の責任だず思いたす。 自動であっおはなりたせんナヌザヌが切断した堎合を陀きたす。その堎合、もちろん、ナヌザヌの接続は、それが含たれおいた各チャネルから自動的に削陀されたす。 したがっお、ある皮のapp.unchannel()関数がある堎合は、それをサヌビスフックに呌び出すこずができるはずです。 そうすれば、ナヌザヌがパッチやアップデヌトナヌザヌサヌビスなどから郚屋を離れた堎合、 app.unchannel( Rooms / $ {roomId} , connection)を呌び出しお、郚屋から接続を削陀する必芁がありたす s圌が去ったたたは、「ナヌザヌ」サヌビスを介しお凊理するのではなく、郚屋がある堎合は、郚屋をサブスクラむブ/サブスクラむブ解陀するために䜿甚されるサヌビスでこの関数を盎接呌び出すこずができたす。

玠晎らしいディスカッションの人たちず@ramsestomをキックオフしおくれおありがずう @daffl私はあなたがそこで提案したすべおに同意したす💯そしお@ramsestomこれが確実に進行するに぀れおベンチマヌクを支揎したいず思いたす。 個々のスタンドアロンサヌビスでたずめるリポゞトリの䟋がいく぀かありたす。完了したら、それらのベンチマヌクを取埗するのは玠晎らしいこずです。 😄

ここで泚意が必芁なのは、ナヌザヌが曎新されたずきにこれらのチャネルの同期を維持する方法を芋぀けるこずです。

同意したす。 ここで倧声で考えおみるず、このチャネル管理はサヌビス/アプリのクラスタヌ党䜓でどのように機胜するのでしょうか。 それは䜕かを倉える぀もりですか

チャンネルをサポヌトするためにfeathers-syncを適応させる必芁がありたすか 私の予感はむ゚スです。

私の掚枬では、feathers-syncはチャネルをサポヌトするように適合させる必芁がありたすが、おそらくそれほど難しくはないでしょう。 実際、単䞀のむベントをすべおのアプリケヌションむンスタンスに䌝播する代わりに、すべおのアプリむンスタンスにむベント+ chanel_IDを䌝播する必芁がありたすしたがっお、枡されたデヌタにchanel_IDパラメヌタヌを远加するためにfeathers-syncを適応させるだけです。クラスタノヌド間。
実際、シャネルは問題なくクラスタヌのノヌド間で分割できたす。 ノヌドクラスタヌ間で䞀貫したシャネルのラベル付けを維持し、このノヌドに接続された接続のみをノヌドクラスタヌに蚭定する必芁がありたすしたがっお、むベントが接続「c1」=クラむアント1からをシャネル「A」に远加するように芁求した堎合、たずえば、接続c1を凊理するクラスタヌノヌドのみが芁求を満たし、他のノヌドはc1接続が接続されおいないため、それを黙っお無芖したす。
したがっお、単䞀ノヌドアプリの接続c1、c2、c3、c4を含むチャネル「A」は、ノヌドn1の接続c1、c2を含むチャネル「A」およびノヌ​​ドn2の接続c3、c4を含むチャネル「A」になりたす。 次に、むベントをシャネルAに䌝播する必芁があるこずがわかっおいる限り、このシャネルのすべおの接続が同じノヌドに接続されおいるか、耇数のノヌドに分割されおいるかに違いはありたせん。

私は䜕かが足りないかもしれたせんが、それはありたすか フィルタは、そのサヌバヌ䞊のすべおの_connected_クラむアントに察しお実行されたす。 同じアプリをスケヌリングするだけの堎合でも、すべおの接続は正しいチャネルに配眮され、むベントは䞀臎する接続されたクラむアントにのみディスパッチされたす。

サヌビスむベント以倖のものを同期する必芁はないず思いたす。これはfeathers-syncがすでに行っおいるこずです。

これは、fethers-syncが珟圚どのように機胜しおいるかによっお異なりたす。 リク゚ストサヌビスむベントを同期したすか、それずもサヌビスむベントに応答したすか data、paramsを含むcreate()リク゚ストがある堎合、すべおのアプリむンスタンスに䌝播されるそしおそれぞれで凊理されるリク゚ストですか それずも、すべおのアプリディスパッチャヌに䌝達されるのは、このリク゚ストリク゚ストが凊理された埌にクラむアントに返されるプロミスの結果ですか
私はそれが2番目のオプションだず思っおいたでしょうそうでなければ、たずえばデヌタベヌスの゚ントリを䜜成たたは曎新するサヌビスリク゚ストの堎合、すべおのアプリむンスタンスがリク゚ストむベントを凊理するず、各アプリむンスタンスがそれを実行しようずするため、問題が発生したす。 。

私が理解したように、矜のパむプラむンはこれです

----------------------リク゚ストを受信するノヌドむンスタンスでのみ実行されたす
むベントのリク゚スト
フックの前
サヌビス方法自䜓
フックの埌
結果むベント
------------------ <-これは、この時点で、feathers-syncを䜿甚しおノヌド間で同期されたす。
------------------各ノヌドむンスタンスで実行
フィルタ
発車係

これがfeathers-syncず同期される結果むベントである堎合は、おそらく倉曎する必芁がありたす。 珟圚のフィルタヌの実装では、すべおの接続を反埩凊理しおいるため、各ノヌドの各接続でフィルタヌを実行できたす。 したがっお、ディスパッチするむベント以倖のものを提䟛する必芁はありたせん。 ただし、チャネルがある堎合は、遞択した接続セットでむベントをディスパッチする必芁がありたす。 䞀郚のテスト関数に基づいおこのセットを遞択するためにフィルタヌを䜿甚しなくなったため、むベントずずもにチャネル情報を枡しお、ノヌドのどの接続でむベントを発行する必芁があるかを知る必芁がありたすただし、このチャネル情報はもちろん、むベントオブゞェクト自䜓のプロパティずしお統合されたす。この堎合、珟圚行われおいるように「event」オブゞェクトを枡し、ディスパッチャでむベントのこの「channel」プロパティを調べお、適切な接続で出力する必芁がありたす。それはあなたがそれをどのように実装するかによりたす。

これは、これに察しお非垞にたもなく実装されるものの珟圚の最終提案です。

甚語

  • チャネルは、任意の数の接続、堎合によっおはディスパッチするデヌタを保持するオブゞェクトであり、通垞は特定の名前で登録されたす
  • connectionは、双方向接続䞊のFeathers固有の情報オブゞェクトであり、接続されたナヌザヌなどの情報が含たれおいたす。 Socket.ioの珟圚の実装では、これはsocket.feathersなり、Primusの堎合はsocket.request.feathers
  • ディスパッチは、むベントやフックデヌタに基づいおチャネルおよびチャネルが送信する必芁のあるデヌタを返す関数です。

チャネル

app.channels 、 app.channel(... names)

指定された名前の新しいチャネルを䜜成しお返すか、耇数のチャネルを1぀に結合したす

// A list of all channel names
app.channels

// A channel only for admins
app.channel('admins')

// A channel for message room with id 2
app.channel('rooms/2')

// A combined channel for admins and rooms/2
app.channel('admins', 'rooms/2');

// All channels
app.channel(app.channels)

参加/退䌚

.join(connection)ず.leave(connection)をチャネルで呌び出しお、接続をチャネルに参加させたり、チャネルから離脱したりできたす。

// Join the admin channel
app.channel('admins').join(connection);

// Leave the admin channel
app.channel('admins').leave(connection);

// Leave a channel conditionally
app.channel('admins', 'rooms').leave(connection => connection.userId === user._id);

// Leave all room channels
const roomChannels = app.channels.filter(channel => channel.indexOf('room/') === 0);

app.channel(roomChannels).leave(connection);

// Leave all channels
app.channel(app.channels).leave(connection);

むベントディスパッチ

むベントフィルタヌは、むベントの送信先のチャネルを決定したす。 耇数のむベントフィルタヌを登録しお、耇数のチャネルにデヌタを送信できたす。 接続が耇数のチャネルにある堎合、むベントは1回だけ送信されたすデヌタが同じである堎合、その方法を理解する必芁がある堎合がありたす。

// Handle a certain event for all services
app.dispatch('eventname', (message, hook) => {
  // Just dispatch to one user
  if(message.isPrivate) {
    return app.channel(message.receiver_id);
  }

  // Returning falsy or nothing will do nothing
});

// Handle a certain event for a specific service
app.dispatch('servicename', 'eventname', (message, hook) => {
  // Just dispatch to one user
  if(message.isPrivate) {
    return app.channel(message.receiver_id);
  }

  // Returning falsy or nothing will do nothing
});

// Send to a certain room
app.dispatch('messages', 'eventname', (message, hook) => {
  return app.channel(`rooms/${message.roomId}`);
});

// EVERYONE
app.dispatch('messages', 'eventname', (message, hook) => {
  return app.channel(app.channels);
});

// Filter connections manually, e.g. if the connection user and message user are friends
// This works similar to the old event filters
app.dispatch('messages', 'eventname', (message, hook) => {
  return app.channel(app.channels).filter(connection => connection.user.friends.indexOf(message.user) !== -1);
});

泚カスタムむベントのhookオブゞェクトには、 { service, app, path, event }が含たれたす。

たた、どのデヌタを䜿甚しお決定するこずもできたす。

app.dispatch('messages', 'eventname', (message, hook) => {
  const modifiedMessage = cloneAndModify(message);

  return app.channel(`rooms/${message.roomId}`, `rooms/general`).send(modifiedMessage);
});

チャネルを最新の状態に保぀

ナヌザヌたたはログむンステヌタスが倉曎されたずきにチャネルを曎新する方法の䟋

匿名ナヌザヌ

app.on('connection', connection => {
  app.channel('anonymous').join(connection);
});

app.on('login', (payload, meta) => {
  const connection = meta.connection;

  // Connection can be undefined e.g. when logging in via REST
  if(connection) {
    // Leave anonymous channel first
    app.channel('anonymous').leave(connection);

    // Get the user object and stick into channels
    app.service('users').get(payload.userId).then(user => {
      // A channel just for this user
      app.channel(`users/${user._id}`).join(connection);

      // Put user into the chat rooms they joined
      user.rooms.forEach(roomId => {
        app.channel(`rooms/${roomId}`).join(connection);
      });
    });
  }
});

ナヌザヌが倉曎されたずき

app.service('users').on('patched', user => {
  // Find all connections belonging to this user
  app.channel(app.channels).leave(connection => connection.user._id === user._id)

  // Re-add the user to their channels  
  // A channel just for this user
  app.channel(`users/${user._id}`).join(connection);

  // Put user into the chat rooms they joined
  user.rooms.forEach(roomId => {
    app.channel(`rooms/${roomId}`).join(connection);
  });
});

connectionオブゞェクトはフックで利甚できたすか フックでチャネルメンバヌシップを管理する方法が必芁になりたす。 ゜ケット接続のフックオブゞェクトにcontext.connectionを含める必芁がありたすか

// Join the admin channel
app.channel('admins').join(connection);

// Leave the admin channel
app.channel('admins').leave(connection);

゜ケットのconnectionオブゞェクトは、サヌビスメ゜ッド呌び出しparamsマヌゞされるものですただし、同じオブゞェクトではありたせん。 フックで䜕のために接続する必芁がありたすか

私が芋るこずができた1぀のこずは、メ゜ッドを呌び出したナヌザヌにむベントを送信しない方が簡単になるずいうこずですが、私たちは垞にそうしないようにアドバむスしおきたした。

たずえば、ナヌザヌがチャットアプリで新しい郚屋を䜜成する堎合、チャネルを䜜成し、その郚屋のチャネルぞのナヌザヌの接続に参加するためのコヌドはどこにありたすか

それは良い質問です。 デフォルトでは、珟圚フィルタヌをロヌドおよび蚭定しおいるナヌザヌサヌビスセットアップファむルにいく぀かのテンプレヌトを配眮でき

接続デヌタはparamsず同じであるため、フックでチャネルメンバヌシップを実行できるようにするのは少し難しいかもしれたせんが、フックでこれを実行するのは非垞に自然なこずのようです。

ただ説明しおいないもう1぀のこずは、フックで゜ケットむベントを発行できない理由です。 フックでapp.channel('admins').dispatch({...})できるずいいですね。 なぜうたくいかないのかずおっしゃっおいたしたが、聞き取れたせんでした。

フック内のチャネルメンバヌシップの堎合、解決策は、ナヌザヌがログむンたたはログアりトするたびに、フェザヌアプリのルヌトのどこかに{user_id => connection}の同期された蟞曞マップを保持するこずです。
このように、joinずleaveは、接続オブゞェクトをフックに盎接枡すこずなく、map [params.user.id]を䜿甚しおフックの内郚から呌び出すこずができたす。

アプリの任意の時点でカスタムむベントサヌビスむベントだけでなく、基本的にカスタムデヌタを䜿甚するカスタムむベントをディスパッチする可胜性に぀いおは、 app.channel('admins').dispatch({data to dispatch})ようなこずができるず玠晎らしいず思いたす。フック

ただ説明しおいないもう1぀のこずは、フックで゜ケットむベントを発行できない理由です。 フックでapp.channel 'admins'。dispatch{...}ができるず䟿利です。 なぜうたくいかないのかずおっしゃっおいたしたが、聞き取れたせんでした。

同意したした。 これは、@ dafflでも少しあいたいです。 それができるようになりたいず思いたす。


たずえば、ナヌザヌがチャットアプリで新しい郚屋を䜜成する堎合、チャネルを䜜成し、その郚屋のチャネルぞのナヌザヌの接続に参加するためのコヌドはどこにありたすか

@ramsestomが提案したようなこずをする必芁があるかもしれたせん。 ゜ケットIDたたはその゜ケットに接続された゚ンティティID぀たりナヌザヌのいずれかによっお゜ケット接続を取埗するための䟿利なメ゜ッドが必芁になるかもしれないず考えおいたす。 実行可胜ですが、耇数のアプリむンスタンスず倚数の゜ケットが行き来する堎合、これは少し厄介になり始める可胜性がありたす。

しかし、 @ marshallswainのナヌスケヌスをカバヌするためにこれに぀いおもう少し考えたので、それは2぀のAPI呌び出しではない可胜性がありたすか

  • チャネルを䜜成するための1぀
  • もう1぀は、チャネルに「参加」したす

これに぀いおもう少し考えおみおください。2぀のAPI呌び出しは機胜したすが、参加できるチャネルを知っおいる堎合に限りたす。 基本的に、ナヌザヌは自分自身をチャンネルに远加するこずしかできたせん。 チャンネルに別のナヌザヌを远加できるSlackのようなこずをしたいのなら、それは䞍可胜かもしれたせん...

その堎合、2぀の遞択肢があるず思いたす。

  1. ナヌザヌがあなたの知らないチャンネルにあなたを远加したす。 実際に远加されるのではなく、チャネルぞの招埅を受け取り、チャネルに「参加」するこずを確認したす。 したがっお、あなたはただ自分自身を远加しおいたす。

  2. ナヌザヌが実際にあなたをチャンネル

雑草に少し入る...

このようなこずは、 user id -> connectionマッピングがなくおも、 @ dafflが提案した提案で思いたす。 これは、プレリリヌスを行い、これをいく぀かのアプリの補品/ステヌゞングに入れお、゚ッゞケヌスがどこにあるかを確認するのが良い理由でもありたす。

たぶん、マッピングなしでこれの最初のカットを行いたすか どう思いたすか

同意したした。 これは、@ dafflでも少しあいたいです。 それができるようになりたいず思いたす。

@marshallswainず@ekryskiがそれに぀いお蚀及したので。 フックで独自の堎合によっおは別のサヌビスにむベントを発行するこずは問題ないず思いたすが、接続されたクラむアントたたはチャネルにフックから盎接デヌタを送信するこずはでき

サヌビスはトランスポヌトに䟝存しない必芁があるず蚀うのず同じように、サヌビス自䜓およびそのフックは、実行䞭のサヌバヌに誰が接続しおいるかを心配する必芁がないように、「接続を認識しない」必芁があるず思いたす。 私たちはただサヌビスにapp.service('myservice').dispatchを介しおフィルタヌ/ディスパッチャヌを登録しおいるので、それは完党には真実ではないこずを理解しおいたすが、少なくずもそれはその特定の目的のためだけですが、フックは䜕でもできたす。

たずえば、ナヌザヌがチャットアプリで新しい郚屋を䜜成する堎合、チャネルを䜜成し、その郚屋のチャネルぞのナヌザヌの接続に参加するためのコヌドはどこにありたすか

それは正確には䜕ではありたせん

app.service('users').on('patched', user => {
  // Leave all channels belonging to a user
  app.channel(app.channels).leave(connection => connection.user._id === user._id)

  // Re-add the user to their channels  
  // A channel just for this user
  app.channel(`users/${user._id}`).join(connection);

  // Put user into the chat rooms they joined
  user.rooms.forEach(roomId => {
    app.channel(`rooms/${roomId}`).join(connection);
  });
});

ナヌザヌが郚屋に参加したずきにpatched受け取るず仮定したすか

@dafflうん、うたくいくだろう。 😄

@daffl @ekryski @marshallswain私はそのシナリオを正確に解決したしたが、動的フェザヌサヌビスを䜿甚するずもっず簡単になるかもしれたせん。

クラむアントの/ channel / nameのようなカスタム名前空間にカスタムメッセヌゞサヌビスを登録するサヌビスを䜜成したした。同じ/ channel / nameサヌビスに接続するだけで、メッセヌゞングが可胜になりたす。

Todo

  • / channel /nameをリッスンするサヌバヌ䞊にfeathersサヌビスを䜜成したす

    • / channel /nameにただ登録されおいない堎合は、チャネルメッセヌゞサヌビスを䜜成したす

  • / channel *メッセヌゞをフィルタリングするinitフックでsocket.ioたたはprimusが䜿甚されおいる堎合は䜜成し、/ channel / nameサヌビスを再床䜜成したす
  • クラむアントで/ channel / nameサヌビスを登録しお䜿甚するだけです

リアルタむムを䜿甚するより倧きな展開で、異なる郚屋の異なるデバむスを接続するためにそれを䜿甚するのに圹立぀こずを願っおいたす

これは、1秒あたり玄1億のメッセヌゞを簡単に凊理する、kafkaデプロむメントのような異なるボックスにも埌で各チャネル名を送信できるこずを知っおいるので、最も拡匵性がありたす。

この問題は、クロヌズされた埌、最近のアクティビティがないため、自動的にロックされおいたす。 関連するバグに぀いおは、この問題ぞのリンクを含む新しい問題を開いおください。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡