mirror of
https://gitee.com/TarsCloud/TarsCpp.git
synced 2024-12-22 22:16:38 +08:00
http rpc call support
This commit is contained in:
parent
30723faaf5
commit
bef3665f03
@ -26,7 +26,7 @@ set(TARS_VERSION "2.0.0")
|
|||||||
add_definitions(-DTARS_VERSION="${TARS_VERSION}")
|
add_definitions(-DTARS_VERSION="${TARS_VERSION}")
|
||||||
set(TARS_SSL 0)
|
set(TARS_SSL 0)
|
||||||
add_definitions(-DTARS_SSL=${TARS_SSL})
|
add_definitions(-DTARS_SSL=${TARS_SSL})
|
||||||
set(TARS_HTTP2 0)
|
set(TARS_HTTP2 1)
|
||||||
add_definitions(-DTARS_HTTP2=${TARS_HTTP2})
|
add_definitions(-DTARS_HTTP2=${TARS_HTTP2})
|
||||||
|
|
||||||
set(_USE_OPENTRACKING $ENV{_USE_OPENTRACKING})
|
set(_USE_OPENTRACKING $ENV{_USE_OPENTRACKING})
|
||||||
|
@ -55,7 +55,7 @@ static TC_NetWorkBuffer::PACKET_TYPE customResponse(TC_NetWorkBuffer &in, Respon
|
|||||||
/*
|
/*
|
||||||
Whole package length (4 bytes) + irequestid (4 bytes) + package content
|
Whole package length (4 bytes) + irequestid (4 bytes) + package content
|
||||||
*/
|
*/
|
||||||
static vector<char> customRequest(const RequestPacket& request)
|
static vector<char> customRequest(RequestPacket& request, Transceiver *)
|
||||||
{
|
{
|
||||||
unsigned int net_bufflength = htonl(request.sBuffer.size()+8);
|
unsigned int net_bufflength = htonl(request.sBuffer.size()+8);
|
||||||
unsigned char * bufflengthptr = (unsigned char*)(&net_bufflength);
|
unsigned char * bufflengthptr = (unsigned char*)(&net_bufflength);
|
||||||
|
@ -153,7 +153,8 @@ void syncRpc(int c)
|
|||||||
int64_t t = TC_Common::now2us();
|
int64_t t = TC_Common::now2us();
|
||||||
|
|
||||||
std::map<std::string, std::string> header;
|
std::map<std::string, std::string> header;
|
||||||
header["X-Test"] = "YYYY";
|
// header[":authority"] = "domain.com";
|
||||||
|
// header[":scheme"] = "http";
|
||||||
|
|
||||||
std::map<std::string, std::string> rheader;
|
std::map<std::string, std::string> rheader;
|
||||||
//发起远程调用
|
//发起远程调用
|
||||||
@ -239,8 +240,11 @@ int main(int argc, char *argv[])
|
|||||||
param.servantPrx->tars_async_timeout(60*1000);
|
param.servantPrx->tars_async_timeout(60*1000);
|
||||||
|
|
||||||
ProxyProtocol proto;
|
ProxyProtocol proto;
|
||||||
proto.requestFunc = tars::http2Request;
|
proto.requestFunc = ProxyProtocol::http1Request;
|
||||||
proto.responseFunc = tars::http2Response;
|
proto.responseFunc = ProxyProtocol::http1Response;
|
||||||
|
// proto.requestFunc = ProxyProtocol::http2Request;
|
||||||
|
// proto.responseFunc = ProxyProtocol::http2Response;
|
||||||
|
param.servantPrx->tars_set_protocol(proto);
|
||||||
|
|
||||||
int64_t start = TC_Common::now2us();
|
int64_t start = TC_Common::now2us();
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ static TC_NetWorkBuffer::PACKET_TYPE pushResponse(TC_NetWorkBuffer &in, Response
|
|||||||
请求包编码函数,本函数的打包格式为
|
请求包编码函数,本函数的打包格式为
|
||||||
整个包长度(4字节)+iRequestId(4字节)+包内容
|
整个包长度(4字节)+iRequestId(4字节)+包内容
|
||||||
*/
|
*/
|
||||||
static vector<char> pushRequest(const RequestPacket& request)
|
static vector<char> pushRequest(RequestPacket& request, Transceiver *)
|
||||||
{
|
{
|
||||||
unsigned int net_bufflength = htonl(request.sBuffer.size()+8);
|
unsigned int net_bufflength = htonl(request.sBuffer.size()+8);
|
||||||
unsigned char * bufflengthptr = (unsigned char*)(&net_bufflength);
|
unsigned char * bufflengthptr = (unsigned char*)(&net_bufflength);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "servant/StatF.h"
|
#include "servant/StatF.h"
|
||||||
#include "servant/StatReport.h"
|
#include "servant/StatReport.h"
|
||||||
#include "util/tc_nghttp2.h"
|
#include "util/tc_nghttp2.h"
|
||||||
#include "util/tc_http2clientmgr.h"
|
// #include "util/tc_http2clientmgr.h"
|
||||||
#ifdef _USE_OPENTRACKING
|
#ifdef _USE_OPENTRACKING
|
||||||
#include "servant/text_map_carrier.h"
|
#include "servant/text_map_carrier.h"
|
||||||
#endif
|
#endif
|
||||||
@ -158,18 +158,18 @@ int AdapterProxy::invoke(ReqMessage * msg)
|
|||||||
msg->request.iRequestId = _timeoutQueue->generateId();
|
msg->request.iRequestId = _timeoutQueue->generateId();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARS_HTTP2
|
// #if TARS_HTTP2
|
||||||
if (getObjProxy()->getProtoName() == HTTP2)
|
// if (getObjProxy()->getProtoName() == HTTP2)
|
||||||
{
|
// {
|
||||||
msg->request.iRequestId = getId(); // session Id
|
// msg->request.iRequestId = getId(); // session Id
|
||||||
}
|
// }
|
||||||
#endif
|
// #endif
|
||||||
|
|
||||||
#ifdef _USE_OPENTRACKING
|
#ifdef _USE_OPENTRACKING
|
||||||
startTrack(msg);
|
startTrack(msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
msg->sReqData->addBuffer(_objectProxy->getProxyProtocol().requestFunc(msg->request));
|
msg->sReqData->addBuffer(_objectProxy->getProxyProtocol().requestFunc(msg->request, _trans.get()));
|
||||||
|
|
||||||
//交给连接发送数据,连接连上,buffer不为空,直接发送数据成功
|
//交给连接发送数据,连接连上,buffer不为空,直接发送数据成功
|
||||||
if(_timeoutQueue->sendListEmpty() && _trans->sendRequest(msg->sReqData) != Transceiver::eRetError)
|
if(_timeoutQueue->sendListEmpty() && _trans->sendRequest(msg->sReqData) != Transceiver::eRetError)
|
||||||
|
@ -15,27 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "util/tc_epoll_server.h"
|
#include "util/tc_epoll_server.h"
|
||||||
|
#include "util/tc_http.h"
|
||||||
#include "servant/AppProtocol.h"
|
#include "servant/AppProtocol.h"
|
||||||
|
#include "servant/Transceiver.h"
|
||||||
|
#include "servant/TarsLogger.h"
|
||||||
#include "tup/Tars.h"
|
#include "tup/Tars.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#if TARS_HTTP2
|
#if TARS_HTTP2
|
||||||
#include "util/tc_nghttp2.h"
|
#include "util/tc_nghttp2.h"
|
||||||
#include "util/tc_http2clientmgr.h"
|
// #include "util/tc_http2clientmgr.h"
|
||||||
|
|
||||||
#define MAKE_NV(NAME, VALUE, VALUELEN) \
|
|
||||||
{ \
|
|
||||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
|
|
||||||
NGHTTP2_NV_FLAG_NONE \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAKE_NV2(NAME, VALUE) \
|
|
||||||
{ \
|
|
||||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
|
||||||
NGHTTP2_NV_FLAG_NONE \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAKE_STRING_NV(NAME, VALUE) {(uint8_t*)(NAME.data()), (uint8_t*)(VALUE.data()), NAME.size(), VALUE.size(), NGHTTP2_NV_FLAG_NONE};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace tars
|
namespace tars
|
||||||
@ -47,7 +36,7 @@ TC_NetWorkBuffer::PACKET_TYPE AppProtocol::parseAdmin(TC_NetWorkBuffer &in, sha
|
|||||||
return parse(in, out->getBuffer());
|
return parse(in, out->getBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<char> ProxyProtocol::tarsRequest(const RequestPacket& request)
|
vector<char> ProxyProtocol::tarsRequest(RequestPacket& request, Transceiver *)
|
||||||
{
|
{
|
||||||
TarsOutputStream<BufferWriterVector> os;
|
TarsOutputStream<BufferWriterVector> os;
|
||||||
|
|
||||||
@ -73,6 +62,21 @@ vector<char> ProxyProtocol::tarsRequest(const RequestPacket& request)
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
#if TARS_HTTP2
|
#if TARS_HTTP2
|
||||||
|
|
||||||
|
#define MAKE_NV(NAME, VALUE, VALUELEN) \
|
||||||
|
{ \
|
||||||
|
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
|
||||||
|
NGHTTP2_NV_FLAG_NONE \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAKE_NV2(NAME, VALUE) \
|
||||||
|
{ \
|
||||||
|
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||||
|
NGHTTP2_NV_FLAG_NONE \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAKE_STRING_NV(NAME, VALUE) {(uint8_t*)(NAME.data()), (uint8_t*)(VALUE.data()), NAME.size(), VALUE.size(), NGHTTP2_NV_FLAG_NONE};
|
||||||
|
|
||||||
// nghttp2读取请求包体,准备发送
|
// nghttp2读取请求包体,准备发送
|
||||||
static ssize_t reqbody_read_callback(nghttp2_session *session, int32_t stream_id,
|
static ssize_t reqbody_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||||
uint8_t *buf, size_t length,
|
uint8_t *buf, size_t length,
|
||||||
@ -97,14 +101,29 @@ static ssize_t reqbody_read_callback(nghttp2_session *session, int32_t stream_id
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
TC_NetWorkBuffer::PACKET_TYPE http1Response(TC_NetWorkBuffer &in, tars::ResponsePacket& rsp)
|
vector<char> ProxyProtocol::http1Request(tars::RequestPacket& request, Transceiver *)
|
||||||
|
{
|
||||||
|
TC_HttpRequest httpRequest;
|
||||||
|
|
||||||
|
httpRequest.setRequest(request.sFuncName, request.sServantName, string(request.sBuffer.data(), request.sBuffer.size()), true);
|
||||||
|
|
||||||
|
vector<char> buffer;
|
||||||
|
|
||||||
|
httpRequest.encode(buffer);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
TC_NetWorkBuffer::PACKET_TYPE ProxyProtocol::http1Response(TC_NetWorkBuffer &in, ResponsePacket& rsp)
|
||||||
{
|
{
|
||||||
TC_NetWorkBuffer::PACKET_TYPE flag = in.checkHttp();
|
TC_NetWorkBuffer::PACKET_TYPE flag = in.checkHttp();
|
||||||
|
|
||||||
if(flag == TC_NetWorkBuffer::PACKET_FULL)
|
if(flag == TC_NetWorkBuffer::PACKET_FULL)
|
||||||
{
|
{
|
||||||
tars::TC_HttpResponse httpRsp;
|
TC_HttpResponse httpRsp;
|
||||||
httpRsp.decode(in.getBuffers());
|
vector<char> buffer = in.getBuffers();
|
||||||
|
|
||||||
|
httpRsp.decode(buffer.data(), buffer.size());
|
||||||
|
|
||||||
// ResponsePacket rsp;
|
// ResponsePacket rsp;
|
||||||
rsp.status["status"] = httpRsp.getResponseHeaderLine();
|
rsp.status["status"] = httpRsp.getResponseHeaderLine();
|
||||||
@ -123,8 +142,87 @@ TC_NetWorkBuffer::PACKET_TYPE http1Response(TC_NetWorkBuffer &in, tars::Response
|
|||||||
// return httpRsp.getHeadLength() + httpRsp.getContentLength();
|
// return httpRsp.getHeadLength() + httpRsp.getContentLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<char> encodeHttp2(RequestPacket& request, TC_NgHttp2* session)
|
// vector<char> encodeHttp2(RequestPacket& request, TC_NgHttp2* session)
|
||||||
|
// {
|
||||||
|
// std::vector<nghttp2_nv> nva;
|
||||||
|
|
||||||
|
// const std::string method(":method");
|
||||||
|
// nghttp2_nv nv1 = MAKE_STRING_NV(method, request.sFuncName);
|
||||||
|
// if (!request.sFuncName.empty())
|
||||||
|
// nva.push_back(nv1);
|
||||||
|
|
||||||
|
// const std::string path(":path");
|
||||||
|
// nghttp2_nv nv2 = MAKE_STRING_NV(path, request.sServantName);
|
||||||
|
// if (!request.sServantName.empty())
|
||||||
|
// nva.push_back(nv2);
|
||||||
|
|
||||||
|
// for (std::map<std::string, std::string>::const_iterator
|
||||||
|
// it(request.context.begin());
|
||||||
|
// it != request.context.end();
|
||||||
|
// ++ it)
|
||||||
|
// {
|
||||||
|
// nghttp2_nv nv = MAKE_STRING_NV(it->first, it->second);
|
||||||
|
// nva.push_back(nv);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// nghttp2_data_provider* pData = NULL;
|
||||||
|
// nghttp2_data_provider data;
|
||||||
|
// if (!request.sBuffer.empty())
|
||||||
|
// {
|
||||||
|
// pData = &data;
|
||||||
|
// data.source.ptr = (void*)&request.sBuffer;
|
||||||
|
// data.read_callback = reqbody_read_callback;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int32_t sid = nghttp2_submit_request(session->session(),
|
||||||
|
// NULL,
|
||||||
|
// &nva[0],
|
||||||
|
// nva.size(),
|
||||||
|
// pData,
|
||||||
|
// NULL);
|
||||||
|
// if (sid < 0)
|
||||||
|
// {
|
||||||
|
// TLOGERROR("encodeHttp2::Fatal error: nghttp2_submit_request return: " << sid << endl);
|
||||||
|
// return vector<char>();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// request.iRequestId = sid;
|
||||||
|
// nghttp2_session_send(session->session());
|
||||||
|
|
||||||
|
// // 交给tars发送
|
||||||
|
// // std::string out;
|
||||||
|
// // out.swap(session->sendBuffer());
|
||||||
|
// // return out;
|
||||||
|
|
||||||
|
// vector<char> out;
|
||||||
|
|
||||||
|
// out.assign(session->sendBuffer().begin(), session->sendBuffer().end());
|
||||||
|
|
||||||
|
// return out;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ENCODE function, called by network thread
|
||||||
|
vector<char> ProxyProtocol::http2Request(RequestPacket& request, Transceiver *trans)
|
||||||
{
|
{
|
||||||
|
cout << "http2Request" << endl;
|
||||||
|
// TC_NgHttp2* session = Http2ClientSessionManager::getInstance()->getSession(request.iRequestId);
|
||||||
|
TC_NgHttp2* session = trans->getHttp2Session();
|
||||||
|
|
||||||
|
assert(session != NULL);
|
||||||
|
|
||||||
|
cout << "http2Request:" << session << endl;
|
||||||
|
|
||||||
|
if (session->getState() == TC_NgHttp2::None)
|
||||||
|
{
|
||||||
|
session->Init();
|
||||||
|
session->settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (session->getState() == TC_NgHttp2::Http2);
|
||||||
|
|
||||||
|
// return encodeHttp2(request, session);
|
||||||
|
cout << "http2Request1" << endl;
|
||||||
|
|
||||||
std::vector<nghttp2_nv> nva;
|
std::vector<nghttp2_nv> nva;
|
||||||
|
|
||||||
const std::string method(":method");
|
const std::string method(":method");
|
||||||
@ -146,6 +244,7 @@ vector<char> encodeHttp2(RequestPacket& request, TC_NgHttp2* session)
|
|||||||
nva.push_back(nv);
|
nva.push_back(nv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cout << "http2Request2" << endl;
|
||||||
nghttp2_data_provider* pData = NULL;
|
nghttp2_data_provider* pData = NULL;
|
||||||
nghttp2_data_provider data;
|
nghttp2_data_provider data;
|
||||||
if (!request.sBuffer.empty())
|
if (!request.sBuffer.empty())
|
||||||
@ -163,10 +262,11 @@ vector<char> encodeHttp2(RequestPacket& request, TC_NgHttp2* session)
|
|||||||
NULL);
|
NULL);
|
||||||
if (sid < 0)
|
if (sid < 0)
|
||||||
{
|
{
|
||||||
cerr << "Fatal error: nghttp2_submit_request return " << sid << endl;
|
TLOGERROR("[TARS]http2Request::Fatal error: nghttp2_submit_request return: " << sid << endl);
|
||||||
return "";
|
return vector<char>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cout << "http2Request3" << endl;
|
||||||
request.iRequestId = sid;
|
request.iRequestId = sid;
|
||||||
nghttp2_session_send(session->session());
|
nghttp2_session_send(session->session());
|
||||||
|
|
||||||
@ -179,50 +279,39 @@ vector<char> encodeHttp2(RequestPacket& request, TC_NgHttp2* session)
|
|||||||
|
|
||||||
out.assign(session->sendBuffer().begin(), session->sendBuffer().end());
|
out.assign(session->sendBuffer().begin(), session->sendBuffer().end());
|
||||||
|
|
||||||
|
cout << "http2Request4:" << out.data() << endl;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ENCODE function, called by network thread
|
// TC_NetWorkBuffer::PACKET_TYPE http2Response(TC_NetWorkBuffer &in, list<ResponsePacket>& done, void* userptr)
|
||||||
vector<char> http2Request(const RequestPacket& request)
|
TC_NetWorkBuffer::PACKET_TYPE ProxyProtocol::http2Response(TC_NetWorkBuffer &in, ResponsePacket& rsp)
|
||||||
{
|
{
|
||||||
TC_NgHttp2* session = Http2ClientSessionManager::getInstance()->getSession(request.iRequestId);
|
TC_NgHttp2* session = ((Transceiver*)(in.getConnection()))->getHttp2Session();
|
||||||
if (session->getState() == TC_NgHttp2::None)
|
|
||||||
{
|
|
||||||
session->Init();
|
|
||||||
session->settings();
|
|
||||||
}
|
|
||||||
|
|
||||||
assert (session->getState() == TC_NgHttp2::Http2);
|
assert (session->getState() == TC_NgHttp2::Http2);
|
||||||
|
|
||||||
return encodeHttp2(request, session);
|
auto it = session->doneResponses().begin();
|
||||||
}
|
|
||||||
|
|
||||||
// TC_NetWorkBuffer::PACKET_TYPE http2Response(TC_NetWorkBuffer &in, list<ResponsePacket>& done, void* userptr)
|
if(it == session->doneResponses().end())
|
||||||
TC_NetWorkBuffer::PACKET_TYPE http2Response(TC_NetWorkBuffer &in, ResponsePacket& done)
|
|
||||||
{
|
|
||||||
auto it = session->_doneResponses.begin();
|
|
||||||
|
|
||||||
if(it == session->_doneResponses.end())
|
|
||||||
{
|
{
|
||||||
vector<char> buffer = in.getBuffers();
|
vector<char> buffer = in.getBuffers();
|
||||||
in.clearBuffers();
|
in.clearBuffers();
|
||||||
|
|
||||||
Transceiver* userptr = ((Transceiver*))in->getConnection();
|
// Transceiver* userptr = ((Transceiver*))in->getConnection();
|
||||||
int sessionId = userptr->getAdapterProxy()->getId();
|
// int sessionId = userptr->getAdapterProxy()->getId();
|
||||||
TC_NgHttp2* session = Http2ClientSessionManager::getInstance()->getSession(sessionId);
|
// TC_NgHttp2* session = Http2ClientSessionManager::getInstance()->getSession(sessionId);
|
||||||
assert (session->getState() == TC_NgHttp2::Http2);
|
|
||||||
|
|
||||||
int readlen = nghttp2_session_mem_recv(session->session(), (const uint8_t*)buffer.data(), buffer.length());
|
int readlen = nghttp2_session_mem_recv(session->session(), (const uint8_t*)buffer.data(), buffer.size());
|
||||||
|
|
||||||
if (readlen < 0)
|
if (readlen < 0)
|
||||||
{
|
{
|
||||||
// throw std::runtime_error("nghttp2_session_mem_recv return error");
|
// throw std::runtime_error("nghttp2_session_mem_recv return error");
|
||||||
return TC_NetWorkBuffer::PACKET_ERROR;
|
return TC_NetWorkBuffer::PACKET_ERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it = session->_doneResponses.begin();
|
it = session->doneResponses().begin();
|
||||||
if(it == session->_doneResponses.end())
|
if(it == session->doneResponses().end())
|
||||||
{
|
{
|
||||||
return TC_NetWorkBuffer::PACKET_LESS;
|
return TC_NetWorkBuffer::PACKET_LESS;
|
||||||
}
|
}
|
||||||
@ -231,7 +320,7 @@ TC_NetWorkBuffer::PACKET_TYPE http2Response(TC_NetWorkBuffer &in, ResponsePacket
|
|||||||
rsp.status = it->second.headers;
|
rsp.status = it->second.headers;
|
||||||
rsp.sBuffer.assign(it->second.body.begin(), it->second.body.end());
|
rsp.sBuffer.assign(it->second.body.begin(), it->second.body.end());
|
||||||
|
|
||||||
session->_doneResponses.erase(it);
|
session->doneResponses().erase(it);
|
||||||
|
|
||||||
// std::map<int, Http2Response>::const_iterator it(session->_doneResponses.begin());
|
// std::map<int, Http2Response>::const_iterator it(session->_doneResponses.begin());
|
||||||
// for (; it != session->_doneResponses.end(); ++ it)
|
// for (; it != session->_doneResponses.end(); ++ it)
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#if TARS_HTTP2
|
#if TARS_HTTP2
|
||||||
#include "util/tc_nghttp2.h"
|
#include "util/tc_nghttp2.h"
|
||||||
#include "util/tc_http2clientmgr.h"
|
// #include "util/tc_http2clientmgr.h"
|
||||||
#endif
|
#endif
|
||||||
namespace tars
|
namespace tars
|
||||||
{
|
{
|
||||||
@ -163,6 +163,7 @@ void Transceiver::setConnected()
|
|||||||
|
|
||||||
_onConnect();
|
_onConnect();
|
||||||
|
|
||||||
|
|
||||||
TLOGTARS("[TARS][tcp setConnected, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "]" << endl);
|
TLOGTARS("[TARS][tcp setConnected, " << _adapterProxy->getObjProxy()->name() << ",fd:" << _fd << "]" << endl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +249,7 @@ bool Transceiver::sendAuthData(const BasicAuthInfo& info)
|
|||||||
request.sBuffer.assign(out.begin(), out.end());
|
request.sBuffer.assign(out.begin(), out.end());
|
||||||
|
|
||||||
// vector<char> toSend;
|
// vector<char> toSend;
|
||||||
_sendBuffer->addBuffer(objPrx->getProxyProtocol().requestFunc(request));
|
_sendBuffer->addBuffer(objPrx->getProxyProtocol().requestFunc(request, this));
|
||||||
|
|
||||||
// _sendBuffer.addBuffer(toSend);
|
// _sendBuffer.addBuffer(toSend);
|
||||||
|
|
||||||
@ -276,7 +277,9 @@ void Transceiver::close()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TARS_HTTP2
|
#if TARS_HTTP2
|
||||||
Http2ClientSessionManager::getInstance()->delSession(_adapterProxy->getId());
|
// Http2ClientSessionManager::getInstance()->delSession(_adapterProxy->getId());
|
||||||
|
nghttp2_session_del(_http2Session->session());
|
||||||
|
_http2Session = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_adapterProxy->getObjProxy()->getCommunicatorEpoll()->delFd(_fd,&_fdInfo,EPOLLIN|EPOLLOUT);
|
_adapterProxy->getObjProxy()->getCommunicatorEpoll()->delFd(_fd,&_fdInfo,EPOLLIN|EPOLLOUT);
|
||||||
@ -300,6 +303,24 @@ void Transceiver::close()
|
|||||||
TLOGTARS("[TARS][trans close:"<< _adapterProxy->getObjProxy()->name()<< "," << _ep.desc() << "]" << endl);
|
TLOGTARS("[TARS][trans close:"<< _adapterProxy->getObjProxy()->name()<< "," << _ep.desc() << "]" << endl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARS_HTTP2
|
||||||
|
TC_NgHttp2* Transceiver::getHttp2Session()
|
||||||
|
{
|
||||||
|
if(_http2Session == NULL)
|
||||||
|
{
|
||||||
|
_http2Session = new TC_NgHttp2(false);
|
||||||
|
|
||||||
|
// if (_http2Session->getState() == TC_NgHttp2::None)
|
||||||
|
// {
|
||||||
|
// _http2Session->Init();
|
||||||
|
// _http2Session->settings();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
return _http2Session;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
// int Transceiver::doRequest()
|
// int Transceiver::doRequest()
|
||||||
// {
|
// {
|
||||||
// if(!isValid())
|
// if(!isValid())
|
||||||
|
@ -33,6 +33,8 @@ using namespace tup;
|
|||||||
namespace tars
|
namespace tars
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class Transceiver;
|
||||||
|
|
||||||
#define TARS_NET_MIN_PACKAGE_SIZE 5
|
#define TARS_NET_MIN_PACKAGE_SIZE 5
|
||||||
#define TARS_NET_MAX_PACKAGE_SIZE 1024*1024*10
|
#define TARS_NET_MAX_PACKAGE_SIZE 1024*1024*10
|
||||||
|
|
||||||
@ -131,13 +133,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<vector<char>(const RequestPacket&)> request_protocol;
|
typedef std::function<vector<char>(RequestPacket&, Transceiver *)> request_protocol;
|
||||||
/**
|
|
||||||
* 接收协议处理, 返回值表示解析了多少字节
|
|
||||||
* 框架层会自动对处理了包做处理
|
|
||||||
*/
|
|
||||||
typedef std::function<TC_NetWorkBuffer::PACKET_TYPE(TC_NetWorkBuffer&, ResponsePacket&)> response_protocol;
|
typedef std::function<TC_NetWorkBuffer::PACKET_TYPE(TC_NetWorkBuffer&, ResponsePacket&)> response_protocol;
|
||||||
// typedef std::function<TC_NetWorkBuffer::PACKET_TYPE(TC_NetWorkBuffer&, ResponsePacket&)> response_ex_protocol;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
/**
|
/**
|
||||||
@ -151,12 +148,23 @@ public:
|
|||||||
*/
|
*/
|
||||||
ProxyProtocol() : requestFunc(streamRequest) {}
|
ProxyProtocol() : requestFunc(streamRequest) {}
|
||||||
|
|
||||||
|
#if TARS_HTTP2
|
||||||
|
static vector<char> http1Request(tars::RequestPacket& request, Transceiver *);
|
||||||
|
static TC_NetWorkBuffer::PACKET_TYPE http1Response(TC_NetWorkBuffer &in, ResponsePacket& done);
|
||||||
|
|
||||||
|
// ENCODE function, called by network thread
|
||||||
|
static vector<char> http2Request(tars::RequestPacket& request, Transceiver *);
|
||||||
|
|
||||||
|
// DECODE function, called by network thread
|
||||||
|
static TC_NetWorkBuffer::PACKET_TYPE http2Response(TC_NetWorkBuffer &in, ResponsePacket& done);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 普通二进制请求包
|
* 普通二进制请求包
|
||||||
* @param request
|
* @param request
|
||||||
* @param buff
|
* @param buff
|
||||||
*/
|
*/
|
||||||
static const vector<char> &streamRequest(const RequestPacket& request)
|
static vector<char> streamRequest(RequestPacket& request, Transceiver *)
|
||||||
{
|
{
|
||||||
return request.sBuffer;
|
return request.sBuffer;
|
||||||
}
|
}
|
||||||
@ -245,12 +253,6 @@ public:
|
|||||||
return streamResponse<offset, T, netorder, idOffset, K, idNetorder, TARS_NET_MAX_PACKAGE_SIZE>(in, done);
|
return streamResponse<offset, T, netorder, idOffset, K, idNetorder, TARS_NET_MAX_PACKAGE_SIZE>(in, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* tup响应包(tup的响应会放在ResponsePacket的buffer中)
|
|
||||||
* @param request
|
|
||||||
* @param buff
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wup响应包(wup的响应会放在ResponsePacket的buffer中)
|
* wup响应包(wup的响应会放在ResponsePacket的buffer中)
|
||||||
* @param request
|
* @param request
|
||||||
@ -294,8 +296,6 @@ public:
|
|||||||
|
|
||||||
is.setBuffer(buffer.c_str() + sizeof(tars::Int32), head);
|
is.setBuffer(buffer.c_str() + sizeof(tars::Int32), head);
|
||||||
|
|
||||||
// is.setBuffer(recvBuffer + pos + sizeof(tars::Int32), head);
|
|
||||||
|
|
||||||
//tup回来是requestpackage
|
//tup回来是requestpackage
|
||||||
RequestPacket rsp;
|
RequestPacket rsp;
|
||||||
|
|
||||||
@ -363,7 +363,7 @@ public:
|
|||||||
* @param request
|
* @param request
|
||||||
* @param buff
|
* @param buff
|
||||||
*/
|
*/
|
||||||
static vector<char> tarsRequest(const RequestPacket& request);
|
static vector<char> tarsRequest(RequestPacket& request, Transceiver *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tars响应包解析
|
* tars响应包解析
|
||||||
@ -471,19 +471,8 @@ public:
|
|||||||
request_protocol requestFunc;
|
request_protocol requestFunc;
|
||||||
|
|
||||||
response_protocol responseFunc;
|
response_protocol responseFunc;
|
||||||
|
|
||||||
// response_ex_protocol responseExFunc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<char> http1Request(const tars::RequestPacket& request);
|
|
||||||
TC_NetWorkBuffer::PACKET_TYPE http1Response(TC_NetWorkBuffer &in, ResponsePacket& done);
|
|
||||||
|
|
||||||
// ENCODE function, called by network thread
|
|
||||||
vector<char> http2Request(const tars::RequestPacket& request);
|
|
||||||
|
|
||||||
// DECODE function, called by network thread
|
|
||||||
TC_NetWorkBuffer::PACKET_TYPE http2Response(TC_NetWorkBuffer &in, ResponsePacket& done);
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,10 @@ namespace tars
|
|||||||
class TC_OpenSSL;
|
class TC_OpenSSL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TARS_HTTP2
|
||||||
|
class TC_NgHttp2;
|
||||||
|
#endif
|
||||||
|
|
||||||
class AdapterProxy;
|
class AdapterProxy;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
@ -221,6 +225,10 @@ public:
|
|||||||
* 发送鉴权数据
|
* 发送鉴权数据
|
||||||
*/
|
*/
|
||||||
bool sendAuthData(const BasicAuthInfo& );
|
bool sendAuthData(const BasicAuthInfo& );
|
||||||
|
|
||||||
|
#if TARS_HTTP2
|
||||||
|
TC_NgHttp2* getHttp2Session();
|
||||||
|
#endif
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
** 物理连接成功回调
|
** 物理连接成功回调
|
||||||
@ -272,6 +280,9 @@ protected:
|
|||||||
std::unique_ptr<TC_OpenSSL> _openssl;
|
std::unique_ptr<TC_OpenSSL> _openssl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if TARS_HTTP2
|
||||||
|
TC_NgHttp2* _http2Session = NULL;
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* 发送buffer
|
* 发送buffer
|
||||||
*/
|
*/
|
||||||
|
@ -26,19 +26,6 @@ using namespace tars;
|
|||||||
namespace tars
|
namespace tars
|
||||||
{
|
{
|
||||||
|
|
||||||
struct node_T_new
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*节点hash值
|
|
||||||
*/
|
|
||||||
int32_t iHashCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*节点下标
|
|
||||||
*/
|
|
||||||
unsigned int iIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum TC_HashAlgorithmType
|
enum TC_HashAlgorithmType
|
||||||
{
|
{
|
||||||
E_TC_CONHASH_KETAMAHASH = 0,
|
E_TC_CONHASH_KETAMAHASH = 0,
|
||||||
@ -55,10 +42,7 @@ public:
|
|||||||
virtual TC_HashAlgorithmType getHashType() = 0;
|
virtual TC_HashAlgorithmType getHashType() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int32_t subTo32Bit(int32_t hash)
|
int32_t subTo32Bit(int32_t hash) { return (hash & 0xFFFFFFFFL); }
|
||||||
{
|
|
||||||
return (hash & 0xFFFFFFFFL);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -70,23 +54,8 @@ typedef TC_AutoPtr<TC_HashAlgorithm> TC_HashAlgorithmPtr;
|
|||||||
class TC_KetamaHashAlg : public TC_HashAlgorithm
|
class TC_KetamaHashAlg : public TC_HashAlgorithm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual int32_t hash(const string & sKey)
|
virtual int32_t hash(const string & sKey);
|
||||||
{
|
virtual TC_HashAlgorithmType getHashType();
|
||||||
string sMd5 = TC_MD5::md5bin(sKey);
|
|
||||||
const char *p = (const char *) sMd5.c_str();
|
|
||||||
|
|
||||||
int32_t hash = ((int32_t)(p[3] & 0xFF) << 24)
|
|
||||||
| ((int32_t)(p[2] & 0xFF) << 16)
|
|
||||||
| ((int32_t)(p[1] & 0xFF) << 8)
|
|
||||||
| ((int32_t)(p[0] & 0xFF));
|
|
||||||
|
|
||||||
return subTo32Bit(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual TC_HashAlgorithmType getHashType()
|
|
||||||
{
|
|
||||||
return E_TC_CONHASH_KETAMAHASH;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,20 +64,8 @@ public:
|
|||||||
class TC_DefaultHashAlg : public TC_HashAlgorithm
|
class TC_DefaultHashAlg : public TC_HashAlgorithm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual int32_t hash(const string & sKey)
|
virtual int32_t hash(const string & sKey);
|
||||||
{
|
virtual TC_HashAlgorithmType getHashType();
|
||||||
string sMd5 = TC_MD5::md5bin(sKey);
|
|
||||||
const char *p = (const char *) sMd5.c_str();
|
|
||||||
|
|
||||||
int32_t hash = (*(int*)(p)) ^ (*(int*)(p+4)) ^ (*(int*)(p+8)) ^ (*(int*)(p+12));
|
|
||||||
|
|
||||||
return subTo32Bit(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual TC_HashAlgorithmType getHashType()
|
|
||||||
{
|
|
||||||
return E_TC_CONHASH_DEFAULTHASH;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,34 +74,7 @@ public:
|
|||||||
class TC_HashAlgFactory
|
class TC_HashAlgFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static TC_HashAlgorithm *getHashAlg()
|
static TC_HashAlgorithm *getHashAlg(TC_HashAlgorithmType hashType);
|
||||||
{
|
|
||||||
TC_HashAlgorithm *ptrHashAlg = new TC_DefaultHashAlg();
|
|
||||||
|
|
||||||
return ptrHashAlg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TC_HashAlgorithm *getHashAlg(TC_HashAlgorithmType hashType)
|
|
||||||
{
|
|
||||||
TC_HashAlgorithm *ptrHashAlg = NULL;
|
|
||||||
|
|
||||||
switch(hashType)
|
|
||||||
{
|
|
||||||
case E_TC_CONHASH_KETAMAHASH:
|
|
||||||
{
|
|
||||||
ptrHashAlg = new TC_KetamaHashAlg();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case E_TC_CONHASH_DEFAULTHASH:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
ptrHashAlg = new TC_DefaultHashAlg();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptrHashAlg;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,93 +84,42 @@ class TC_ConsistentHashNew
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
struct node_T_new
|
||||||
* @brief 构造函数
|
|
||||||
*/
|
|
||||||
TC_ConsistentHashNew()
|
|
||||||
{
|
{
|
||||||
_ptrHashAlg = TC_HashAlgFactory::getHashAlg();
|
/**
|
||||||
}
|
*节点hash值
|
||||||
|
*/
|
||||||
|
int32_t iHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*节点下标
|
||||||
|
*/
|
||||||
|
unsigned int iIndex;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 构造函数
|
* @brief 构造函数
|
||||||
*/
|
*/
|
||||||
TC_ConsistentHashNew(TC_HashAlgorithmType hashType)
|
TC_ConsistentHashNew();
|
||||||
{
|
|
||||||
_ptrHashAlg = TC_HashAlgFactory::getHashAlg(hashType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 节点比较.
|
* @brief 构造函数
|
||||||
*
|
|
||||||
* @param m1 node_T_new类型的对象,比较节点之一
|
|
||||||
* @param m2 node_T_new类型的对象,比较节点之一
|
|
||||||
* @return less or not 比较结果,less返回ture,否则返回false
|
|
||||||
*/
|
*/
|
||||||
static bool less_hash(const node_T_new & m1, const node_T_new & m2)
|
TC_ConsistentHashNew(TC_HashAlgorithmType hashType);
|
||||||
{
|
|
||||||
return m1.iHashCode < m2.iHashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 增加节点.
|
* @brief 排序
|
||||||
*
|
*
|
||||||
* @param node 节点名称
|
* @param node 节点名称
|
||||||
* @param index 节点的下标值
|
* @param index 节点的下标值
|
||||||
* @return 节点的hash值
|
|
||||||
*/
|
*/
|
||||||
int sortNode()
|
void sortNode();
|
||||||
{
|
|
||||||
sort(_vHashList.begin(), _vHashList.end(), less_hash);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 打印节点信息
|
* @brief 打印节点信息
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void printNode()
|
void printNode();
|
||||||
{
|
|
||||||
map<unsigned int, unsigned int> mapNode;
|
|
||||||
size_t size = _vHashList.size();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
unsigned int value = 0xFFFFFFFF - _vHashList[size - 1].iHashCode + _vHashList[0].iHashCode;
|
|
||||||
mapNode[_vHashList[0].iIndex] = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int value = _vHashList[i].iHashCode - _vHashList[i - 1].iHashCode;
|
|
||||||
|
|
||||||
if (mapNode.find(_vHashList[i].iIndex) != mapNode.end())
|
|
||||||
{
|
|
||||||
value += mapNode[_vHashList[i].iIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
mapNode[_vHashList[i].iIndex] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "printNode: " << _vHashList[i].iHashCode << "|" << _vHashList[i].iIndex << "|" << mapNode[_vHashList[i].iIndex] << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
map<unsigned int, unsigned int>::iterator it = mapNode.begin();
|
|
||||||
double avg = 100;
|
|
||||||
double sum = 0;
|
|
||||||
|
|
||||||
while (it != mapNode.end())
|
|
||||||
{
|
|
||||||
double tmp = it->second;
|
|
||||||
cerr << "result: " << it->first << "|" << it->second << "|" << (tmp * 100 * mapNode.size() / 0xFFFFFFFF - avg) << endl;
|
|
||||||
sum += (tmp * 100 * mapNode.size() / 0xFFFFFFFF - avg) * (tmp * 100 * mapNode.size() / 0xFFFFFFFF - avg);
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << "variance: " << sum / mapNode.size() << ", size: " << _vHashList.size() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 增加节点.
|
* @brief 增加节点.
|
||||||
@ -250,46 +129,7 @@ public:
|
|||||||
* @param weight 节点的权重,默认为1
|
* @param weight 节点的权重,默认为1
|
||||||
* @return 是否成功
|
* @return 是否成功
|
||||||
*/
|
*/
|
||||||
int addNode(const string & node, unsigned int index, int weight = 1)
|
int addNode(const string & node, unsigned int index, int weight = 1);
|
||||||
{
|
|
||||||
if (_ptrHashAlg.get() == NULL)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_T_new stItem;
|
|
||||||
stItem.iIndex = index;
|
|
||||||
|
|
||||||
for (int j = 0; j < weight; j++)
|
|
||||||
{
|
|
||||||
string virtualNode = node + "_" + TC_Common::tostr<int>(j);
|
|
||||||
|
|
||||||
// TODO: 目前写了2 种hash 算法,可以根据需要选择一种,
|
|
||||||
// TODO: 其中KEMATA 为参考memcached client 的hash 算法,default 为原有的hash 算法,测试结论在表格里有
|
|
||||||
if (_ptrHashAlg->getHashType() == E_TC_CONHASH_KETAMAHASH)
|
|
||||||
{
|
|
||||||
string sMd5 = TC_MD5::md5bin(virtualNode);
|
|
||||||
char *p = (char *) sMd5.c_str();
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
stItem.iHashCode = ((int32_t)(p[i * 4 + 3] & 0xFF) << 24)
|
|
||||||
| ((int32_t)(p[i * 4 + 2] & 0xFF) << 16)
|
|
||||||
| ((int32_t)(p[i * 4 + 1] & 0xFF) << 8)
|
|
||||||
| ((int32_t)(p[i * 4 + 0] & 0xFF));
|
|
||||||
stItem.iIndex = index;
|
|
||||||
_vHashList.push_back(stItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stItem.iHashCode = _ptrHashAlg->hash(virtualNode);
|
|
||||||
_vHashList.push_back(stItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取某key对应到的节点node的下标.
|
* @brief 获取某key对应到的节点node的下标.
|
||||||
@ -298,18 +138,7 @@ public:
|
|||||||
* @param iIndex 对应到的节点下标
|
* @param iIndex 对应到的节点下标
|
||||||
* @return 0:获取成功 -1:没有被添加的节点
|
* @return 0:获取成功 -1:没有被添加的节点
|
||||||
*/
|
*/
|
||||||
int getIndex(const string & key, unsigned int & iIndex)
|
int getIndex(const string & key, unsigned int & iIndex);
|
||||||
{
|
|
||||||
if(_ptrHashAlg.get() == NULL || _vHashList.size() == 0)
|
|
||||||
{
|
|
||||||
iIndex = 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t iCode = _ptrHashAlg->hash(TC_MD5::md5bin(key));
|
|
||||||
|
|
||||||
return getIndex(iCode, iIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取某hashcode对应到的节点node的下标.
|
* @brief 获取某hashcode对应到的节点node的下标.
|
||||||
@ -318,60 +147,20 @@ public:
|
|||||||
* @param iIndex 对应到的节点下标
|
* @param iIndex 对应到的节点下标
|
||||||
* @return 0:获取成功 -1:没有被添加的节点
|
* @return 0:获取成功 -1:没有被添加的节点
|
||||||
*/
|
*/
|
||||||
int getIndex(int32_t hashcode, unsigned int & iIndex)
|
int getIndex(int32_t hashcode, unsigned int & iIndex);
|
||||||
{
|
|
||||||
if(_ptrHashAlg.get() == NULL || _vHashList.size() == 0)
|
|
||||||
{
|
|
||||||
iIndex = 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 只保留32位
|
|
||||||
size_t iCode = (hashcode & 0xFFFFFFFFL);
|
|
||||||
|
|
||||||
int low = 0;
|
|
||||||
size_t high = _vHashList.size();
|
|
||||||
|
|
||||||
if(iCode <= _vHashList[0].iHashCode || iCode > _vHashList[high-1].iHashCode)
|
|
||||||
{
|
|
||||||
iIndex = _vHashList[0].iIndex;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (low < high - 1)
|
|
||||||
{
|
|
||||||
int mid = (low + high) / 2;
|
|
||||||
if (_vHashList[mid].iHashCode > iCode)
|
|
||||||
{
|
|
||||||
high = mid;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
low = mid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iIndex = _vHashList[low+1].iIndex;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取当前hash列表的长度.
|
* @brief 获取当前hash列表的长度.
|
||||||
*
|
*
|
||||||
* @return 长度值
|
* @return 长度值
|
||||||
*/
|
*/
|
||||||
size_t size()
|
size_t size() { return _vHashList.size(); }
|
||||||
{
|
|
||||||
return _vHashList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 清空当前的hash列表.
|
* @brief 清空当前的hash列表.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void clear()
|
void clear() { _vHashList.clear(); }
|
||||||
{
|
|
||||||
_vHashList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
vector<node_T_new> _vHashList;
|
vector<node_T_new> _vHashList;
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
namespace tars
|
namespace tars
|
||||||
{
|
{
|
||||||
|
|
||||||
struct RequestPacket;
|
// struct RequestPacket;
|
||||||
struct ResponsePacket;
|
// struct ResponsePacket;
|
||||||
|
|
||||||
enum ResponseState
|
enum ResponseState
|
||||||
{
|
{
|
||||||
@ -154,6 +154,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
nghttp2_session* session() const;
|
nghttp2_session* session() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 响应包
|
||||||
|
*/
|
||||||
|
std::map<int, Http2Response> &doneResponses() { return _doneResponses; }
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* session
|
* session
|
||||||
|
241
util/src/tc_consistent_hash_new.cpp
Executable file
241
util/src/tc_consistent_hash_new.cpp
Executable file
@ -0,0 +1,241 @@
|
|||||||
|
/**
|
||||||
|
* Tencent is pleased to support the open source community by making Tars available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "util/tc_consistent_hash_new.h"
|
||||||
|
// #include "util/tc_autoptr.h"
|
||||||
|
// #include "util/tc_hash_fun.h"
|
||||||
|
|
||||||
|
using namespace tars;
|
||||||
|
|
||||||
|
namespace tars
|
||||||
|
{
|
||||||
|
|
||||||
|
int32_t TC_KetamaHashAlg::hash(const string & sKey)
|
||||||
|
{
|
||||||
|
string sMd5 = TC_MD5::md5bin(sKey);
|
||||||
|
const char *p = (const char *) sMd5.c_str();
|
||||||
|
|
||||||
|
int32_t hash = ((int32_t)(p[3] & 0xFF) << 24)
|
||||||
|
| ((int32_t)(p[2] & 0xFF) << 16)
|
||||||
|
| ((int32_t)(p[1] & 0xFF) << 8)
|
||||||
|
| ((int32_t)(p[0] & 0xFF));
|
||||||
|
|
||||||
|
return subTo32Bit(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
TC_HashAlgorithmType TC_KetamaHashAlg::getHashType()
|
||||||
|
{
|
||||||
|
return E_TC_CONHASH_KETAMAHASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t TC_DefaultHashAlg::hash(const string & sKey)
|
||||||
|
{
|
||||||
|
string sMd5 = TC_MD5::md5bin(sKey);
|
||||||
|
const char *p = (const char *) sMd5.c_str();
|
||||||
|
|
||||||
|
int32_t hash = (*(int*)(p)) ^ (*(int*)(p+4)) ^ (*(int*)(p+8)) ^ (*(int*)(p+12));
|
||||||
|
|
||||||
|
return subTo32Bit(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
TC_HashAlgorithmType TC_DefaultHashAlg::getHashType()
|
||||||
|
{
|
||||||
|
return E_TC_CONHASH_DEFAULTHASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
TC_HashAlgorithm *TC_HashAlgFactory::getHashAlg(TC_HashAlgorithmType hashType)
|
||||||
|
{
|
||||||
|
TC_HashAlgorithm *ptrHashAlg = NULL;
|
||||||
|
|
||||||
|
switch(hashType)
|
||||||
|
{
|
||||||
|
case E_TC_CONHASH_KETAMAHASH:
|
||||||
|
{
|
||||||
|
ptrHashAlg = new TC_KetamaHashAlg();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_TC_CONHASH_DEFAULTHASH:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ptrHashAlg = new TC_DefaultHashAlg();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptrHashAlg;
|
||||||
|
}
|
||||||
|
|
||||||
|
TC_ConsistentHashNew::TC_ConsistentHashNew()
|
||||||
|
{
|
||||||
|
_ptrHashAlg = TC_HashAlgFactory::getHashAlg(E_TC_CONHASH_DEFAULTHASH);
|
||||||
|
}
|
||||||
|
|
||||||
|
TC_ConsistentHashNew::TC_ConsistentHashNew(TC_HashAlgorithmType hashType)
|
||||||
|
{
|
||||||
|
_ptrHashAlg = TC_HashAlgFactory::getHashAlg(hashType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 节点比较.
|
||||||
|
*
|
||||||
|
* @param m1 node_T_new类型的对象,比较节点之一
|
||||||
|
* @param m2 node_T_new类型的对象,比较节点之一
|
||||||
|
* @return less or not 比较结果,less返回ture,否则返回false
|
||||||
|
*/
|
||||||
|
static bool less_hash(const TC_ConsistentHashNew::node_T_new & m1, const TC_ConsistentHashNew::node_T_new & m2)
|
||||||
|
{
|
||||||
|
return m1.iHashCode < m2.iHashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TC_ConsistentHashNew::sortNode()
|
||||||
|
{
|
||||||
|
sort(_vHashList.begin(), _vHashList.end(), less_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TC_ConsistentHashNew::printNode()
|
||||||
|
{
|
||||||
|
map<unsigned int, unsigned int> mapNode;
|
||||||
|
size_t size = _vHashList.size();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
unsigned int value = 0xFFFFFFFF - _vHashList[size - 1].iHashCode + _vHashList[0].iHashCode;
|
||||||
|
mapNode[_vHashList[0].iIndex] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int value = _vHashList[i].iHashCode - _vHashList[i - 1].iHashCode;
|
||||||
|
|
||||||
|
if (mapNode.find(_vHashList[i].iIndex) != mapNode.end())
|
||||||
|
{
|
||||||
|
value += mapNode[_vHashList[i].iIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
mapNode[_vHashList[i].iIndex] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "printNode: " << _vHashList[i].iHashCode << "|" << _vHashList[i].iIndex << "|" << mapNode[_vHashList[i].iIndex] << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
map<unsigned int, unsigned int>::iterator it = mapNode.begin();
|
||||||
|
double avg = 100;
|
||||||
|
double sum = 0;
|
||||||
|
|
||||||
|
while (it != mapNode.end())
|
||||||
|
{
|
||||||
|
double tmp = it->second;
|
||||||
|
cerr << "result: " << it->first << "|" << it->second << "|" << (tmp * 100 * mapNode.size() / 0xFFFFFFFF - avg) << endl;
|
||||||
|
sum += (tmp * 100 * mapNode.size() / 0xFFFFFFFF - avg) * (tmp * 100 * mapNode.size() / 0xFFFFFFFF - avg);
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr << "variance: " << sum / mapNode.size() << ", size: " << _vHashList.size() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TC_ConsistentHashNew::addNode(const string & node, unsigned int index, int weight)
|
||||||
|
{
|
||||||
|
if (_ptrHashAlg.get() == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_T_new stItem;
|
||||||
|
stItem.iIndex = index;
|
||||||
|
|
||||||
|
for (int j = 0; j < weight; j++)
|
||||||
|
{
|
||||||
|
string virtualNode = node + "_" + TC_Common::tostr<int>(j);
|
||||||
|
|
||||||
|
// TODO: 目前写了2 种hash 算法,可以根据需要选择一种,
|
||||||
|
// TODO: 其中KEMATA 为参考memcached client 的hash 算法,default 为原有的hash 算法,测试结论在表格里有
|
||||||
|
if (_ptrHashAlg->getHashType() == E_TC_CONHASH_KETAMAHASH)
|
||||||
|
{
|
||||||
|
string sMd5 = TC_MD5::md5bin(virtualNode);
|
||||||
|
char *p = (char *) sMd5.c_str();
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
stItem.iHashCode = ((int32_t)(p[i * 4 + 3] & 0xFF) << 24)
|
||||||
|
| ((int32_t)(p[i * 4 + 2] & 0xFF) << 16)
|
||||||
|
| ((int32_t)(p[i * 4 + 1] & 0xFF) << 8)
|
||||||
|
| ((int32_t)(p[i * 4 + 0] & 0xFF));
|
||||||
|
stItem.iIndex = index;
|
||||||
|
_vHashList.push_back(stItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stItem.iHashCode = _ptrHashAlg->hash(virtualNode);
|
||||||
|
_vHashList.push_back(stItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TC_ConsistentHashNew::getIndex(const string & key, unsigned int & iIndex)
|
||||||
|
{
|
||||||
|
if(_ptrHashAlg.get() == NULL || _vHashList.size() == 0)
|
||||||
|
{
|
||||||
|
iIndex = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t iCode = _ptrHashAlg->hash(TC_MD5::md5bin(key));
|
||||||
|
|
||||||
|
return getIndex(iCode, iIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int TC_ConsistentHashNew::getIndex(int32_t hashcode, unsigned int & iIndex)
|
||||||
|
{
|
||||||
|
if(_ptrHashAlg.get() == NULL || _vHashList.size() == 0)
|
||||||
|
{
|
||||||
|
iIndex = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只保留32位
|
||||||
|
size_t iCode = (hashcode & 0xFFFFFFFFL);
|
||||||
|
|
||||||
|
int low = 0;
|
||||||
|
size_t high = _vHashList.size();
|
||||||
|
|
||||||
|
if(iCode <= _vHashList[0].iHashCode || iCode > _vHashList[high-1].iHashCode)
|
||||||
|
{
|
||||||
|
iIndex = _vHashList[0].iIndex;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (low < high - 1)
|
||||||
|
{
|
||||||
|
int mid = (low + high) / 2;
|
||||||
|
if (_vHashList[mid].iHashCode > iCode)
|
||||||
|
{
|
||||||
|
high = mid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
low = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iIndex = _vHashList[low+1].iIndex;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1532,20 +1532,20 @@ void TC_HttpRequest::encode(int iRequestType, ostream &os)
|
|||||||
|
|
||||||
void TC_HttpRequest::setRequest(const string& method, const string &sUrl, const std::string& body, bool bNewCreateHost)
|
void TC_HttpRequest::setRequest(const string& method, const string &sUrl, const std::string& body, bool bNewCreateHost)
|
||||||
{
|
{
|
||||||
std::string lowMethod(method);
|
// std::string lowMethod(method);
|
||||||
std::transform(method.begin(), method.end(), lowMethod.begin(), ::tolower);
|
// std::transform(method.begin(), method.end(), lowMethod.begin(), ::tolower);
|
||||||
|
|
||||||
if (lowMethod == "get")
|
if (TC_Port::strncasecmp(method.c_str(), "GET", 3) == 0)
|
||||||
setGetRequest(sUrl, bNewCreateHost);
|
setGetRequest(sUrl, bNewCreateHost);
|
||||||
else if (lowMethod == "head")
|
else if (TC_Port::strncasecmp(method.c_str(), "HEAD", 4) == 0)
|
||||||
setHeadRequest(sUrl, bNewCreateHost);
|
setHeadRequest(sUrl, bNewCreateHost);
|
||||||
else if (lowMethod == "post")
|
else if (TC_Port::strncasecmp(method.c_str(), "POST", 4) == 0)
|
||||||
setPostRequest(sUrl, body, bNewCreateHost);
|
setPostRequest(sUrl, body, bNewCreateHost);
|
||||||
else if (lowMethod == "put")
|
else if (TC_Port::strncasecmp(method.c_str(), "PUT", 3) == 0)
|
||||||
setPutRequest(sUrl, body, bNewCreateHost);
|
setPutRequest(sUrl, body, bNewCreateHost);
|
||||||
else if (lowMethod == "delete")
|
else if (TC_Port::strncasecmp(method.c_str(), "DELETE", 6) == 0)
|
||||||
setDeleteRequest(sUrl, body, bNewCreateHost);
|
setDeleteRequest(sUrl, body, bNewCreateHost);
|
||||||
else if (lowMethod == "patch")
|
else if (TC_Port::strncasecmp(method.c_str(), "PATH", 5) == 0)
|
||||||
setPatchRequest(sUrl, body, bNewCreateHost);
|
setPatchRequest(sUrl, body, bNewCreateHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
#include "nghttp2/nghttp2.h"
|
#include "nghttp2/nghttp2.h"
|
||||||
|
|
||||||
#include "util/tc_nghttp2.h"
|
#include "util/tc_nghttp2.h"
|
||||||
#include "util/tc_http2clientmgr.h"
|
// #include "util/tc_http2clientmgr.h"
|
||||||
#include "util/tc_base64.h"
|
#include "util/tc_base64.h"
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user