web-dev-qa-db-ja.com

Appleプッシュ通知をまとめて

Appleプッシュ通知を約100万人のユーザーに定期的に送信するアプリがあります。そのためのセットアップが構築され、少数の通知に対してテストされています。送信をテストする方法がないため、その規模で、大量のプッシュ通知を送信する際の落とし穴があるかどうかを知りたいと思っています。Pythonで記述されたスクリプトがあり、プッシュサーバーへの単一の接続を開き、その上ですべての通知を送信します。接続。Appleは、できるだけ長く開いたままにしておくことをお勧めします。しかし、接続が終了し、再確立する必要があることも確認しました。

全体として、成功した送信が確認されず、誤った送信のみにフラグが立てられるのは当惑させられます。プログラマーの観点からは、単に「if(success)」をチェックするのではなく、問題が発生する可能性のある多くのことを監視する必要があります。

私の質問は、メッセージが黙って忘却に消えないようにするために注意する必要がある典型的なエラーのセットは何ですか?接続を閉じるのは簡単です。他にありますか?

26
er0

このAPIは非常に苛立たしいものであり、通知ごとに応答を送信していたとしたら、実装がはるかに簡単だったことに完全に同意します。

そうは言っても、これがAppleあなたがすべきだと言っていることです( テクニカルノート から):

プッシュ通知のスループットとエラーチェック

APNを使用するための上限やバッチサイズの制限はありません。 iOS 6.1のプレスリリースによると、APNは設立以来4兆を超えるプッシュ通知を送信しています。 WWDC 2012で、APNが毎日70億件の通知を送信していることが発表されました。

スループットが1秒あたり9,000通知未満の場合、サーバーはエラー処理ロジックの改善から恩恵を受ける可能性があります。

拡張バイナリインターフェイスを使用するときにエラーをチェックする方法は次のとおりです。書き込みが失敗するまで書き込みを続けます。ストリームを再度書き込む準備ができたら、通知を再送信して続行します。ストリームを書き込む準備ができていない場合は、ストリームを読み取ることができるかどうかを確認してください。

そうである場合は、ストリームから利用可能なすべてを読み取ります。ゼロバイトが返される場合、無効なコマンドバイトやその他の解析エラーなどのエラーのために接続が閉じられました。 6バイトが戻った場合、それはエラー応答であり、応答コードとエラーの原因となった通知のIDを確認できます。それに続くすべての通知をもう一度送信する必要があります。

すべてが送信されたら、最後にもう一度チェックしてエラー応答を確認します。

通常の遅延のために、ドロップされた接続がAPNからサーバーに戻るまでに時間がかかる場合があります。接続が切断されたために書き込みが失敗する前に、500を超える通知を送信することができます。パイプがいっぱいであるという理由だけで約1,700の通知書き込みが失敗する可能性があるため、その場合は、ストリームが再度書き込みの準備ができたら再試行してください。

ここで、トレードオフが興味深いものになります。書き込むたびにエラー応答を確認でき、エラーをすぐにキャッチできます。ただし、これにより、通知のバッチを送信するのにかかる時間が大幅に増加します。

デバイストークンを正しくキャプチャし、正しい環境に送信している場合、デバイストークンはほぼすべて有効です。したがって、障害がまれであると想定して最適化することは理にかなっています。書き込みが失敗するか、バッチが完了するのを待ってからエラー応答を確認すると、ドロップされた通知を再度送信する時間を数えても、パフォーマンスが大幅に向上します。

これはAPNに固有のものではなく、ほとんどのソケットレベルのプログラミングに適用されます。

選択した開発ツールが複数のスレッドまたはプロセス間通信をサポートしている場合は、スレッドまたはプロセスが常にエラー応答を待機し、メインの送信スレッドまたはプロセスに、いつあきらめて再試行するかを通知できます。

12
Eran

毎日何百万ものAPNS通知を送信しているので、一人称の視点でチャイムを鳴らしたかっただけです。

残念ながら、@ Eranの引用は、AppleがAPNSソケットを管理する方法についての最良のリソースに関するものです。少量の場合は問題ありませんが、Appleのドキュメントは全体として、カジュアルで少量の開発者に偏っています。スケーリングすると、文書化されていない動作がたくさん表示されます。

エラー検出を非同期で行うことに関するそのドキュメントの一部は、高スループットにとって重要です。送信ごとにエラーをブロックすることを主張する場合は、スループットを維持するためにワーカーを大幅に並列化する必要があります。ただし、推奨される方法は、送信できる限り高速に送信し、エラーが発生した場合は常に修復と再生を行うことです。

私が例外とするその投稿の部分は次のとおりです。

デバイストークンはほぼすべて有効である必要があります正しくキャプチャした場合そして正しい環境に送信しています。 したがって、失敗がまれであると想定して最適化することは理にかなっています

そのような巨大な「IF」でそのアドバイスを述語することは、非常に誤解を招くように思われます。ほとんどの開発者がトークンをキャプチャしてAppleのフィードバックサービスを100%「正しく」処理していないことをほぼ保証できます。たとえそうであったとしても、システムは本質的に損失が大きいため、ドリフトが発生します。

ルート権限を取得された電話、クライアントのバグ、またはユーザーが意図的にトークンをスプーフィングしたことに起因する、ゼロ以外の数のエラー#8応答(無効なデバイストークン)が表示されます。また、過去にいくつかのエラー#7(無効なペイロードサイズ)が発生しました。これは、開発者が私たちの側で追加した不適切にエンコードされたメッセージまで追跡しました。もちろんそれは私たちのせいでしたが、それが私のポイントです。「失敗がまれであると想定して最適化する」というのは、学習開発者に送信する間違ったメッセージです。代わりに私が言うことは次のようになります:

エラーが発生すると想定します。

それらがまれにしか発生しないことを願っていますが、発生しない場合に備えて防御的にコーディングしてください。

エラーがまれであると想定して最適化すると、APNSサービスがダウンし、送信するすべてのメッセージがエラー#10を返すたびに、インフラストラクチャが危険にさらされる可能性があります。

エラーに適切に対応する方法を見つけようとすると、問題が発生します。さまざまなエラーを適切に処理して回復する方法に関するドキュメントがあいまいであるか、存在しません。これはどうやら読者のための練習として残されています。

7
DougW