Skip to content

Instantly share code, notes, and snippets.

@emaxerrno
Created March 24, 2016 17:25
Show Gist options
  • Select an option

  • Save emaxerrno/d336223975e4862802aa to your computer and use it in GitHub Desktop.

Select an option

Save emaxerrno/d336223975e4862802aa to your computer and use it in GitHub Desktop.
handler.cc
#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