搜狗workflow项目研究(十四)http性能改动

搜狗workflow项目研究(十四)http性能改动,第1张

搜狗workflow项目研究(十四)http性能改动

2021SC@SDUSC

本周主要任务是改进HttpTaskImpl.cc中的ComplexHttpTask::message_out()部分代码,提高http性能。

在简单的http request client中,任务被调起,发送request(request优先复用,然后message_out发送)

相关代码在workflow/src/factory/HttpTaskImpl.cc中。

用gdb查看

cgdb ./wget

(gdb) set args www.baidu.com

(gdb) b HttpTaskImpl.cc:ComplexHttpTask::message_out

分析代码可以看到,这里一共用了4次find header,分别是"Transfer-Encoding","Content-Length", "Connection","Keep-Alive",伴随了三次cursor的rewind。

旧版代码如下:

CommMessageOut *ComplexHttpProxyTask::message_out()
{
	long long seqid = this->get_seq();

	if (seqid == 0) // ConNECT
	{
		HttpRequest *conn_req = new HttpRequest;
		std::string request_uri(user_uri_.host);

		request_uri += ":";
		if (user_uri_.port)
			request_uri += user_uri_.port;
		else
			request_uri += is_ssl_ ? "443" : "80";

		conn_req->set_method("CONNECT");
		conn_req->set_request_uri(request_uri);
		conn_req->set_http_version("HTTP/1.1");
		conn_req->add_header_pair("Host", request_uri.c_str());

		if (!proxy_auth_.empty())
			conn_req->add_header_pair("Proxy-Authorization", proxy_auth_);

		is_user_request_ = false;
		return conn_req;
	}
	else if (seqid == 1 && is_ssl_) // HANDSHAKE
	{
		is_user_request_ = false;
		return get_ssl_handshaker();
	}

	auto *msg = (ProtocolMessage *)this->ComplexHttpTask::message_out();
	return is_ssl_ ? get_ssl_wrapper(msg) : msg;
}

修改后新代码如下:

CommMessageOut *ComplexHttpTask::message_out()
{
	HttpRequest *req = this->get_req();
	struct HttpMessageHeader header;
	bool is_alive;

	// 如果不为chunked 且req没有content_length 的 header
	if (!req->is_chunked() && !req->has_content_length_header())
	{
		size_t body_size = req->get_output_body_size();
		const char *method = req->get_method();

		if (body_size != 0 || strcmp(method, "POST") == 0 ||
							  strcmp(method, "PUT") == 0)
		{
			// 同理,不为chunked的话,那我们给他添加上 "Content-Length" 这个header
			char buf[32];
			header.name = "Content-Length";
			header.name_len = strlen("Content-Length");
			header.value = buf;
			header.value_len = sprintf(buf, "%zu", body_size);
			req->add_header(&header);
		}
	}
	
	// 如果req有connection_header
	if (req->has_connection_header())
		// 查看是否is_keep_alive
		is_alive = req->is_keep_alive();
	else
	{
		// 如果没有,我们帮用户添加
		header.name = "Connection";
		header.name_len = strlen("Connection");
		is_alive = (this->keep_alive_timeo != 0);  // 如果是time_out不为0,则是Keep-Alive
		if (is_alive)
		{
			header.value = "Keep-Alive";
			header.value_len = strlen("Keep-Alive");
		}
		else
		{
			header.value = "close";
			header.value_len = strlen("close");
		}
	
		req->add_header(&header);
	}

	if (!is_alive)
		this->keep_alive_timeo = 0;
	else if (req->has_keep_alive_header())
	{
		// 这里因为不是简单的有没有的信息,而是要把这个字段取出切割,还是得用一次find
		HttpHeaderCursor req_cursor(req);

		//req---Connection: Keep-Alive
		//req---Keep-Alive: timeout=0,max=100
		header.name = "Keep-Alive";
		header.name_len = strlen("Keep-Alive");
		if (req_cursor.find(&header))
		{
			std::string keep_alive((const char *)header.value, header.value_len);
			std::vector params = StringUtil::split(keep_alive, ',');

			for (const auto& kv : params)
			{
				std::vector arr = StringUtil::split(kv, '=');
				if (arr.size() < 2)
					arr.emplace_back("0");

				std::string key = StringUtil::strip(arr[0]);
				std::string val = StringUtil::strip(arr[1]);
				if (strcasecmp(key.c_str(), "timeout") == 0)
				{
					this->keep_alive_timeo = 1000 * atoi(val.c_str());
					break;
				}
			}
		}

		if ((unsigned int)this->keep_alive_timeo > HTTP_KEEPALIVE_MAX)
			this->keep_alive_timeo = HTTP_KEEPALIVE_MAX;
		//if (this->keep_alive_timeo < 0 || this->keep_alive_timeo > HTTP_KEEPALIVE_MAX)
	}

	//req->set_header_pair("Accept", "*/*");
	return this->WFComplexClientTask::message_out();
}

原代码没有利用好http_parser中的一些记录信息, 比如说是否是chunked,是否有content_length _header等等,而是反复的rewind去find这些字段。新代码改进了这点不足。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5684430.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存