View
6.795
Download
1
Category
Preview:
DESCRIPTION
Designing a real-time chat system using NSQ and Go
Citation preview
NSQ-Centric
ArchitectureNSQ中心の構造
About me
• American
• Went to college in Japan (Waseda)
• The “Go person” at Gunosy
• アメリカ人
• 早稲田大学出身
• Gunosyの「Go担当」
Greg Roseberry
http://github.com/guregu
GunosyNews aggregator / portal app
If you’re Japanese and have a TV
you already know about it
テレビを持っている日本人ならばご存知のはず
Life at Gunosy
• We like Go
• The API server is all Go
• Anything else I get my hands
on will be Go
• You can use basically any
software/library/whatever you’d
like… if you’re willing to take
responsibility.
GunosyはGoが好きAPIなどで
Goを喜んで利用
責任を持てば…
好きな技術を使っていいという主義
Bring it on.
かかってこい
The Problem
• A chat server…
• … that’s real-time
• … and easily scalable
• … and distributed
• … and flexible, without
complex configuration
issues
• チャット
• … リアルタイム
• … スケールしやすい
• … 分散
• … 柔軟で、複雑なconfigいらず
The Basics
• Go (obviously)
• In-app webview, so
WebSockets for realtime
stuff
• How can we stick our
WebSocket servers
behind a load balancer?
• Goに決まってるだろ
• アプリ内WebViewなのでリアルタム処理はWebSocket
• WebSocketはどうやってロードバランス?
Enter: NSQ
“Spray some NSQ on it!”
NSQをぶっかけよう!
NSQって何?
• What is NSQ?
• It’s a message queue.
• Written in Go.
• Made and used
extensively by bit.ly.
• メッセージキュー
• Goで書かれた
• bit.lyが開発している
NSQ Features• Distributed, no SPOF
• Easily horizontally scalable
• Low-latency, push-based
messages
• Can do load-balanced style
and multicast style
• Data format agnostic
• etc
• 分散 SPOFなし
• 横にスケールしやすい
• レイテンシーが低く、プッシュでメッセージを送る
• ロードバランスもマルチキャストも可能
• データフォーマットは何でもOK
• 等々
NSQ Guarantees• messages are not durable (by
default)
• set --mem-queue-size=0 to
persist all messages to disk
• messages are delivered at
least once
• messages received are un-
ordered
• consumers eventually find all
topic producers
• デフォルトでメッセージは耐久性がない
• --mem-queue-size=0で問題解決
• メッセージが必ず一回以上届く
• メッセージは順番がない
• consumerは少し時間かかっても結局全部のトピックを見つける
Topics and Channels
トピックにメッセージを送る。そのメッセージがコピーされて各チャンネルに送られる。複数のconsumer (
消費者)の場合はランダムに届く。consumerがない場合はメッセージが保管される。
nsqlookupd自動サービスディスカバリ
NSQはそもそも何のために作られたの?分散統計処理とか、だが…
• What was NSQ made for?
• Distributed statics processing
• But…
The Mission
WebViewでiMessage風チャットアプリ
The Protocol
• KISS. JSON.
• Same for
server→server and
server→client
• Easily routable
• シンプルなJSON
• サーバー同士のやり取りとサーバーとクライアントのやり取りが一緒
• ルートしやすい
Message Format
{
"type": <message-type>,
"to": <recipient-id>,
"body": {
...
}
}
オレオレRPC idを作れば完全にjson-rpc
Big Picture“chat” topic
websocket-srv-1
websocket-srv-2
websocket-srv-…
archive
push
bot
WebSocket Channels“chat” topic
websocket-srv-1
websocket-srv-2
websocket-srv-…
archive
push
bot
Msg A
Msg A
Msg A
Msg A
WebSocket Channels• One unique channel per server
(uses hostname)
• Every server gets every
message, drops uninteresting
ones (uses message To: field
and a map/sync.RWMutex)
• NSQ will hold on to all of our
messages if we disconnect, so
we can reconnect and catch up
• Distributed (at least, multiplexed)
chat!
• サーバー1台につき、1つのチャンネル
• 全部のメッセージが全部のサーバーに行く。宛先を見て、関係ないメッセージは無視する(mapとsync.RWMutex)
• もしネットワーク障害とかあったら、NSQが届かなかったメッセージを保管してくれる。
• 分散(少なくともマルチプレックス)チャット出来上がり!
Archive Channel“chat” topic
websocket-srv-1
websocket-srv-2
websocket-srv-…
archive
push
bot
Msg A
Msg B
Msg CMsg A
Msg B
Msg C
Randomly
distributed
Archive Channel
• One channel, many consumers
• Consumers grab every
message, and persist relevant
ones to the database
• It’s easy to add load balancing:
just add more consumers
• You can put the archiver
processes on the same server
as a DB and messages to be
archived will be delivered directly
• 一つのチャンネルに複数のconsumer
• 全部のメッセージを見て、DBに書き込む
• ロードバランスで分散するのに、サーバーを追加するだけでOK
• アーカイブプロセスとDBを一緒にすればメッセージが直接DBサーバーへ
Push Channel“chat” topic
websocket-srv-1
websocket-srv-2
websocket-srv-…
archive
push
bot
Msg A
Msg A
Msg B
Msg C
Msg BMsg C
Push Channel
• One channel, one
consumer
• Receives chat messages
and read receipts,
counting unread
messages
• Sends a push message
after a message goes
unread for a certain time
• 一つのチャンネルに一つのconsumer
• チャットメッセージと既読メッセージを受けて、読まれていないメッセージを数える
• 「新着メッセージが○件あります。」をプッシュ
Push Problems
• 1 server is going to get
overwhelmed eventually
• Not a problem for us
right now, but could be
solved in the future (split
servers based on
message ID, etc).
• サーバー1台だけだといずれ問題が起こす
• しばらくは大丈夫だけどいつか分散化へ
Microservices“chat” topic
websocket-srv-1
websocket-srv-2
websocket-srv-…
archive
push
bot
Just by adding a new channel,
we can easily add a new service.
It’s even possible to pause
topics or channels on the NSQ
web admin interface.
チャンネルを追加するだけで、新しいマイクロサービスを
追加できる。nsqadminという管理画面でトピックとチャンネルを一時停止もできる。デプロイが楽!
NSQ 0.3
• Came out less like a week
ago
• Introduces ephemeral topics:
topics that disappear when
there are no consumers left
• Could completely obsolete
this architecture/the multicast
method.
• No docs, needs more
research.
• 一週間前くらいに出た
• ephemeral topicsという、consumerがいなくなったら消えるトピック
• 今日紹介した仕組みすたれちゃうかも
• ドキュメントがまだない。研究が必要。
Client-side
Considerations
Order
• Messages might get
delivered out of order.
• Solution: sort messages
by their date.
• Make sure your clocks
are synchronized!
• メッセージの届く順番がない
• 日付に応じてソートすればOK
• 時計を同期しましょう
Duplicates
• Messages might get
delivered more than once.
• Solution: keep a list of
received messages, ignore
duplicates. UUIDs.
• You can handle message
edits by date or revision
number or something
fancier
• メッセージは2回以上届くかも
• すでに届いたメッセージのIDを記憶すればOK。UUIDが便利
• メッセージの編集は日付やバージョンで上書き
Why React
• It’s easy to reason about
updating data if you
keep a single source of
truth.
• It’s easier to think about
components than
controllers, services,
factories, scope, etc.
• Virtual DOM is fast
• 情報の更新は一元化すれば捗る
• コンポーネント指向は捗る
• DOMの変更が早い
Conclusion
• It’s easy to make a flexible,
distributed app with an “NSQ-
first” attitude.
• … but it’s hard to make a truly
“queue-only” app that avoids
hitting the DB. Groupcache
can help.
• Nothing here is particularly
novel, but it was simple to
develop. Less than a month
for a MVP between one
programmer and one
designer. Not bad for a
distributed service.
• NSQを中心にすれば、分散でフレキシブルなサービスが作りやすい。
• しかし、ほとんどDBをたたかない「キューのみ」のサービスはちょっと難しい。Groupcacheは助かる。
• これは別に新しい技術ではないが、開発しやすい仕組みです。プログラマー1人が1ヶ月でMVP。
Thank you!
「毎日Goが書きたい!NSQとやら新技術を使ってみたい!」と思っている諸君!
Gunosyはただ今、日本では数少ないGoエンジニア募集を行っています。
ぜひ、一緒にGoを書きましょう!
Recommended