Created
March 24, 2016 17:25
-
-
Save emaxerrno/d336223975e4862802aa to your computer and use it in GitHub Desktop.
handler.cc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <glog/logging.h> | |
| #include <folly/io/async/EventBase.h> | |
| #include <proxygen/httpserver/RequestHandler.h> | |
| #include <proxygen/httpserver/ResponseBuilder.h> | |
| #include <folly/MoveWrapper.h> | |
| #include "http_common/client/HTTPClient.hpp" | |
| namespace concord { | |
| // Last benchmarked on March 23, 2016 | |
| // it can do 11.7K request per second forwarded to a go server | |
| // wrk -t16 -c100 -d30s --latency -R1000000 "http://localhost:11000/_/0/r" | |
| // | |
| // This is the go program used | |
| // | |
| // package main | |
| // import ( | |
| // "fmt" | |
| // "net/http" | |
| // ) | |
| // func handler(w http.ResponseWriter, r *http.Request) { | |
| // r.Header.Set("Connection", "close") | |
| // r.Close = true | |
| // r.Body.Close() | |
| // fmt.Print("."); | |
| // } | |
| // func main() { | |
| // http.HandleFunc("/", handler) | |
| // http.ListenAndServe(":8000", nil) | |
| // } | |
| // | |
| // | |
| // | |
| // Result: | |
| // | |
| // #[Mean = 19616.875, StdDeviation = 5700.764] | |
| // #[Max = 29556.736, Total count = 287631] | |
| // #[Buckets = 27, SubBuckets = 2048] | |
| // ---------------------------------------------------------- | |
| // 430362 requests in 30.00s, 40.63MB read | |
| // Requests/sec: 14346.65 | |
| // Transfer/sec: 1.35MB | |
| // | |
| // | |
| // | |
| // | |
| class PrincipalForwardRequestHandler : public proxygen::RequestHandler { | |
| public: | |
| class callback : public HTTPClient::ClientCallback { | |
| public: | |
| callback(PrincipalForwardRequestHandler *h) : handler_(CHECK_NOTNULL(h)) {} | |
| virtual void success(folly::EventBase *evb, | |
| folly::HHWheelTimer *timer, | |
| proxygen::HTTPMessage request, | |
| std::unique_ptr<folly::IOBuf> body) override final { | |
| handler_->sendStatus(200, "OK"); | |
| } | |
| virtual void | |
| fail(folly::EventBase *evb, | |
| folly::HHWheelTimer *timer, | |
| proxygen::HTTPMessage request, | |
| std::unique_ptr<proxygen::HTTPException> error) override final { | |
| handler_->sendStatus(404, "ERROR"); | |
| } | |
| private: | |
| PrincipalForwardRequestHandler *handler_; | |
| }; | |
| PrincipalForwardRequestHandler(folly::EventBase *evb, | |
| folly::HHWheelTimer *timer) | |
| : evb_(CHECK_NOTNULL(evb)), timer_(CHECK_NOTNULL(timer)) { | |
| cb_.reset(new callback(this)); | |
| } | |
| void | |
| onRequest(std::unique_ptr<proxygen::HTTPMessage> headers) noexcept override {} | |
| void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override { | |
| if(body_) { | |
| body_->prependChain(std::move(body)); | |
| } else { | |
| body_ = std::move(body); | |
| } | |
| } | |
| void sendStatus(int16_t status, std::string hdr) { | |
| evb_->runInEventBaseThread([this, status, hdr] { | |
| // response builder needs to be in the same thread as the socket | |
| proxygen::ResponseBuilder(downstream_).status(status, hdr).sendWithEOM(); | |
| }); | |
| } | |
| void onEOM() noexcept override { | |
| HTTPClient::create() | |
| ->setEventBase(evb_) | |
| ->setTimer(timer_) | |
| ->setMethod(proxygen::HTTPMethod::POST) | |
| ->setURL(proxygen::URL("http://127.0.0.1:8000/foobar"), false) | |
| ->setRequestBody(std::move(body_)) | |
| ->setClientCallback(cb_.get()) | |
| ->send(); | |
| } | |
| void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {} | |
| void requestComplete() noexcept override { delete this; } | |
| void onError(proxygen::ProxygenError err) noexcept override { delete this; } | |
| private: | |
| folly::EventBase *evb_; | |
| folly::HHWheelTimer *timer_; | |
| std::unique_ptr<folly::IOBuf> body_ = nullptr; | |
| std::unique_ptr<callback> cb_; | |
| }; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment