Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Wangle调研
chenxiaojie@qiyi.com
2016.07.16
Content
• Example
• Features
• Architecture
• Summary
Example
Server
ServerBootstrap<SerializePipeline>()
// .pipeline(RoutingDataPipelineFactory())
.childPipeline(RpcPipelineFactory()...
Server Bootstrap
Pipeline
class RpcPipelineFactory : public … {
public:
SerializePipelinePtr newPipeline(AsyncTransport sock) {
auto pipeli...
Pipeline
LengthFieldBasedFrameDecoder
EventBaseHandler
AsyncSocketHandler
event
LengthFieldPrepender
ServerSerializeHandle...
RPC Protocol
class ServerSerializeHandler : public … {
public:
void read(Context* ctx, IOBuf msg) override {
Bonk received...
RPC Handler
class RpcService : public Service<Bonk, Xtruct> {
public:
virtual Future<Xtruct> operator()(Bonk request) over...
Client
ClientBootstrap<SerializePipeline> client;
auto pipeline = client
.client.group(IOThreadPoolExecutor>());
.client.p...
Pipeline
class RpcPipelineFactory : public … {
public:
SerializePipelinePtr newPipeline(AsyncTransport sock) override {
au...
Pipeline
LengthFieldBasedFrameDecoder
EventBaseHandler
AsyncSocketHandler
LengthFieldPrepender
ClientSerializeHandler
Serv...
RPC Protocol
class ClientSerializeHandler : public … {
public:
void read(Context* ctx, IOBuf msg) override {
Xtruct receiv...
RPC Handler
class BonkMultiplexClientDispatcher : public … {
public:
void read(Context* ctx, Xtruct in) override {
auto se...
Features
Executor
• IOThreadPoolExecutor:
• IO intensive
• one event loop, notification queue(eventfd) per thread
• round robin, us...
MPMC Queue
• LIFO Semaphore:
• approximately LIFO
• multi-post, exact wakeups, fewer system calls than sem_t
• MPMC Queue:...
MPMC Queue
Service
• Client Dispatcher:
• SerialClientDispatcher: one request is allowed at a time
• PipelinedClientDispatcher: use a...
Overload Protection
• CoDel:
• Controlled Delay
• an active queue management algorithm
• attacking bufferbloat
• if every ...
Connection Routing
class NaiveRoutingDataHandler : public … {
public:
bool parseRoutingData(IOBufQueue& bufQueue, RoutingD...
Parallel Computing
vector<Future<int>> futures;
for (int channel = 0; channel < 10; ++channel) {
futures.emplace_back(make...
Parallel Computing
vector<Future<map<int, Entity>>> segments;
for (int segment = 0; segment < 10; ++segment) {
segments.em...
Architecture
EventBase
• based on libevent::event_base
• NotificationQueue:
• producer-consumer
• passing messages between EventBase th...
SmoothLoopTime
• dynamically adjusting loop time
• EMA Algorithm (Exponential Moving Average)
• https://en.wikipedia.org/w...
Acceptor
• Acceptor IO Executor
• multi-IP (SO_REUSEADDR), multi-thread accept (SO_REUSEPORT)
• bind, listen, accept4 (max...
Group
Server
Bootstrap
create
Server
WorkerPool
ServerAcceptor
Factory
IOExecutor
(io_group)
Server
Acceptor
create
addObs...
Bind
Server
Bootstrap
IOExecutor
(accept_group)
AsyncServer
SocketFactory
Async
ServerSocket
newSocket
create
bind、listen
...
Bind
Server
Bootstrap
forEacherWorker
Server
WorkerPool
EventBase
(acceptor_group)
AsyncServer
SocketFactory
runAddAcceptC...
Accept
EventBase
(accept_group)
handlerReady
Server
EventHandler
Async
ServerSocket
handlerReady
accept4
connectionEventCa...
Connection
RemoteAcceptor
EventBase
(io_group)
ServerAcceptor
mesageAvailable
connectionAccepted
AcceptPipeline
read
read
...
Connection
Procedure
Pipeline
• HandlerContext:
• transmit events between handlers
• In/OutboundLink:
• link handlers together in order
• call ...
Pipeline
<<接口>>
HandlerBase<Context>
-attachPipeline
-detachPipeline
<<接口>>
HandlerContext<In,Out>
-fireRead
-fireReadEOF
...
Pipeline
events
Pipeline
Context
Handler
read
read
fireRead
NextHandler
read
NextHandler
fireRead
read
Futures
• f.via(e).then(a).then(b)
• via:
• set executor
• then:
• make a new future/promise pair
• set callback:
• functi...
Core
• shared state object for Future and Promise
• reference count: Future, Promise, Executor
• callback and result
• act...
Chained Future
Future<R> then(Func func) {
Promise<R> p;
Future<R> f = p.getFuture();
setCallback([func, p](Try t) {
if (t...
Chained Future
Future<vector<string>> f = makeFuture<int>(3)
.then([](int i) {
return to_string(i);
})
.then([](string s) ...
Chained Future
Future<R> onError(Func func) {
Promise<R> p;
Future<R> f = p.getFuture();
setCallback([func, p](Try t) {
if...
Summary
Proxygen
• Facebook's C++ HTTP Libraries
• comprises the core C++ HTTP abstractions used at Facebook
Netty
Reference
• https://github.com/facebook/wangle
• https://github.com/facebook/folly
• https://github.com/facebook/proxygen
...
Thank you
Upcoming SlideShare
Loading in …5
×

Facebook C++网络库Wangle调研

556 views

Published on

Facebook Network Library Wangle Research

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Facebook C++网络库Wangle调研

  1. 1. Wangle调研 chenxiaojie@qiyi.com 2016.07.16
  2. 2. Content • Example • Features • Architecture • Summary
  3. 3. Example
  4. 4. Server ServerBootstrap<SerializePipeline>() // .pipeline(RoutingDataPipelineFactory()) .childPipeline(RpcPipelineFactory()) // .group(IOThreadPoolExecutor(), IOThreadPoolExecutor()) // .acceptorConfig(…) .bind(6666) .waitForStop();
  5. 5. Server Bootstrap
  6. 6. Pipeline class RpcPipelineFactory : public … { public: SerializePipelinePtr newPipeline(AsyncTransport sock) { auto pipeline = SerializePipeline::create(); pipeline->addBack(AsyncSocketHandler(sock)); pipeline->addBack(EventBaseHandler()); pipeline->addBack(LengthFieldBasedFrameDecoder()); pipeline->addBack(LengthFieldPrepender()); pipeline->addBack(ServerSerializeHandler()); pipeline->addBack(MultiplexServerDispatcher<Bonk, Xtruct>(&service_)); pipeline->finalize(); return pipeline; } private: RpcService<Bonk, Xtruct> service_; };
  7. 7. Pipeline LengthFieldBasedFrameDecoder EventBaseHandler AsyncSocketHandler event LengthFieldPrepender ServerSerializeHandler MultiplexServerDispatcher Service LengthFieldBasedFrameDecoder EventBaseHandler AsyncSocketHandler LengthFieldPrepender ServerSerializeHandler MultiplexServerDispatcher
  8. 8. RPC Protocol class ServerSerializeHandler : public … { public: void read(Context* ctx, IOBuf msg) override { Bonk received; ser.deserialize<Bonk>(msg, &received); ctx->fireRead(received); } Future<Unit> write(Context* ctx, Xtruct b) override { string out; ser.serialize<Xtruct>(b, &out); return ctx->fireWrite(out); } private: ThriftSerializerCompact<> ser; };
  9. 9. RPC Handler class RpcService : public Service<Bonk, Xtruct> { public: virtual Future<Xtruct> operator()(Bonk request) override { return makeFuture() .via(getIOExecutor()) .then(getCouchbaseResult()) .via(getCpuExecutor()) .then(calculate1()) .via(getIOExecutor()) .then(getCtrServerResult()) .then(calculate2()) .then(getRedisResult()) .then(calculate3()) .then(sendResponse()); } };
  10. 10. Client ClientBootstrap<SerializePipeline> client; auto pipeline = client .client.group(IOThreadPoolExecutor>()); .client.pipelineFactory(RpcPipelineFactory()); .client.connect(address).get(); BonkMultiplexClientDispatcher service; service.setPipeline(pipeline); while (true) { Bonk request; service(request).then([](Xtruct response) { cout << response.string_thing << endl; }); }
  11. 11. Pipeline class RpcPipelineFactory : public … { public: SerializePipelinePtr newPipeline(AsyncTransport sock) override { auto pipeline = SerializePipeline::create(); pipeline->addBack(AsyncSocketHandler(sock)); pipeline->addBack(EventBaseHandler()); pipeline->addBack(LengthFieldBasedFrameDecoder()); pipeline->addBack(LengthFieldPrepender()); pipeline->addBack(ClientSerializeHandler()); pipeline->finalize(); return pipeline; } };
  12. 12. Pipeline LengthFieldBasedFrameDecoder EventBaseHandler AsyncSocketHandler LengthFieldPrepender ClientSerializeHandler Service EventBase LengthFieldBasedFrameDecoder EventBaseHandler AsyncSocketHandler LengthFieldPrepender ClientSerializeHandler
  13. 13. RPC Protocol class ClientSerializeHandler : public … { public: void read(Context* ctx, IOBuf msg) override { Xtruct received; ser.deserialize<Xtruct>(msg, &received); ctx->fireRead(received); } Future<Unit> write(Context* ctx, Bonk b) override { string out; ser.serialize<Bonk>(b, &out); return ctx->fireWrite(out); } private: ThriftSerializerCompact<> ser; };
  14. 14. RPC Handler class BonkMultiplexClientDispatcher : public … { public: void read(Context* ctx, Xtruct in) override { auto search = requests_.find(in.i32_thing); auto p = move(search->second); requests_.erase(in.i32_thing); p.setValue(in); } Future<Xtruct> operator()(Bonk arg) override { auto& p = requests_[arg.type]; auto f = p.getFuture(); this->pipeline_->write(arg); return f; } private: unordered_map<int32_t, Promise<Xtruct>> requests_; };
  15. 15. Features
  16. 16. Executor • IOThreadPoolExecutor: • IO intensive • one event loop, notification queue(eventfd) per thread • round robin, user define • MPSC • CPUThreadPoolExecutor: • CPU intensive • multi-threads single queue • MPMC Queue, LIFO wakeup, cache efficiency • ThreadedExecutor • FiberIOExecutor(stackful) • FutureExecutor
  17. 17. MPMC Queue • LIFO Semaphore: • approximately LIFO • multi-post, exact wakeups, fewer system calls than sem_t • MPMC Queue: • fixed capacity, blocking or throw exception • incremental ticket based, item index = hash(ticket) • if holds item, wait for turn, else write the element • a read ticket with same growing rule • get the right version of element with ticket turn • false sharing: • advance by stride slots per ticket • futex: • Fast Userspace muTEXes, userspace (no competition), kernel space (wait, wakeup) • tbb::concurrent_bounded_queue
  18. 18. MPMC Queue
  19. 19. Service • Client Dispatcher: • SerialClientDispatcher: one request is allowed at a time • PipelinedClientDispatcher: use a promises queue for pipelining • Server Dispatcher: • SerialServerDispatcher: one at a time synchronously • PipelinedServerDispatcher: queued with a request id until they can be sent in order • MultiplexServerDispatcher: dispatch as they come in • Common Filter: • ExpiringFilter: expires the service after a certain amount of time • ExecutorFilter: through an executor
  20. 20. Overload Protection • CoDel: • Controlled Delay • an active queue management algorithm • attacking bufferbloat • if every request has experienced queuing delay greater than the target (5ms) during the past interval (100ms), then shed load • slough off requests which have exceeded an alternate timeout (2 * target_delay) • back to normal if delay down to 5ms • application case: RabbitMQ
  21. 21. Connection Routing class NaiveRoutingDataHandler : public … { public: bool parseRoutingData(IOBufQueue& bufQueue, RoutingData& routingData) override { auto buf = bufQueue.move(); buf->coalesce(); routingData.routingData = buf->data()[0]; routingData.bufQueue.append(buf); return true; } }; ServerBootstrap<DefaultPipeline> .pipeline(AcceptRoutingPipelineFactory(…));
  22. 22. Parallel Computing vector<Future<int>> futures; for (int channel = 0; channel < 10; ++channel) { futures.emplace_back(makeFuture().then([channel] { int sum = 0; for (int i = 100 * channel; i < 100 * channel + 100; ++i) { sum += i; } return sum; })); } collectAll(futures.begin(), futures.end()) .then([](vector<Try<int>>&& parts) { for (auto& part : parts) { cout << part.value() << endl; } });
  23. 23. Parallel Computing vector<Future<map<int, Entity>>> segments; for (int segment = 0; segment < 10; ++segment) { segments.emplace_back(makeFuture().then([] { map<int, Entity> result; // fill segment result return result; })); } Future<map<int, Entity>> entities = reduce(segments, {}, [](map<int, Entity> last, map<int, Entity> current) { // merge current into last });
  24. 24. Architecture
  25. 25. EventBase • based on libevent::event_base • NotificationQueue: • producer-consumer • passing messages between EventBase threads • use an eventfd • loop(): • before loop callbacks • event_base_loop • loop callbacks, busy • time measurement • run NotificationQueue events
  26. 26. SmoothLoopTime • dynamically adjusting loop time • EMA Algorithm (Exponential Moving Average) • https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average 2 lastbusy busy idle idle + = + _int _int 1 (1 ) idle idle time erval time erval i iEMA EMA e e busy − − −= × + − ×
  27. 27. Acceptor • Acceptor IO Executor • multi-IP (SO_REUSEADDR), multi-thread accept (SO_REUSEPORT) • bind, listen, accept4 (max accept at once) • connection event callback • adjusting connection accept rate • put accept info into a NotificationQueue • build connection info via Connection IO Executor • active accept pipeline (Acceptor) read • fire child pipeline
  28. 28. Group Server Bootstrap create Server WorkerPool ServerAcceptor Factory IOExecutor (io_group) Server Acceptor create addObserver newAcceptor forEachThread threadStarted create Connection Manager create
  29. 29. Bind Server Bootstrap IOExecutor (accept_group) AsyncServer SocketFactory Async ServerSocket newSocket create bind、listen wait addStartupFunction
  30. 30. Bind Server Bootstrap forEacherWorker Server WorkerPool EventBase (acceptor_group) AsyncServer SocketFactory runAddAcceptCB InEventBase addAcceptCallback Async ServerSocket addAcceptCallabck Remote Acceptor create EventBase (io_group) runStartConsuming InEventBase initEventfd NotificationQueue (AsyncServerSocket) Server EventHandler registerAcceptHandler addAcceptCallback register EventHandler addEventCallback
  31. 31. Accept EventBase (accept_group) handlerReady Server EventHandler Async ServerSocket handlerReady accept4 connectionEventCallback acceptRateAdjust RemoteAcceptor tryPutMessage EventBase (io_group) signal
  32. 32. Connection RemoteAcceptor EventBase (io_group) ServerAcceptor mesageAvailable connectionAccepted AcceptPipeline read read Server Connection init Connection Pipeline transportActive
  33. 33. Connection
  34. 34. Procedure
  35. 35. Pipeline • HandlerContext: • transmit events between handlers • In/OutboundLink: • link handlers together in order • call handler to handle events • PipelineContext: • derived from HandlerContext and In/OutboundLink • directions: In, Out, Both • Pipeline<In, Out>: • HandlerContext: wrap Handler • chain: • event (like read) --> PipelineContext (as In/OutboundLink)::read -->Handler::read --> PipelineContext (as HandlerContext)::fireRead -->NextHandler::read --> …
  36. 36. Pipeline <<接口>> HandlerBase<Context> -attachPipeline -detachPipeline <<接口>> HandlerContext<In,Out> -fireRead -fireReadEOF -fireReadException -fireTransportActive -fireTransportInactive -fireWrite -fireWriteException -fireClose <<接口>> InboundHandlerContext<In> -fireRead -fireReadEOF -fireReadException -fireTransportActive -fireTransportInactive <<接口>> OutboundHandlerContext<Out> -fireWrite -fireWriteException -fireClose <<接口>> Handler<RIn,ROut,WIn,WOut> -read -readEOF -readException -transportActive -transportInactive -write -writeException -close <<接口>> InboundHandler<RIn,ROut,WIn,WOut> -read -readEOF -readException -transportActive -transportInactive <<接口>> OutboundHandler<RIn,ROut,WIn,WOut> -write -writeException -close <<类>> HandlerAdapter<RIn,ROut,WIn,WOut> <<类>> PipelineBase <<类>> Pipeline<In,Out> -read -readEOF -readException -transportActive -transportInactive -write -writeException -close <<接口>> PipelineContext -attachPipeline -detachPipeline <<接口>> InboundLink<In> -read -readEOF -readException -transportActive -transportInactive <<接口>> OutboundLink<Out> -write -writeException -close -setNextOut -setNextIn <<类>> ContextImplBase<Handler,Context> <<类>> ContextImpl<Handler> <<类>> InboundContextImpl<Handler> <<类>> OutboundContextImpl<Handler>
  37. 37. Pipeline events Pipeline Context Handler read read fireRead NextHandler read NextHandler fireRead read
  38. 38. Futures • f.via(e).then(a).then(b) • via: • set executor • then: • make a new future/promise pair • set callback: • function result will be set in the new promise • return its future
  39. 39. Core • shared state object for Future and Promise • reference count: Future, Promise, Executor • callback and result • activated by Future Destructor • Finite State Machine: • Try: • value and exception
  40. 40. Chained Future Future<R> then(Func func) { Promise<R> p; Future<R> f = p.getFuture(); setCallback([func, p](Try t) { if (t.hasException) { p.setException(t.exception); } else { p.setWith([&]() { return func(t.get()); }); } }); return f; }
  41. 41. Chained Future Future<vector<string>> f = makeFuture<int>(3) .then([](int i) { return to_string(i); }) .then([](string s) { return vector<string>(s, 10); });
  42. 42. Chained Future Future<R> onError(Func func) { Promise<R> p; Future<R> f = p.getFuture(); setCallback([func, p](Try t) { if (!t.withException([](Exp e) { p.setWith([&] { return func(e); }); })) { p.setTry(t); } } return f; }
  43. 43. Summary
  44. 44. Proxygen • Facebook's C++ HTTP Libraries • comprises the core C++ HTTP abstractions used at Facebook
  45. 45. Netty
  46. 46. Reference • https://github.com/facebook/wangle • https://github.com/facebook/folly • https://github.com/facebook/proxygen • http://twitter.github.io/finagle • http://netty.io
  47. 47. Thank you

×