Enviar búsqueda
Cargar
Pub/Sub model, msm, and asio
•
Descargar como PPTX, PDF
•
5 recomendaciones
•
1,601 vistas
Takatoshi Kondo
Seguir
Boost study group #20 presentation slides.
Leer menos
Leer más
Software
Denunciar
Compartir
Denunciar
Compartir
1 de 42
Descargar ahora
Recomendados
Boost sg msgpack
Boost sg msgpack
Takatoshi Kondo
CppCon2016 report and Boost.SML
CppCon2016 report and Boost.SML
Takatoshi Kondo
いまさら聞けないRake入門
いまさら聞けないRake入門
Tomoya Kawanishi
Reactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単に
Yoshifumi Kawai
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
Atsuo Ishimoto
H2O - making HTTP better
H2O - making HTTP better
Kazuho Oku
WebRTC multitrack / multistream
WebRTC multitrack / multistream
mganeko
Qt Creator を拡張する
Qt Creator を拡張する
Takumi Asaki
Recomendados
Boost sg msgpack
Boost sg msgpack
Takatoshi Kondo
CppCon2016 report and Boost.SML
CppCon2016 report and Boost.SML
Takatoshi Kondo
いまさら聞けないRake入門
いまさら聞けないRake入門
Tomoya Kawanishi
Reactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単に
Yoshifumi Kawai
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
Atsuo Ishimoto
H2O - making HTTP better
H2O - making HTTP better
Kazuho Oku
WebRTC multitrack / multistream
WebRTC multitrack / multistream
mganeko
Qt Creator を拡張する
Qt Creator を拡張する
Takumi Asaki
Rust-DPDK
Rust-DPDK
Masaru Oki
C#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive Extensions
Yoshifumi Kawai
HTTP/2時代のウェブサイト設計
HTTP/2時代のウェブサイト設計
Kazuho Oku
WebRTC getStats - WebRTC Meetup Tokyo 5 LT
WebRTC getStats - WebRTC Meetup Tokyo 5 LT
mganeko
Rake
Rake
Tomoya Kawanishi
NanoStrand
NanoStrand
Masashi Umezawa
WebRTC meetup Tokyo 1
WebRTC meetup Tokyo 1
mganeko
Node.js with WebRTC DataChannel
Node.js with WebRTC DataChannel
mganeko
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
mganeko
qmake入門
qmake入門
hermit4 Ishida
Reactive Extensions v2.0
Reactive Extensions v2.0
Yoshifumi Kawai
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Yoshifumi Kawai
HTTP/2, QUIC入門
HTTP/2, QUIC入門
shigeki_ohtsu
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
azumakuniyuki 🐈
Node.jsv0.8からv4.xへのバージョンアップ ~大規模Push通知基盤の運用事例~
Node.jsv0.8からv4.xへのバージョンアップ ~大規模Push通知基盤の運用事例~
Recruit Technologies
Pd Kai#3 Startup Process
Pd Kai#3 Startup Process
nagachika t
Gocon2017:Goのロギング周りの考察
Gocon2017:Goのロギング周りの考察
貴仁 大和屋
Rust-DPDK
Rust-DPDK
Masaru Oki
LINQ in Unity
LINQ in Unity
Yoshifumi Kawai
linq.js - Linq to Objects for JavaScript
linq.js - Linq to Objects for JavaScript
Yoshifumi Kawai
Glfw3,OpenGL,GUI
Glfw3,OpenGL,GUI
hira_kuni_45
C++14 solve explicit_default_constructor
C++14 solve explicit_default_constructor
Akira Takahashi
Más contenido relacionado
La actualidad más candente
Rust-DPDK
Rust-DPDK
Masaru Oki
C#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive Extensions
Yoshifumi Kawai
HTTP/2時代のウェブサイト設計
HTTP/2時代のウェブサイト設計
Kazuho Oku
WebRTC getStats - WebRTC Meetup Tokyo 5 LT
WebRTC getStats - WebRTC Meetup Tokyo 5 LT
mganeko
Rake
Rake
Tomoya Kawanishi
NanoStrand
NanoStrand
Masashi Umezawa
WebRTC meetup Tokyo 1
WebRTC meetup Tokyo 1
mganeko
Node.js with WebRTC DataChannel
Node.js with WebRTC DataChannel
mganeko
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
mganeko
qmake入門
qmake入門
hermit4 Ishida
Reactive Extensions v2.0
Reactive Extensions v2.0
Yoshifumi Kawai
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Yoshifumi Kawai
HTTP/2, QUIC入門
HTTP/2, QUIC入門
shigeki_ohtsu
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
azumakuniyuki 🐈
Node.jsv0.8からv4.xへのバージョンアップ ~大規模Push通知基盤の運用事例~
Node.jsv0.8からv4.xへのバージョンアップ ~大規模Push通知基盤の運用事例~
Recruit Technologies
Pd Kai#3 Startup Process
Pd Kai#3 Startup Process
nagachika t
Gocon2017:Goのロギング周りの考察
Gocon2017:Goのロギング周りの考察
貴仁 大和屋
Rust-DPDK
Rust-DPDK
Masaru Oki
LINQ in Unity
LINQ in Unity
Yoshifumi Kawai
linq.js - Linq to Objects for JavaScript
linq.js - Linq to Objects for JavaScript
Yoshifumi Kawai
La actualidad más candente
(20)
Rust-DPDK
Rust-DPDK
C#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive Extensions
HTTP/2時代のウェブサイト設計
HTTP/2時代のウェブサイト設計
WebRTC getStats - WebRTC Meetup Tokyo 5 LT
WebRTC getStats - WebRTC Meetup Tokyo 5 LT
Rake
Rake
NanoStrand
NanoStrand
WebRTC meetup Tokyo 1
WebRTC meetup Tokyo 1
Node.js with WebRTC DataChannel
Node.js with WebRTC DataChannel
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
qmake入門
qmake入門
Reactive Extensions v2.0
Reactive Extensions v2.0
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
HTTP/2, QUIC入門
HTTP/2, QUIC入門
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
JSONでメール送信 | HTTP API Server ``Haineko''/YAPC::Asia Tokyo 2013 LT Day2
Node.jsv0.8からv4.xへのバージョンアップ ~大規模Push通知基盤の運用事例~
Node.jsv0.8からv4.xへのバージョンアップ ~大規模Push通知基盤の運用事例~
Pd Kai#3 Startup Process
Pd Kai#3 Startup Process
Gocon2017:Goのロギング周りの考察
Gocon2017:Goのロギング周りの考察
Rust-DPDK
Rust-DPDK
LINQ in Unity
LINQ in Unity
linq.js - Linq to Objects for JavaScript
linq.js - Linq to Objects for JavaScript
Destacado
Glfw3,OpenGL,GUI
Glfw3,OpenGL,GUI
hira_kuni_45
C++14 solve explicit_default_constructor
C++14 solve explicit_default_constructor
Akira Takahashi
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
Hideyuki Tanaka
Boost.Timer
Boost.Timer
melpon
C++14 enum hash
C++14 enum hash
Akira Takahashi
Introduction to boost test
Introduction to boost test
Kohsuke Yuasa
Destacado
(6)
Glfw3,OpenGL,GUI
Glfw3,OpenGL,GUI
C++14 solve explicit_default_constructor
C++14 solve explicit_default_constructor
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
Boost.Timer
Boost.Timer
C++14 enum hash
C++14 enum hash
Introduction to boost test
Introduction to boost test
Similar a Pub/Sub model, msm, and asio
Prosym2012
Prosym2012
MITSUNARI Shigeo
Boost tour 1_40_0
Boost tour 1_40_0
Akira Takahashi
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
ThinReports
Inside Movable Type
Inside Movable Type
純生 野田
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
Preferred Networks
Gumi study7 messagepack
Gumi study7 messagepack
Sadayuki Furuhashi
gumiStudy#7 The MessagePack Project
gumiStudy#7 The MessagePack Project
Sadayuki Furuhashi
Microsoft Graph API Library for Go
Microsoft Graph API Library for Go
yaegashi
20130315 abc firefox_os
20130315 abc firefox_os
Tomoaki Konno
API Gateway + LambdaでLINE通知サービス構築
API Gateway + LambdaでLINE通知サービス構築
Ken'ichirou Kimura
mod_auth_ticket - Bringing Single-Sign-On to lighttpd
mod_auth_ticket - Bringing Single-Sign-On to lighttpd
Taisuke Yamada
OCamlのトップレベルあれそれ
OCamlのトップレベルあれそれ
nomaddo
boost tour 1.48.0 all
boost tour 1.48.0 all
Akira Takahashi
社内向けTech Talk資料~Fluentdの基本紹介~
社内向けTech Talk資料~Fluentdの基本紹介~
Daisuke Ikeda
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
Shintaro Fukushima
About GStreamer 1.0 application development for beginners
About GStreamer 1.0 application development for beginners
Shota TAMURA
Continuation with Boost.Context
Continuation with Boost.Context
Akira Takahashi
恐怖!シェルショッカーの POSIX原理主義シェルスクリプト
恐怖!シェルショッカーの POSIX原理主義シェルスクリプト
Richie Shellshoccar
Python physicalcomputing
Python physicalcomputing
Noboru Irieda
Boost Tour 1.50.0 All
Boost Tour 1.50.0 All
Akira Takahashi
Similar a Pub/Sub model, msm, and asio
(20)
Prosym2012
Prosym2012
Boost tour 1_40_0
Boost tour 1_40_0
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Inside Movable Type
Inside Movable Type
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
Gumi study7 messagepack
Gumi study7 messagepack
gumiStudy#7 The MessagePack Project
gumiStudy#7 The MessagePack Project
Microsoft Graph API Library for Go
Microsoft Graph API Library for Go
20130315 abc firefox_os
20130315 abc firefox_os
API Gateway + LambdaでLINE通知サービス構築
API Gateway + LambdaでLINE通知サービス構築
mod_auth_ticket - Bringing Single-Sign-On to lighttpd
mod_auth_ticket - Bringing Single-Sign-On to lighttpd
OCamlのトップレベルあれそれ
OCamlのトップレベルあれそれ
boost tour 1.48.0 all
boost tour 1.48.0 all
社内向けTech Talk資料~Fluentdの基本紹介~
社内向けTech Talk資料~Fluentdの基本紹介~
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
About GStreamer 1.0 application development for beginners
About GStreamer 1.0 application development for beginners
Continuation with Boost.Context
Continuation with Boost.Context
恐怖!シェルショッカーの POSIX原理主義シェルスクリプト
恐怖!シェルショッカーの POSIX原理主義シェルスクリプト
Python physicalcomputing
Python physicalcomputing
Boost Tour 1.50.0 All
Boost Tour 1.50.0 All
Más de Takatoshi Kondo
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39
Takatoshi Kondo
MessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization Library
Takatoshi Kondo
Emcpp0506
Emcpp0506
Takatoshi Kondo
Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02
Takatoshi Kondo
Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02
Takatoshi Kondo
Unpack mechanism of the msgpack-c
Unpack mechanism of the msgpack-c
Takatoshi Kondo
N3495 inplace realloc
N3495 inplace realloc
Takatoshi Kondo
N3701 concept lite
N3701 concept lite
Takatoshi Kondo
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Takatoshi Kondo
Más de Takatoshi Kondo
(9)
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39
MessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization Library
Emcpp0506
Emcpp0506
Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02
Unpack mechanism of the msgpack-c
Unpack mechanism of the msgpack-c
N3495 inplace realloc
N3495 inplace realloc
N3701 concept lite
N3701 concept lite
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Pub/Sub model, msm, and asio
1.
Pub/Subモデルとmsmとasioと Takatoshi Kondo 2016/7/23 1
2.
発表内容 2016/7/23 2 • Pub/Subモデルとは? •
コネクションとスレッド • 2つのスケーラビリティ • brokerの状態管理とイベントの遅延処理 • msmの要求する排他制御 • io_serviceのpostと実行順序 • async_writeとstrand
3.
自己紹介 2016/7/23 3 • 近藤
貴俊 • ハンドルネーム redboltz • msgpack-cコミッタ – https://github.com/msgpack/msgpack-c • MQTTのC++クライアント mqtt_client_cpp 開発 – https://github.com/redboltz/mqtt_client_cpp • MQTTを拡張したスケーラブルな brokerを仕事で開発中 • CppCon 2016 参加予定
4.
Pub/Subモデルとは 2016/7/23 4 topic A publisher
1 subscriber 1 topic B publisher 2 subscriber 2 hello world 論理的な概念 subscribe publish world
5.
client Pub/Subモデルとは 2016/7/23 5 broker clientpublisher subscriber topictopic connection 物理的?な配置 node
6.
コネクションとスレッド 2016/7/23 6 broker client connection worker thread worker thread worker thread client client context
switch のコスト増大
7.
コネクションとスレッド 2016/7/23 7 broker client connection boost::asio::io_service on
1 thread client client
8.
io_service 2016/7/23 8 #include <iostream> #include
<boost/asio.hpp> int main() { boost::asio::io_service ios; ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.run(); } http://melpon.org/wandbox/permlink/MzfsrLNdJjfAeV15 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 11 12 様々な処理(ネットワーク、タイマ、シリアルポート、 シグナルハンドル、etc)をio_serviceにpost。 イベントが無くなるまで処理を実行 http://www.boost.org/doc/html/boost_asio/reference.html
9.
io_service 2016/7/23 9 #include <iostream> #include
<boost/asio.hpp> int main() { boost::asio::io_service ios; ios.post([&ios]{ std::cout << __LINE__ << std::endl; ios.post([&ios]{ std::cout << __LINE__ << std::endl; ios.post([&ios]{ std::cout << __LINE__ << std::endl; }); }); }); ios.run(); } http://melpon.org/wandbox/permlink/lXbFTVurVNUXM8BZ 7 9 11 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 処理の中で次のリクエストをpost
10.
2つのスケーラビリティ 2016/7/23 10 • マルチスレッド •
マルチノード(マルチサーバ)
11.
マルチスレッドにスケールアウト 2016/7/23 11 broker client connection boost::asio::io_service on
1 thread client client コアを有効活用したい
12.
マルチスレッドにスケールアウト 2016/7/23 12 #include <iostream> #include
<thread> #include <boost/asio.hpp> int main() { boost::asio::io_service ios; ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); std::vector<std::thread> ths; ths.emplace_back([&ios]{ ios.run(); }); ths.emplace_back([&ios]{ ios.run(); }); ths.emplace_back([&ios]{ ios.run(); }); ths.emplace_back([&ios]{ ios.run(); }); ths.emplace_back([&ios]{ ios.run(); }); for (auto& t : ths) t.join(); std::cout << "finished" << std::endl; } http://melpon.org/wandbox/permlink/z5bQJYgO23tvM9XF 8 9 10 11 7 finished 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 実行順序はpostの順序とは異なる
13.
マルチスレッドにスケールアウト 2016/7/23 13 broker client connection client client ios client thread
threadthread
14.
subscriber Pub/Subモデルとロック 2016/7/23 14 subscriber topic publisher subscribers_ subscribe subscribe subscribe unsubscribe 排他ロック publish 対象のsubscriberに配送 共有ロック
15.
webserver マルチノードにスケールアウト 2016/7/23 15 client client
client load balancer webserver webserver 毎回コネクションを切断する、Webサーバなどは スケールアウトがシンプル
16.
broker brokerbroker マルチノードにスケールアウト 2016/7/23 16 client client
client client Pub/Subモデルはコネクション型通信のため、 Webサーバのようなリクエスト毎の切断を 前提とするロードバランス戦略をとれない 情報の転送が必要 publisher subscriber load balancer or dispatcher hello
17.
broker brokerbroker マルチノードにスケールアウト 2016/7/23 17 client client
client client ルーティングなどの 情報の同期が必要 publisher subscriber 同期中 publish/Defer 同期済み publish/配信処理 同期完了 イベント処理の遅延 ステートマシンが常に必須とは限らないが、 今回は必要であると仮定する。
18.
msmとasioの組み合わせ 2016/7/23 18 boost::asio::async_read( socket_, boost::asio::buffer(payload_), [this]( boost::system::error_code const&
ec, std::size_t bytes_transferred){ // error checking ... // 受信時の処理 } ); boost::shared_lock<mutex> guard(mtx_subscribers_); auto& idx = subscribers_.get<tag_topic>(); auto r = idx.equal_range(topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; boost::asio::write(socket, boost::asio::buffer(payload_)); } 全てのsubscriberに対して publish内容を配信 msm導入前
19.
msmとasioの組み合わせ 2016/7/23 19 struct transition_table:mpl::vector< //
Start Event Next Action Guard msmf::Row < s_normal, e_pub, msmf::none, a_pub, msmf::none >, msmf::Row < s_sync, e_pub, msmf::none, msmf::Defer, msmf::none > > {}; struct a_pub { template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; boost::asio::write(socket, boost::asio::buffer(e.payload)); } } }; // boost::asio::async_read ハンドラ内にて process_event(e_pub(topic, payload)); msm導入後 受信時の処理は アクションに移動 イベントの遅延が可能 イベントを処理すると 現在状態に応じた アクションが実行される
20.
msmとスレッド 2016/7/23 20 process_event()の呼び出しはserializeされなければならない
21.
msmとスレッド 2016/7/23 21 同期中 publish/Defer 同期済み publish/配信処理 同期完了 process_event()の呼び出しはserializeされなければならない 複数のスレッドで同時に状態遷移が起こると、 msmの内部状態がおかしくなるのであろう // boost::asio::async_read
ハンドラ内にて process_event(e_pub(topic, payload)); ここに排他ロックが必要となる subscribersubscriberpublish受信 subscriber subscribersubscriberpublish受信 subscriber 配信 配信 別々の受信でも順番に処理せねばならない
22.
msmとスレッド 2016/7/23 22 排他ロック 共有ロック 排他ロック 共有ロック
23.
msmとasioの組み合わせ 2016/7/23 23 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; boost::asio::write(socket, boost::asio::buffer(e.payload)); } }); } }; 排他ロックの必要な範囲では、ios.post()のみ行い、 ios.post()に渡した処理が呼び出されるところで、 共有ロックを行う subscribersubscriberpublish受信 subscriber subscribersubscriberpublish受信 subscriber post post postのみserialize 並行処理が可能
24.
msmとasioの組み合わせ 2016/7/23 24 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; boost::asio::write(socket, boost::asio::buffer(e.payload)); } }); } }; 排他ロックの必要な範囲では、ios.post()のみ行い、 ios.post()に渡した処理が呼び出されるところで、 共有ロックを行う 注意点 ・処理の遅延に問題は無いか? ・ios.post()に渡した処理が参照するオブジェクトは生存しているか?
25.
forループの処理もpostすれば。。。 2016/7/23 25 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; ios.post([&socket, e]{ boost::asio::write(socket, boost::asio::buffer(e.payload)); }); } }); } }; ループの中で行われるwrite()が並列化され、パフォーマンスの向上が見込める
26.
struct a_pub { template
<typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; ios.post([&socket, e]{ boost::asio::write(socket, boost::asio::buffer(e.payload)); }); } }); } }; forループの処理もpostすれば。。。 2016/7/23 26 publish受信 subscriber post postのみserialize 並行処理が可能 post subscriber subscriber publish受信 subscriber post 並行処理が可能 post subscriber subscriber 並行処理が可能 排他ロック 共有ロック
27.
broker forループの処理もpostすれば。。。 2016/7/23 27 client client publisher subscriber 1. subscribe 2.
ack 3. publish(data) 4. data 1と3がほぼ同時に発生した場合、subscriberから見て許容される振る舞いは、 2, 4の順で受信 (1が3よりも先にbrokerで処理された場合) または 2のみ受信 (1が3よりも後にbrokerで処理された場合) 4, 2の順で受信が発生してはならない。 (ackの前にdata到着)
28.
broker forループの処理もpostすれば。。。 2016/7/23 28 client client publisher subscriber 1. unsubscribe 2.
data 3. publish(data) 4. ack 1と3がほぼ同時に発生した場合、subscriberから見て許容される振る舞いは、 2, 4の順で受信 (1が3よりも先にbrokerで処理された場合) または 4のみ受信 (1が3よりも後にbrokerで処理された場合) 4, 2の順で受信が発生してはならない。 (ackの後にdata到着)
29.
forループの処理もpostすれば。。。 2016/7/23 29 #include <iostream> #include
<thread> #include <boost/asio.hpp> int main() { boost::asio::io_service ios; ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); ios.post([]{ std::cout << __LINE__ << std::endl; }); std::vector<std::thread> ths; ths.emplace_back([&ios]{ ios.run(); }); ths.emplace_back([&ios]{ ios.run(); }); ths.emplace_back([&ios]{ ios.run(); }); ths.emplace_back([&ios]{ ios.run(); }); ths.emplace_back([&ios]{ ios.run(); }); for (auto& t : ths) t.join(); std::cout << "finished" << std::endl; } http://melpon.org/wandbox/permlink/z5bQJYgO23tvM9XF 8 9 10 11 7 finished 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 実行順序はpostの順序とは異なる
30.
forループの処理もpostすれば。。。 2016/7/23 30 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; ios.post([&socket, e]{ boost::asio::write(socket, boost::asio::buffer(e.payload)); }); } }); } }; unsubscribe処理を行い、ackを返送した後に、この処理が実行されることがある
31.
問題はどこにあるのか? 2016/7/23 31 • 同一コネクションに対する送信の順序を 保証したいが、 •
io_service::post()を使うことで、順序の保証が できなくなっている • しかし、ループ処理の並列化は行いたい • コネクションとの対応付けを考慮した、 処理のpostが行えれば良い
32.
boost::asio::async_write 2016/7/23 32 現実的には、このハンドラ内で次のasync_writeを呼ぶことになる
33.
boost::asio::async_write 2016/7/23 33 template <typename
F> void my_async_write( std::shared_ptr<std::string> const& buf, F const& func) { strand_.post( [this, buf, func] () { queue_.emplace_back(buf, func); if (queue_.size() > 1) return; my_async_write_imp(); } ); } まずenque データは、バッファと完了ハンドラ 未完了のasync_writeがあるなら 何もせず終了 async_writeの呼び出し処理 制約無く、いつでも呼べる、async_writeを作るには、 自前でキューイングなどの処理を実装する必要がある。
34.
boost::asio::async_write 2016/7/23 34 void my_async_write_imp()
{ auto& elem = queue_.front(); auto const& func = elem.handler(); as::async_write( socket_, as::buffer(elem.ptr(), elem.size()), strand_.wrap( [this, func] (boost::system::error_code const& ec, std::size_t bytes_transferred) { func(ec); queue_.pop_front(); if (!queue_.empty()) { my_async_write_imp(); } } ) ); } queueからデータを取り出して、 async_write まだqueueにデータがあれば、 再びasync_write queueからデータを消去し strand_.post() および strand_.wrap() を用いて、 排他制御を行っている queue_ だけ mutex でロックするのと何が違うのか?
35.
async_readもstrand wrapする 2016/7/23 35 boost::asio::async_read( socket_, boost::asio::buffer(payload_), strand_.wrap( [this]( boost::system::error_code
const& ec, std::size_t bytes_transferred){ // error checking ... // 受信時の処理 } ) ); async_readもstrand経由で処理する
36.
strandは本当に必要か? 2016/7/23 36 strandしなくても、暗黙的にstrandになるケース
37.
publish処理 2016/7/23 37 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; socket.my_async_write(boost::asio::buffer(e.payload), 完了ハンドラ); } }); } }; 自前の非同期writeを呼び出す subscribe / unsubscribe の ack送信処理も、同様に、 自前の非同期writeを経由させることで、順序の入れ替わりを 防ぎ、かつ、処理の並列化を実現することができる
38.
publish処理 2016/7/23 38 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; socket.my_async_write(boost::asio::buffer(e.payload), 完了ハンドラ); } }); } }; 自前の非同期writeを呼び出す publish受信 subscriber post postのみserialize 並行処理が可能 かつ 同一接続に対しては シリアライズ my_async_write subscriber subscriber publish受信 subscriber post subscriber subscriber 並行処理が可能 排他ロック 共有ロック my_async_write 並行処理が可能 かつ 同一接続に対しては シリアライズ
39.
publish処理 2016/7/23 39 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; socket.my_async_write(boost::asio::buffer(e.payload), 完了ハンドラ); } }); } }; 自前の非同期writeを呼び出す 非同期writeは十分に軽量であるため、forループの所要時間は短かった。 排他ロックの中で処理を行ってもパフォーマンスは落ちなかった。 よってシンプルな実装を採用した。(グレーの部分のコードを削除した)
40.
publish処理 2016/7/23 40 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; socket.my_async_write(boost::asio::buffer(e.payload), 完了ハンドラ); } }); } }; 自前の非同期writeを呼び出す publish受信 subscriber post postのみserialize 並行処理が可能 かつ 同一接続に対しては シリアライズ my_async_write subscriber subscriber publish受信 subscriber post subscriber subscriber 並行処理が可能 排他ロック 共有ロック my_async_write 並行処理が可能 かつ 同一接続に対しては シリアライズ
41.
publish処理 2016/7/23 41 struct a_pub
{ template <typename Event, typename Fsm, typename Source, typename Target> void operator()(Event const& e, Fsm& f, Source&, Target&) const { ios.post([&f, e]{ boost::shared_lock<mutex> guard(f.mtx_subscribers_); auto& idx = f.subscribers_.get<tag_topic>(); auto r = idx.equal_range(e.topic); for (; r.first != r.second; ++r.first) { auto& socket = r.first->socket; socket.my_async_write(boost::asio::buffer(e.payload), 完了ハンドラ); } }); } }; 自前の非同期writeを呼び出す publish受信 subscriber my_async_writeのみserialize 並行処理が可能 かつ 同一接続に対しては シリアライズ my_async_write subscriber subscriber publish受信 subscriber subscriber subscriber 排他ロック my_async_write 並行処理が可能 かつ 同一接続に対しては シリアライズ
42.
まとめ 2016/7/23 42 • io_serviceを複数スレッドでrun()することで、 コアを有効利用できる •
msmのDeferはイベント処理を遅延できて便利 • その一方、msmの状態遷移は排他制御を要求する • post()を利用することで任意の処理を、 遅延でき、ロックの最適化が可能となる • post()はコネクションを意識しないので、 マルチスレッドの場合、実行順序が保証されない • 通信では同一コネクションに対して、 順序を保証したいことがよくある • そんなときは、async_write()が使える • 好きなタイミングで呼べるasync_write()は 自分で実装する必要がある • キューイング処理とasync_writeハンドラに加え、 async_read()も合わせてstrandする必要がある
Descargar ahora