Proxygenã¯ãApacheãnginxã«ä»£ãããã®ãšããŠã¯èããããŠããŸããã§ããããããã®ãããžã§ã¯ãã¯ãæ倧éã®ããã©ãŒãã³ã¹ãéæããããã®åŸ®èª¿æŽãå¯èœã«ããååã«æè»ã§æ§æå¯èœãªWebãµãŒããŒã®äœæã«çŠç¹ãåœãŠãŠããŸãã Proxygenã®ã¿ã¹ã¯ã¯ãæ¢å®ã®èšå®ã§éåžžã«ããŸãæ©èœããããšã§ãããæ¢åã®ãããžã§ã¯ãã«ç°¡åã«çµ±åã§ãã䜿ããããWebãµãŒããŒãšWebã¯ã©ã€ã¢ã³ããããã°ã©ããŒã«æäŸããŸãã äœã³ã¹ãã§C ++ã§WebãµãŒãã¹ãæ§ç¯ãã人ã ãæ¯æŽãããã®ã§ãProxygenã¯ãã®ããã®åªãããã¬ãŒã ã¯ãŒã¯ã§ãããšèããŠããŸãã ãã®ããã¥ã¡ã³ããèªãã§ã Githubã®éçºã«æ¥ç¶ã§ããŸãã
èæ¯
Proxygenã¯ãçŽ4幎åã«è² è·åæ£ãè¡ãã«ã¹ã¿ã é«æ§èœãªããŒã¹ãããã·ãäœæãããããžã§ã¯ããšããŠå§ãŸããŸããã Proxygenããããã·ãµãŒããŒãçæããããã®ã©ã€ãã©ãªã«ãªãããšãèšç»ããŸããïŒããããProxygenãšããååããæšæž¬ããã§ãããïŒã ãããããã以æ¥ãããã¯çå£ã«é²åããŸããã ãã®ãããªåé¡ïŒApacheãnginxãHAProxyãVarnishãªã©ïŒã解決ããããã°ã©ã ãæ¢ã«ååã«ããããšã¯æ¿ç¥ããŠããŸãããç§ãã¡ã¯ç¬èªã®æ¹æ³ã§é²ãããšã«ããŸããã
ãªãç¬èªã®HTTPã¹ã¿ãã¯ãäœæããã®ã§ããïŒ
çµ±å
æ¢åã®Facebookã€ã³ãã©ã¹ãã©ã¯ãã£ã«ãã°ããç°¡åã«çµ±åã§ããããšãéèŠã§ããã ããšãã°ã Thriftãªã©ã®ããŒã«ã䜿çšããŠHTTPã€ã³ãã©ã¹ãã©ã¯ãã£ã管çããæ©èœã¯ãæ¢åã®ã·ã¹ãã ãšã®çµ±åãç°¡çŽ åããŸãã ODS ïŒåœç€Ÿã®å éšç£èŠããŒã«ïŒãªã©ã®ã·ã¹ãã ã䜿çšããŠProxygenã®ããã©ãŒãã³ã¹ãç°¡åã«ç£èŠããã³æž¬å®ã§ãããããæ°ããããŒã¿ã«è¿ éã«å¯Ÿå¿ããŠè£œåãå€æŽã§ããŸãã ç¬èªã®HTTPã¹ã¿ãã¯ãäœæããããšã§ãå¿ èŠãªã·ã¹ãã ãã³ã³ããŒãã³ããšããå¯æ¥ã«å¯Ÿè©±ããæ©äŒãåŸãããŸããã
ã³ãŒãã®åå©çš
ãã¹ãŠã®ãããžã§ã¯ãã®ãããã¯ãŒã¯ã³ã³ããŒãã³ããæ§ç¯ããããã®åºç€ãäœãããã£ãã®ã§ãã çŸåšã Haystack ã HHVM ãHTTPãã©ãã£ãã¯ãã©ã³ãµãŒãã¢ãã€ã«ã€ã³ãã©ã¹ãã©ã¯ãã£ã®äžéšãªã©ã®ã·ã¹ãã ã®äžéšãå«ãã12ãè¶ ããå éšã·ã¹ãã ãProxygenã䜿çšããŠæ§ç¯ãããŠããŸãã Proxygenã¯ãããšãã°ãHTTP / 2ãããã³ã«ã®ãµããŒãã«åãçµãããšãã§ãããã©ãããã©ãŒã ã§ãããå®å šã«æºåãæŽã次第ããã¹ãŠã®è£œåã§ãµããŒããåããããšãã§ããŸãã
æ¡åŒµæ§
ç§ãã¡ã¯ãæ¢åã®è£œåãã€ã³ãã©ã¹ãã©ã¯ãã£å šäœã«æ¡åŒµããããšãæ£çŽã«è©Šã¿ãŸããã ããŸããããã®ãããã°ãé·ãéæ©èœãããã®ããããŸããã ããããããæç¹ã§ã䜿çšãããŠãã補åã容éã®å¢å ã«è¿œãã€ããŠããªãããšãå€æããŸããã
æ©èœç
ProxygenãæžããŠããæç¹ã§ç¹å®ã®æ°ã®æ©èœãä»ã®åæ§ã®ãããžã§ã¯ãã«ã¯ååšããŠããŸããã§ããïŒãããŠãçŸåšãããã€ãæ¬ èœããŠããŸãïŒã ãããã®æ©èœã®äžéšã¯ãSPDYãWebSocketãHTTP / 1.1ïŒããŒãã¢ã©ã€ãïŒãTLS-falseã¹ã¿ãŒããè² è·åæ£ã®äžéšã®æ©èœã«éåžžã«åœ¹ç«ã¡ãŸãã ç¬èªã®HTTPã¹ã¿ãã¯ãæ§ç¯ããããšã§ããã®æ©èœãå®è£ ãããšããç¹ã§æã解æŸããŸããã
Proxygenã¯ãHTTPãããã³ã«ãããå¹ççã«äœ¿çšããããšãç®æããŠããè€æ°ã®ãšã³ãžãã¢ã«ãã£ãŠ2011幎ã«æåã«éå§ãããŸãããProxygenã¯ã3ã4人ã®äž»èŠéçºè ãšå€æ°ã®å éšè²¢ç®è ã®ããŒã ã«ãã£ãŠéçºãããŸããã ãããžã§ã¯ãã®ãã€ã«ã¹ããŒã³ïŒ
- 2011-Proxygenã®éçºã®å§ãŸãã åã幎ã«ããããžã§ã¯ãã¯å®éã®Facebookãã©ãã£ãã¯ã®äžéšã®åŠçãéå§ããŸããã
- 2012-SPDY / 2ãµããŒãã®è¿œå ã
- 2013-SPDY / 3.1ã®äœæ¥ã®å§ãŸãã§ããå®çšŒåSPDY / 3ã§ã®ãªãªãŒã¹
- 2014-å®çšŒåSPDY / 3.1ã§ã®ãªãªãŒã¹ãHTTP / 2ã§ã®äœæ¥éå§
éçºã«ã¯ããã«éèŠãªãã€ã³ããããã€ããããŸããã ã³ãŒãã¯ãã®è©±ãç§ãã¡ãããããŸãäŒãããšæããŸãã
çŸåšãProxygenã䜿çšããæ°å¹Žã®çµéšããããŸãã ã©ã€ãã©ãªã¯ããã§ã«äœå ãã®HTTPïŒSïŒããã³SPDYèŠæ±ãåŠçããŠããŸãã ç§ãã¡ã¯ããã®ãããžã§ã¯ããã³ãã¥ããã£ãšå ±æããããšãæ¥ããŠããªã段éã«ãã§ã«éããŠãããšä¿¡ããŠããŸãã
建ç¯
HTTPã¬ã€ã€ãŒã®ã³ã¢ã¯ãã»ãã·ã§ã³ãã³ãŒããã¯ããã©ã³ã¶ã¯ã·ã§ã³ããã³ãã©ãŒã®4ã€ã®æœè±¡åã«åãããŠããŸãã ã»ãã·ã§ã³ã¯æ¥ç¶ããšã«äœæãããŸãã åã»ãã·ã§ã³ã«ã¯ããã¬ãŒã ãHTTPã¡ãã»ãŒãžã«ã·ãªã¢ã©ã€ãºããã³ãã·ãªã¢ã©ã€ãºããããã®ã³ãŒããã¯ããããŸãã ã»ãã·ã§ã³ã¯ãã³ãŒããã¯ããç¹å®ã®ãã©ã³ã¶ã¯ã·ã§ã³ã«åã¡ãã»ãŒãžãéä¿¡ãã圹å²ãæãããŸãã ã©ã€ãã©ãªã®ãŠãŒã¶ãŒã¯ããã©ã³ã¶ã¯ã·ã§ã³ã«å°çããã¡ãã»ãŒãžã®ãã³ãã©ãŒãäœæãã責任ããããŸãã ãã®èšèšã«ãããSPDYãHTTP / 2ãªã©ã®æ°ããå€éåãããã³ã«ããµããŒãã§ããŸãã
Proxygenã¯ãææ°ã®C ++æšæºã®æ©èœãç©æ¥µçã«äœ¿çšããŠããã ThriftãšFollyã«äŸåããŠããŸãã 移åã»ãã³ãã£ã¯ã¹ã䜿çšããŠãããã£ãããã¡ãŒãèŠæ±ããããŒãšå¿çããããŒãªã©ã®å€§ããªãªããžã§ã¯ããã³ããŒããã³ã¹ããåé¿ããŸããã ããã«ãéããããã³ã°I / OãšLinux epollãå éšã§äœ¿çšããŠãã¡ã¢ãªäœ¿çšéãšCPUæéã®äž¡æ¹ã®ç¹ã§å¹ççãªãµãŒããŒãäœæããŸããã
HTTPãµãŒããŒ
ãªãªãŒã¹ã«å«ãŸããŠãããµãŒããŒã®äŸã¯ãåçŽãªãããã«äœ¿çšå¯èœãªéåæãµãŒããŒããã¯ããŒã³ããéå§ããå Žåã®é©åãªéå§ç¹ã§ãã
EchoServer.cpp
/* * Copyright (c) 2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ #include "EchoHandler.h" #include "EchoStats.h" #include "proxygen/httpserver/HTTPServer.h" #include "proxygen/httpserver/RequestHandlerFactory.h" #include <folly/Portability.h> #include <folly/Memory.h> #include <folly/io/async/EventBaseManager.h> #include <unistd.h> using namespace EchoService; using namespace proxygen; using folly::EventBase; using folly::EventBaseManager; using folly::SocketAddress; using Protocol = HTTPServer::Protocol; DEFINE_int32(http_port, 11000, "Port to listen on with HTTP protocol"); DEFINE_int32(spdy_port, 11001, "Port to listen on with SPDY protocol"); DEFINE_int32(thrift_port, 10000, "Port to listen on for thrift"); DEFINE_string(ip, "localhost", "IP/Hostname to bind to"); DEFINE_int32(threads, 0, "Number of threads to listen on. Numbers <= 0 " "will use the number of cores on this machine."); class EchoHandlerFactory : public RequestHandlerFactory { public: void onServerStart() noexcept override { stats_.reset(new EchoStats); } void onServerStop() noexcept override { stats_.reset(); } RequestHandler* onRequest(RequestHandler*, HTTPMessage*) noexcept override { return new EchoHandler(stats_.get()); } private: folly::ThreadLocalPtr<EchoStats> stats_; }; int main(int argc, char* argv[]) { gflags::ParseCommandLineFlags(&argc, &argv, true); google::InitGoogleLogging(argv[0]); google::InstallFailureSignalHandler(); std::vector<HTTPServer::IPConfig> IPs = { {SocketAddress(FLAGS_ip, FLAGS_http_port, true), Protocol::HTTP}, {SocketAddress(FLAGS_ip, FLAGS_spdy_port, true), Protocol::SPDY}, }; if (FLAGS_threads <= 0) { FLAGS_threads = sysconf(_SC_NPROCESSORS_ONLN); CHECK(FLAGS_threads > 0); } HTTPServerOptions options; options.threads = static_cast<size_t>(FLAGS_threads); options.idleTimeout = std::chrono::milliseconds(60000); options.shutdownOn = {SIGINT, SIGTERM}; options.handlerFactories = RequestHandlerChain() .addThen<EchoHandlerFactory>() .build(); HTTPServer server(std::move(options)); server.bind(IPs); // Start HTTPServer mainloop in a separate thread std::thread t([&] () { server.start(); }); t.join(); return 0; }
EchoHandler.cpp
/* * Copyright (c) 2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ #include "EchoHandler.h" #include "EchoStats.h" #include "proxygen/httpserver/RequestHandler.h" #include "proxygen/httpserver/ResponseBuilder.h" using namespace proxygen; namespace EchoService { EchoHandler::EchoHandler(EchoStats* stats): stats_(stats) { } void EchoHandler::onRequest(std::unique_ptr<HTTPMessage> headers) noexcept { stats_->recordRequest(); } void EchoHandler::onBody(std::unique_ptr<folly::IOBuf> body) noexcept { if (body_) { body_->prependChain(std::move(body)); } else { body_ = std::move(body); } } void EchoHandler::onEOM() noexcept { ResponseBuilder(downstream_) .status(200, "OK") .header("Request-Number", folly::to<std::string>(stats_->getRequestCount())) .body(std::move(body_)) .sendWithEOM(); } void EchoHandler::onUpgrade(UpgradeProtocol protocol) noexcept { // handler doesn't support upgrades } void EchoHandler::requestComplete() noexcept { delete this; } void EchoHandler::onError(ProxygenError err) noexcept { delete this; } }
32åã®Intel®Xeon®CPUã³ã¢E5-2670 @ 2.60GHzãš16 GiBã®ã¡ã¢ãªãæèŒããã³ã³ãã¥ãŒã¿ãŒã§ãšã³ãŒãµãŒããŒã®ãã³ãããŒã¯ãè¡ããã¯ãŒã¯ãããŒã®æ°ã1ãã8ãŸã§å€åãããŸããã ãããã¯ãŒã¯ã®é 延ãé¿ããããã«ãåããã·ã³ã§ã¯ã©ã€ã¢ã³ããèµ·åããŸããããããåŸããããã®ã§ãã
ïŒã¯ã©ã€ã¢ã³ãèšå®ïŒ
ïŒãµãŒããŒã¯ãŒã¯ãããŒããšã«ã2ã¯ã©ã€ã¢ã³ã
ïŒ400åæã«æ¥ç¶ãéã
ïŒ100æ¥ç¶èŠæ±
ïŒ60ç§éã®ãã¹ã
ïŒçµæã¯ã10åã®ãã¹ãã®çµæã®å¹³åã瀺ããŠããŸã
ïŒã·ã³ãã«GETã245ãã€ãã®ãªã¯ãšã¹ãããããŒã600ãã€ãã®ã¬ã¹ãã³ã¹ïŒãã£ã¹ã¯ã«ä¿åããã«ïŒ
ïŒSPDY / 3.1ã¯æ倧10ã®åææ¥ç¶èŠæ±ãèš±å¯ããŸã
ãšã³ãŒãµãŒããŒèªäœã¯å®éã®WebãµãŒããŒãšæ¯èŒããŠéåžžã«åå§çã§ããããã®ãã³ãããŒã¯ã¯ProxygenãSPDYããã³HTTP / 2ã§ã©ã®ããã«å¹ççã«æ©èœãããã瀺ããŠããŸãã Proxygenãããã®HTTPãµãŒããŒã¯äœ¿ãããããããã«éåžžã«çç£çã«æ©èœããŸãããå¯èœãªéãæé«ã®é床ããã䜿ããããã«éç¹ã眮ããŠããŸãã ããšãã°ããµãŒããŒã®ãã£ã«ã¿ãŒã¢ãã«ã¯ãå®çŸ©ãããã¢ã«ãŽãªãºã ã«åŸã£ãŠãã¢ã«ãŽãªãºã ã³ãŒãã®åã ã®ãããã¯ãç°¡åã«ãã¹ãã§ããããã«ãäžè¬çãªããŒã¿ãããã¯ãåŠçããæ©äŒãæäŸããŸãã äžæ¹ããã®ãã£ã«ã¿ãŒã¢ãã«ã«é¢é£ä»ããããã¡ã¢ãªå²ãåœãŠã®å¿ èŠæ§ã¯ãé«æ§èœã¢ããªã±ãŒã·ã§ã³ã«ã¯çæ³çã§ã¯ãããŸããã
圱é¿å
Proxygenã䜿çšãããšãç®çã®æ©èœããã°ããå®è£ ããéçšç°å¢ã§ãªãªãŒã¹ããŠããã«çµæãåŸãããšãã§ããŸãã ããšãã°ã HPACKãªã¯ãšã¹ãããããŒã®å§çž®åœ¢åŒã®è©äŸ¡ã«èå³ããããŸããããæ®å¿µãªããHTTP / 2ã¯ã©ã€ã¢ã³ãããµãŒããŒããããŸããã§ãããäžè¬ã«ãHTTP / 2ä»æ§èªäœã¯ãŸã éçºäžã§ãã Proxygenã䜿çšãããšãHPACKãå®è£ ããSPDYäžã§ããã䜿çšããŠããµãŒããŒãšã¢ãã€ã«ã¯ã©ã€ã¢ã³ãã«åæã«ãªãªãŒã¹ããããšãã§ããŸãã HPACK圢åŒã®å®éã®ãã©ãã£ãã¯ããã°ããå®éšããæ©èœã«ãããå®éã®ããã©ãŒãã³ã¹ãç解ãããã®äœ¿çšã®å©ç¹ãè©äŸ¡ããæ©äŒãäžããããŸããã
ãªãŒãã³ãœãŒã¹
Proxygenã³ãŒãããŒã¹ã¯æŽ»çºã«éçºäžã§ãããé²åãç¶ããŸãã HTTPãããã³ã«ãé«æ§èœãããã¯ãŒã¯ã³ãŒããææ°ã®C ++ãæ°ã«å ¥ã£ãå Žåã¯ãåãã§å¯Ÿå¿ããããŸãïŒ ãã«ãªã¯ãšã¹ããGithubã«éä¿¡ããŠãã ããã
ç§ãã¡ã¯ãªãŒãã³ãœãŒã¹ãããžã§ã¯ãã®éçºã«ç©æ¥µçã«é¢äžããŠãããã³ãŒããã³ãã¥ããã£ãšå ±æããæ©äŒãåžžã«æ¢ããŠããŸãã ãããã¯ãŒã¯ã€ã³ãã©ã¹ãã©ã¯ãã£éçºããŒã ã¯ãFacebookã®2ã€ã®éèŠãªãããã¯ãŒã¯ã³ã³ããŒãã³ãã§ããThriftãšProxygenããªãŒãã³ãœãŒã¹ã«å ¬éããŠããŸã ã 圌ããä»ã®ãããžã§ã¯ãã§åœŒãã®ã¢ããªã±ãŒã·ã§ã³ãèŠã€ããããšãé¡ã£ãŠããŸãã
ãã®ãããžã§ã¯ãã®éçºã«åå ãããã¹ãŠã®ãšã³ãžãã¢ã«æè¬ããŸããAjitBanerjeeãDavid GadlingãClaudiu GheorgheãRajat GoelãPeter GriessãMartin LauãAdam LazurãNoam LernerãXu NingãBrian PaneãPraveen Kumar RamakrishnanãAdam Simpivum ViswanãŠãŒã»ã·ãšã