ホームページ  >  記事  >  バックエンド開発  >  情報システムの設計と導入

情報システムの設計と導入

WBOY
WBOYオリジナル
2016-06-13 12:29:04787ブラウズ

メッセージ システムの設計と実装

文/JC_Huang (概要本の著者)
原文リンク: http://www.jianshu.com/p/f4d7827821f1
著作権は著者に属し、転載する場合は著者に連絡して許可を得て、「概要書の著者」とマークを付けてください。

製品分析

まず、メッセージが市場でどのように実装されるかを見てみましょう。

Jianshu

Jianshuのメッセージシステムは主に2つのタイプに分かれています

  • ショートメッセージ
  • リマインダー

ショートメッセージ
ショートメッセージの性質は、実際にはプライベートメッセージと同じであり、特定の情報内容を含むユーザーからユーザーに送信されるメッセージです。


ショートレター

リマインダー
リマインダーは、システムによって送信されるメッセージの形式です。コピーは固定されており、通常は特定のオブジェクトへのハイパーリンクがあります。


Jianshu リマインダー

Zhihu

Zhihu は Jianshu と同じで、主に 2 つのタイプがあります:

  • プライベートメッセージ
  • メッセージ

プライベートメッセージ
Jianshu と同様に、ユーザーがユーザーにメッセージを送信できます。管理者からユーザーに送信されるメッセージにすることができます。


Zhihu プライベートメッセージ

メッセージ
Zhihu メッセージは Jianshu のリマインダーよりも優れています。 Zhihu は、ユーザーの読書プレッシャーを軽減するために、複数の同様のメッセージを収集します。


Zhihu News

3 つのカテゴリーのニュース

2 つの製品の簡単な分析を通じて、これに基づいて、もう 1 つのメッセージ、つまりアナウンスを追加します。
アナウンスの主な性質は、システムがサイト上のすべてのユーザーが読むことができる特定のコンテンツを含むメッセージを送信することです。
メッセージには 3 つのカテゴリがあります:

  1. アナウンス
  2. リマインド
  3. プライベート メッセージ

リマインダーの言語分析

Jianshu から一連のリマインダー サンプルを取得します。

  • 3dbe1bd90774 さんがあなたをフォローしました
  • magicdawn があなたの記事「シングル サインオンを実装する 3 つの方法」を気に入ってくれました
  • 悪徳プログラムはあなたの記事「RESTful API に基づいてユーザー権限制御を設計する方法?」を気に入りました。 》
  • alexcc4 さんがあなたの記事「Nodejs での単体テストの実装」を気に入ってくれました。
  • あなたは「RESTful API に基づいてユーザー権限制御を設計する方法?」で書きました。 "cnlinjie からコメントを受け取りました
  • あなたの記事「セッション原則」がトピック「ios 開発」に追加されました

文の構造を分析してください、リマインダーの内容は単なるものです

「誰が誰のものに何をするのか」
「誰かが誰かの何かで何かをする」

誰か = リマインダーのトリガー、または送信者、送信者としてマーク
何かをする = リマインダーのアクション、コメント、いいね、注目はすべて 1 つのアクションに属し、アクションとしてマーク
何か = リマインダーのアクションのオブジェクト、どの特定の記事それは、ターゲットとしてマークされています
誰かの = リマインダー アクションのオブジェクトの所有者、targetOwner

としてマークされています これは明らかです、送信者と targetOwner は Web サイトのユーザーであり、ターゲットは特定の記事がリマインダーの対象である場合、記事に限定されず、他にもある場合は、ターゲットが記事であるかそれ以外であるかをマークする targetType を追加する必要があります。アクションは固定されています。Web サイト全体でリマインダーをトリガーするアクションはいくつかしかありません: コメント、いいね、フォロー... (または企業がリマインダーを必要とするその他のアクション)

の両側メッセージを取得するには 2 つの方法があります

  • プッシュ
  • プル

Zhihu を例に挙げます
プッシュの方が多いです特定の質問のフォロワーのリストを維持する必要があります。この質問をプッシュする条件がトリガーされると (たとえば、誰かが質問に回答するなど)、この通知が各フォロワーに送信されます。

プルはプッシュの逆で、少し面倒です。たとえば、ユーザーがオンラインになるたびに、各問題のイベント リストがポーリングされます。元のタイムスタンプよりも大きい場合は、それを取得します。

メッセージの分類に応じて異なる取得方法を使用します。:
メッセージが生成されると、メッセージは特定のメッセージ テーブルに保存されます。送信者がメッセージを作成した後、関心のある問題の表に従ってメッセージをプルし、それを独自のメッセージ キューに追加します。また、受信者を指定するか、受信者のメッセージ キューにメッセージを追加します。

購読

リマインダーに従ってプル方式を使用するには、注目すべき事項のリストを維持する必要があります。

この動作を次のように呼びます。

"サブスクライブ" サブスクライブ

サブスクリプションには次の 3 つのコア属性があります

:

サブスクリプション ターゲットtarget
  • サブスクリプション ターゲット タイプ targetType
  • サブスクリプション アクション action
  • たとえば、記事を公開する場合、記事「XXX」コメント アクションをサブスクライブします。 , そのため、記事「XXX」にコメントが付けられるたびに、リマインダーを送信して通知する必要があります。

購読ルールも拡張できます

記事が気に入った場合、購読アクションは記事を公開するときとは異なる場合があります。 記事が気に入ったら、更新情報やコメントを得るためにこの記事を購読していただければ幸いです。
記事を投稿するときに、この記事のコメント アクションを購読できればいいのにと思います。

この時点で、もう 1 つのパラメータが必要です。subscribReason

アクション配列に対応する異なる subscribReason、

subscribeReason = like、actions = [update, comment]
subscribeReason = に対応します。 public 、アクションに対応 = [コメント]

サブスクリプション ルールは拡張することもできます

ユーザーは独自のサブスクリプション設定を持つことができます。たとえば、すべてのお気に入りのアクションに対して、「I Don'」受け取りたくないのです。 たとえば、知っているリマインダーの設定

知っているリマインダーの設定
なので、別のテーブルを維持する必要があります: SubscriptionConfig

、ユーザーのリマインダー設定を保存します。 また、ユーザーがリマインダー設定を持っていない場合は、システムによって提供される一連のデフォルト設定を使用できます: defaultSubscriptionConfig
Aggregation

If I public私がオンラインではなかったとき、「XXX」という記事に 10 回コメントが付けられました。オンラインになったときは、次のようなメッセージを 10 回受け取ったはずです。「誰々があなたの記事「XXX」にコメントしました。

まだですか? 「A、B、C、D... あなたの記事 "XXX" にコメントしました。」というメッセージが表示されます。


Zhihu は集計において優れた仕事をしました。彼らが達成したいかどうかを知る必要があります。これはかなり技術的です:

Zhihu のメッセージング メカニズムは技術的にどのように設計され、計画されていますか?

Web サイトのメッセージ (通知) システムは一般的にどのように実装されていますか?

関数のこの部分に関しては、まだ具体的な実装方法が決まっていないため、これ以上詳しく説明することはできません。 ⊙﹏⊙

5 つのエンティティ

上記の分析を通じて、このメッセージング システムを構築するためにどのようなエンティティ クラスが必要であるかがおおよそわかります:

ユーザー メッセージ キュー UserNotify
  1. ユーザー
  2. サブスクリプション
  3. サブスクリプション設定 SubscriptionConfig
  4. メッセージ通知
  5. アナウンス
    • リマインド
    • メッセージ
  6. 動作の内訳

ここまで述べたので、メッセージ プロセス全体の動作をいくつか整理してみましょう。 >システムまたは管理者、メッセージを作成

createNotify (アナウンス | リマインド | メッセージ)

    • ユーザー、メッセージの購読、購読解除
    • 購読、購読のキャンセル
    • ユーザー管理サブスクリプション設定
    • getSubscriptionConfig, updateSubscriptionConfig
    • ユーザー、メッセージをプル
    • pullNotify (アナウンス | リマインド | メッセージ | すべて)
    • ユーザー、メッセージ キューをクエリします
    • getUserNotify(get cancel | remember | message | all)
    • ユーザーがメッセージを読み取ります
    • 読む
  • >>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>> ;>>>>>>>>>>>>>>>>>>>>>>

モデル設計

通知

<code class="javascript">id            : {type: <span class="hljs-string">'integer', primaryKey: <span class="hljs-literal">true},        <span class="hljs-comment">// 主键content     : {type: <span class="hljs-string">'text'},    <span class="hljs-comment">// 消息的内容type        : {type: <span class="hljs-string">'integer', required: <span class="hljs-literal">true, enum: [<span class="hljs-number">1, <span class="hljs-number">2, <span class="hljs-number">3]},  <span class="hljs-comment">// 消息的类型,1: 公告 Announce,2: 提醒 Remind,3:信息 Messagetarget      : {type: <span class="hljs-string">'integer'},    <span class="hljs-comment">// 目标的IDtargetType  : {type: <span class="hljs-string">'string'},    <span class="hljs-comment">// 目标的类型action      : {type: <span class="hljs-string">'string'},    <span class="hljs-comment">// 提醒信息的动作类型sender      : {type: <span class="hljs-string">'integer'},    <span class="hljs-comment">// 发送者的IDcreatedAt    : {type: <span class="hljs-string">'datetime', required: <span class="hljs-literal">true}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

保存リマインド
メッセージ テーブルには、targettargetType フィールドが必要です。このリマインダーに関連付けられたオブジェクトを記録します。 action フィールドには、リマインダーに関連付けられたアクションが記録されます。
たとえば、メッセージ: 「Xiao Ming が記事を気に入った」
その後:

<code class="javascript">target = <span class="hljs-number">123,  <span class="hljs-comment">// 文章IDtargetType = <span class="hljs-string">'post',  <span class="hljs-comment">// 指明target所属类型是文章sender = <span class="hljs-number">123456  <span class="hljs-comment">// 小明ID</span></span></span></span></span></span></code>

アナウンスとメッセージを保存
もちろん、Notify は保存もサポートしていますお知らせと情報。 content フィールドは使用されますが、targettargetType、および action フィールドは使用されません。

UserNotify

<code class="javascript">id            : {type: <span class="hljs-string">'integer', primaryKey: <span class="hljs-literal">true},        <span class="hljs-comment">// 主键isRead      : {type: <span class="hljs-string">'boolean', required: <span class="hljs-literal">true},   user        : {type: <span class="hljs-string">'integer', required: <span class="hljs-literal">true},  <span class="hljs-comment">// 用户消息所属者notify      : {type: <span class="hljs-string">'integer', required: <span class="hljs-literal">true}   <span class="hljs-comment">// 关联的NotifycreatedAt    : {type: <span class="hljs-string">'datetime', required: <span class="hljs-literal">true}</span></span></span></span></span></span></span></span></span></span></span></span></span></code>

UserNotify を使用して、リマインダー (通知) の特定のコンテンツに関連付けられたユーザーのメッセージ キューを保存します。
UserNotify は主に 2 つの方法で作成されます:

  1. アナウンスとリマインドをプルするためにサブスクリプション テーブルを走査するときに作成されます
  2. 新しい情報 (メッセージ) はすぐに作成されます。

サブスクリプション

<code class="javascript">target      : {type: <span class="hljs-string">'integer', required: <span class="hljs-literal">true},    <span class="hljs-comment">// 目标的IDtargetType  : {type: <span class="hljs-string">'string', required: <span class="hljs-literal">true},    <span class="hljs-comment">// 目标的类型action      : {type: <span class="hljs-string">'string'},   <span class="hljs-comment">// 订阅动作,如: comment/like/post/update etc.user        : {type: <span class="hljs-string">'integer'},createdAt    : {type: <span class="hljs-string">'datetime', required: <span class="hljs-literal">true}</span></span></span></span></span></span></span></span></span></span></span></code>

サブスクリプションは、Notify テーブルから UserNotify にメッセージをプルするための前提条件です。ユーザーはまず特定のターゲットのアクションをサブスクライブし、次にこの Only を生成します。ユーザーはターゲットのアクションを通知されます。
例: 「Xiao Ming は製品 A のコメントに注目しました」、データは次のように表現されます:

<code class="javascript">target: <span class="hljs-number">123,  <span class="hljs-comment">// 产品A的IDtargetType: <span class="hljs-string">'product',action: <span class="hljs-string">'comment',user: <span class="hljs-number">123  <span class="hljs-comment">// 小明的ID</span></span></span></span></span></span></code>

このように、製品 A で生成されたすべてのコメントにより Xiao への通知が生成されます。明。

SubscriptionConfig

<code class="javascript">action: {type: <span class="hljs-string">'json', required: <span class="hljs-literal">true},   <span class="hljs-comment">// 用户的设置user: {type: <span class="hljs-string">'integer'}</span></span></span></span></code>

ユーザーごとにサブスクリプションの習慣が異なる場合があります。このテーブルでは、ユーザーは特定のアクションをサブスクライブするかどうかを一律に設定できます。デフォルトでは、システムによって提供されるデフォルト構成が使用されます。

<code class="javascript">defaultSubscriptionConfig: {  <span class="hljs-string">'comment'   : <span class="hljs-literal">true,    <span class="hljs-comment">// 评论  <span class="hljs-string">'like'      : <span class="hljs-literal">true,    <span class="hljs-comment">// 喜欢}</span></span></span></span></span></span></code>

このモデルのセットでは、targetTypeaction は必要に応じて拡張できます。各アクションのリマインダーをさらに追加します: hate が嫌われた、update が更新されたなど。

設定ファイル NotifyConfig

<code class="javascript"><span class="hljs-comment">// 提醒关联的目标类型targetType: {  PRODUCT : <span class="hljs-string">'product',    <span class="hljs-comment">// 产品  POST    : <span class="hljs-string">'post'    <span class="hljs-comment">// 文章},<span class="hljs-comment">// 提醒关联的动作action: {  COMMENT   : <span class="hljs-string">'comment',  <span class="hljs-comment">// 评论  LIKE      : <span class="hljs-string">'like',     <span class="hljs-comment">// 喜欢},<span class="hljs-comment">// 订阅原因对应订阅事件reasonAction: {  <span class="hljs-string">'create_product'  : [<span class="hljs-string">'comment', <span class="hljs-string">'like']  <span class="hljs-string">'like_product'    : [<span class="hljs-string">'comment'],  <span class="hljs-string">'like_post'       : [<span class="hljs-string">'comment'],},<span class="hljs-comment">// 默认订阅配置defaultSubscriptionConfig: {  <span class="hljs-string">'comment'   : <span class="hljs-literal">true,    <span class="hljs-comment">// 评论  <span class="hljs-string">'like'      : <span class="hljs-literal">true,    <span class="hljs-comment">// 喜欢}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

サービス層 NotifyService

NotifyService には次のメソッドがあります:

  • createAnnounce(content, sender )
  • createRemind(ターゲット、targetType、アクション、送信者、コンテンツ)
  • createMessage(コンテンツ、送信者、受信者)
  • pullAnnounce(user)
  • pullRemind ( user)
  • subscribe(user, target, targetType,reason)
  • cancelSubscription(user, target, targetType)
  • getSubscriptionConfig(userID)
  • updateSubscriptionConfig ( userID)
  • getUserNotify(userID)
  • read(user, NoticeIDs)

各メソッドの処理ロジックは以下のとおりです:

createAnnounce (content, sender)

  1. Notify テーブルにアナウンス レコードを挿入します

createRemind(target, targetType, action, sender 、content)

  1. Notify テーブルにリマインダー レコードを挿入します

createMessage(content, sender,Receiver)

  1. Notify テーブルに情報レコードを挿入します
  2. UserNotify テーブルにレコードを挿入し、新しく作成された Notify を関連付けます

pullAnnounce(user)

  1. UserNotify から最新のアナウンス情報の作成時刻を取得します: lastTime
  2. lastTime をフィルター条件として使用して、Notify のアナウンス情報をクエリします
  3. 新しい UserNotify を作成し、クエリされたお知らせ情報を関連付けます

pullRemind(user)

  1. ユーザーのサブスクリプション テーブルをクエリし、一連のユーザーのサブスクリプションを取得しますrecords
  2. 各サブスクリプション レコードの targettargetTypeactioncreatedAt を介して Notify テーブルをクエリし、サブスクライブされた Notify レコードを取得します。 (サブスクリプション時刻はリマインダーの作成時刻よりも前である必要があることに注意してください)
  3. ユーザーの構成ファイル SubscriptionConfig をクエリします。そうでない場合は、デフォルトの構成 DefaultSubscriptionConfig を使用します。
  4. サブスクリプション構成を使用して、クエリされたものをフィルタリングします。 Notify
  5. フィルターされた通知を関連付けとして使用して、新しい UserNotify

subscribe(user, target, targetType,reason)

    を作成します
  1. 理由 NotifyConfig によってクエリを実行し、対応するアクション グループを取得します: actions
  2. アクション グループを走査し、アクションごとに新しいサブスクリプション レコードを作成します

cancelSubscription (user, target, targetType)

  1. usertargettargetType

getSubscriptionConfig に対応する 1 つ以上のレコードを削除します(userID)

  1. SubscriptionConfig テーブルをクエリしてユーザーのサブスクリプション構成を取得します

updateSubscriptionConfig(userID)

  1. ユーザーの SubscriptionConfig レコードを更新します

getUserNotify(userID)

  1. ユーザーのメッセージ リストを取得します

読み取り(ユーザー、通知ID)

  1. 指定された通知を更新し、isRead 属性を true に設定します

シーケンス図

リマインダーのサブスクリプション、作成、取得


リマインダーのサブスクリプション、作成、プル


製品の作成後に NotifyService.subscribe メソッドを呼び出し、
メソッドを呼び出して、製品のレビュー後に呼び出すことができます。 NotifyService.createRemind メソッド、
はその後、ユーザーがシステムにログインするときに NotifyService.pullRemind メソッドを呼び出します。または、ユーザーがメッセージ キューをクエリするときに、
は最後に NotifyService.getUserNotify メソッドを呼び出します。

アナウンスの作成と取得


アナウンスの作成と取得


管理者から送信 アナウンス時が作成され、NotifyService.createAnnounce メソッドが呼び出され、
次に、ユーザーがシステムにログインするとき、または別の時点で NotifyService.pullAnnounce メソッドが呼び出され、最後にユーザーがシステムにログインしたときに
メソッドが呼び出されます。メッセージキューをクエリします。 NotifyService.getUserNotify

情報の作成


情報の作成

情報を作成するには、
を直接呼び出すだけです これNotifyService.createMessage次回ユーザーがメッセージ キューをクエリするときに、この情報がクエリされます。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。