間違ってたらごめんなさい
mastodon
分散SNSです
分散SNSの実現方法
Based on ActivityStreams, Webfinger, PubsubHubbub and Salmon.
とのことなんで、追って流れを見ていきましょう
超ざっくり
登場人物
- mastodon instance
- social network server
- こいつが誰でも立てられて連携できる
- pubsubで言うところのsubscriberでありpublisherである
- user
- mastodon利用者
アクション
- to-to
- tweet on twitter
- Reply
- reply on twitter
- Boost
- retweet on twitter
- Favorite
- favorite on twitter
- Follow
- favorite on twitter
- timeline
- timeline on twitter
流れ
instance XのUser Aさんの情報をinstance Yで見る
- (webfinger) User Aさんのtimelineを見たいので、User Aさんのtimeline取得endpointを探す
- (PubSubHubbub) User Aさんをfollow
- (activestream) User Aさんのfeed取得
- (PubSubHubbub) User Aさんの更新が更に通知される
instance XのUser Aさんにinstance YのUser Bさんがreplyし、それをinstance ZのUser Cさんが閲覧する
- (activestream) User Aさんのfeed取得
- (activestream) User Aさん向けのreply
- (salmon) replyがAさんのmention受付エンドポイントに通知される
- (salmon) mentionを他のインスタンスに通知依頼
- (PubSubHubbub) インスタンスに展開
- User Cさんが会話のやり取りを見る!
要素技術の説明
Webfinger
WebFingerは、セキュアなトランスポートを介して標準的なHTTP(Hypertext Transfer Protocol)方式を使用してURIで識別される、インターネット上の人または他のエンティティに関する情報を検出するために使用されます。
WebFingerリソースは、照会されるエンティティを記述するJavaScript Object Notation(JSON)オブジェクトを返します。 JSONオブジェクトはJSONリソース記述子(JRD)と呼ばれます。
= Userのfeed discoveryです。
というわけで、webfinger叩いてみる
実際の動き
host-metaからwebfinger情報を取得
<?xml version="1.0"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" type="application/xrd+xml" template="https://mstdn.jp/.well-known/webfinger?resource={uri}"/>
</XRD>
webfingerにてuserの情報をdiscoveryする
{
"subject": "acct:threetreeslight@mstdn.jp",
"aliases": [
"https://mstdn.jp/@threetreeslight",
"https://mstdn.jp/users/threetreeslight"
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://mstdn.jp/@threetreeslight"
},
{
"rel": "http://schemas.google.com/g/2010#updates-from",
"type": "application/atom+xml",
"href": "https://mstdn.jp/users/threetreeslight.atom"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://mstdn.jp/@threetreeslight"
},
{
"rel": "salmon",
"href": "https://mstdn.jp/api/salmon/140702"
},
{
"rel": "magic-public-key",
"href": "data:application/magic-public-key,RSA.x6myjejqg0H7pCoE_gX6_AC_sbkSR5C8VKJVHZe1LJqrKjqjb4Wg8AIbztz5qzyAOVF1SW8Uswn9VZRjUd5i1nAiLCioC0nV_-c4EEa5hD4-VVG4zJfKHUPmdZg_rh13r7hpWmJi3VBkPAE3Jo7jSlPoESWROrM_7-397cwqNODRY50K5MDoiZGUihAHamuZNOwjaA7X3yoo7CzQ_q2U6mGtTDFtaG3NtVD48siokEmdhgoDoKDY3onA7qFQVfotZ-CiQNw4m8uXByW6FvWJ1frG9FO5z5jmIRZKBaY0c3OmdB2XB0aRqYLFdgm1CDXawaf4chb6jGUEDIP0NaU50w==.AQAB"
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://mstdn.jp/authorize_follow?acct={uri}"
}
]
}
これでどこ見に行けばその人のfeed取得できるか分かる!やったね!
ActivityStreams
ユーザーアクティビティの場合、Atomは、アクティビティ固有のメタデータの大部分を機械で解析可能な形式で表現する能力が欠けています。
アクティビティストリームは、この追加のアクティビティメタデータを既存のAtomエントリおよびフィード内で表現できるように設計されたXML形式です。
というわけでAtom拡張しました。
こんな情報でわかります。
Activityはactor、動varb、object、およびtargetで構成されます。
「ジェラルディンは彼女のアルバムに写真を掲載しました」または「ジョンはビデオを共有しました」という物語の上で、またはオブジェクトと一緒に行動する人物の話をします。
拡張されたschema情報をみてみると
https://github.com/activitystreams/activity-schema/blob/master/activity-schema.md
実際の動き
別インスタンスの@trebyとコミュニケーションとったときの@threetreeslight streamをみてみる
<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0">
<id>https://mstdn.jp/users/threetreeslight.atom</id>
<title>threetreeslight</title>
<subtitle></subtitle>
<updated>2017-04-21T13:49:18Z</updated>
<logo>/avatars/original/missing.png</logo>
<author>
<id>https://mstdn.jp/users/threetreeslight</id>
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
<uri>https://mstdn.jp/users/threetreeslight</uri>
<name>threetreeslight</name>
<email>threetreeslight@mstdn.jp</email>
<link rel="alternate" type="text/html" href="https://mstdn.jp/@threetreeslight"/>
<link rel="avatar" type="" media:width="120" media:height="120" href="/avatars/original/missing.png"/>
<link rel="header" type="" media:width="700" media:height="335" href="/headers/original/missing.png"/>
<poco:preferredUsername>threetreeslight</poco:preferredUsername>
<mastodon:scope>public</mastodon:scope>
</author>
<link rel="alternate" type="text/html" href="https://mstdn.jp/@threetreeslight"/>
<link rel="self" type="application/atom+xml" href="https://mstdn.jp/users/threetreeslight.atom"/>
<link rel="hub" href="https://mstdn.jp/api/push"/>
<link rel="salmon" href="https://mstdn.jp/api/salmon/140702"/>
<entry>
<id>tag:mstdn.jp,2017-05-24:objectId=13974575:objectType=Status</id>
<published>2017-05-24T06:31:33Z</published>
<updated>2017-05-24T06:31:33Z</updated>
<title>New status by threetreeslight</title>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/comment</activity:object-type>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<content type="html" xml:lang="ru"><p><span class="h-card"><a href="https://imastodon.net/@treby" class="u-url mention">@<span>treby</span></a></span> 食べたい</p></content>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="https://imastodon.net/users/treby"/>
+ <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
<mastodon:scope>public</mastodon:scope>
<link rel="alternate" type="text/html" href="https://mstdn.jp/users/threetreeslight/updates/6205287"/>
<link rel="self" type="application/atom+xml" href="https://mstdn.jp/users/threetreeslight/updates/6205287.atom"/>
<thr:in-reply-to ref="tag:imastodon.net,2017-05-24:objectId=967970:objectType=Status" href="https://imastodon.net/users/treby/updates/422592"/>
</entry>
<entry>
<id>tag:mstdn.jp,2017-04-21:objectId=2405319:objectType=Status</id>
<published>2017-04-21T13:59:07Z</published>
<updated>2017-04-21T13:59:07Z</updated>
<title>New status by threetreeslight</title>
+ <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
+ <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<content type="html" xml:lang="en"><p>しかし横1024だと使うの難しい。</p></content>
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
<mastodon:scope>public</mastodon:scope>
<link rel="alternate" type="text/html" href="https://mstdn.jp/users/threetreeslight/updates/1202938"/>
<link rel="self" type="application/atom+xml" href="https://mstdn.jp/users/threetreeslight/updates/1202938.atom"/>
</entry>
</feed>
各アクション(Activity)が定義できたね!やったね!
replyのやり取りをどうやってとりまとめているかは追いきれませんでした。すいません :swear:
ref
PubSubHubbub
よく噛むので読み方: パブサブハバブ
PubSub with poling is Hard
Publisherが3つあってSubscriberが3つあるととすると常に9箇所ポーリング!
# Publisher Pとしては無意味なpolingが発生されて辛い
Publisher P <-poling- Subscriber X
Publisher P <-poling- Subscriber Y
Publisher P <-poling- Subscriber Z
# Subscriber Xとしては更新されていないかもしれないpolingがつらい
Publisher O <-poling- Subscriber X
Publisher P <-poling- Subscriber X
Publisher Q <-poling- Subscriber X
負荷を捌くためには、PublisherとSubscriberをスケールしなければいけない
じゃあどうするか?
PubSub with poling is Hard
じゃあどうするか?
mailmagzineみたいに更新受取登録しておいて、連絡を受けるようにする。
Subscriberが更新受付たい旨を登録する。
Publisherは更新があったら登録されているsubscriberに更新を通知する。
Hub P <-registered- Subscriber X
Hub P <-registered- Subscriber Y
Hub P <-registered- Subscriber Z
Publisher P -update notify-> Hub P
Publisher P <-get contents- Hub P
Hub P -post contents-> Subscriber X
Hub P -post contents-> Subscriber Y
Hub P -post contents-> Subscriber Z
salmon
RSS、Atom、PubSubHubbubなどのテクノロジでは、読者にリアルタイムの更新フローが提供されますが、これは会話の断片化につながります。
コメント、評価、およびアノテーションは、アグリゲータでますます発生し、元のソースからは見えません。サーモンプロトコルは、アグリゲーターとソースが会話を統一できるオープンでシンプルな標準ベースのソリューションです。 当初、パブリックコンテンツを中心とした一般の会話に焦点を当てています。
replyの仕組みとそれが各インスタンスに展開される流れ
- entryにreply(commnet)する際にはsalmon endpointにも通知する
- salmon endpointが受けた通知をサーバー内に保存し、entryと紐付ける
- publisherはreply(commnet)をpubsubhubbubを通してsubscriberにrepublishする
ref
- http://www.salmon-protocol.org/
- http://www.salmon-protocol.org/salmon-protocol-summary
- https://github.com/salmon-protocol/salmon-protocol
ref
だいたいココ読めば分かるのでおすすめです。