Skip to content

Commit 4c276ed

Browse files
committed
opt(http):1.13.10, 优化FileDownloaderMiddleware文件下载,允许使用外部线程池
1 parent 604a854 commit 4c276ed

4 files changed

Lines changed: 68 additions & 35 deletions

File tree

examples/http/server/file_download/file_download.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
#include <tbox/util/fs.h>
4141
#include <tbox/trace/sink.h>
4242

43+
//! 是否采用外部线程池,不需要则屏蔽之
44+
#define USE_THREAD_POOL 1
45+
46+
#if USE_THREAD_POOL
47+
#include <tbox/eventx/thread_pool.h>
48+
#endif
49+
4350
using namespace std;
4451
using namespace tbox;
4552
using namespace tbox::event;
@@ -120,6 +127,13 @@ int main(int argc, char **argv)
120127
}
121128
);
122129

130+
#if USE_THREAD_POOL
131+
tbox::eventx::ThreadPool thread_pool(sp_loop);
132+
thread_pool.initialize(2);
133+
#endif
134+
135+
::signal(SIGPIPE, SIG_IGN);
136+
123137
// 初始化信号处理
124138
sp_sig_event->initialize({SIGINT, SIGTERM}, Event::Mode::kPersist);
125139
sp_sig_event->enable();
@@ -136,7 +150,12 @@ int main(int argc, char **argv)
136150

137151
// 创建路由器和文件下载中间件
138152
RouterMiddleware router;
153+
154+
#if USE_THREAD_POOL
155+
FileDownloaderMiddleware file_downloader(sp_loop, &thread_pool);
156+
#else
139157
FileDownloaderMiddleware file_downloader(sp_loop);
158+
#endif
140159

141160
// 添加状态页面路由
142161
router.get("/api/status", [](ContextSptr ctx, const NextFunc& next) {

modules/http/server/middlewares/file_downloader_middleware.cpp

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,26 @@ struct DirectoryConfig {
5858

5959
//! 中间件私有数据结构
6060
struct FileDownloaderMiddleware::Data {
61-
eventx::WorkThread worker;
61+
eventx::ThreadExecutor *worker = nullptr;
62+
eventx::WorkThread *inner_worker = nullptr;
6263
std::vector<DirectoryConfig> directories; //! 目录配置列表
6364
std::map<std::string, std::string> path_mappings;//! 特定路径映射
6465
std::map<std::string, std::string> mime_types; //! MIME类型映射
6566
std::string default_mime_type; //! 默认MIME类型
6667
bool directory_listing_enabled; //! 是否允许目录列表
6768
size_t switch_to_worker_filesize_threshold;
6869

69-
Data(event::Loop *wp_loop)
70-
: worker(wp_loop)
70+
Data(event::Loop *wp_loop, eventx::ThreadExecutor *wp_thread_executor)
71+
: worker(wp_thread_executor)
7172
, default_mime_type("application/octet-stream")
7273
, directory_listing_enabled(false)
7374
, switch_to_worker_filesize_threshold(100 << 10)
7475
{
76+
if (worker == nullptr) {
77+
inner_worker = new tbox::eventx::WorkThread(wp_loop);
78+
worker = inner_worker;
79+
}
80+
7581
//! 初始化常见MIME类型
7682
mime_types["html"] = "text/html";
7783
mime_types["htm"] = "text/html";
@@ -98,13 +104,17 @@ struct FileDownloaderMiddleware::Data {
98104
mime_types["ttf"] = "font/ttf";
99105
mime_types["otf"] = "font/otf";
100106
}
107+
~Data() {
108+
CHECK_DELETE_RESET_OBJ(inner_worker);
109+
}
101110
};
102111

103-
FileDownloaderMiddleware::FileDownloaderMiddleware(event::Loop *wp_loop)
104-
: d_(new Data(wp_loop))
112+
FileDownloaderMiddleware::FileDownloaderMiddleware(event::Loop *wp_loop, eventx::ThreadExecutor *wp_thread_executor)
113+
: d_(new Data(wp_loop, wp_thread_executor))
105114
{ }
106115

107-
FileDownloaderMiddleware::~FileDownloaderMiddleware() { delete d_; }
116+
FileDownloaderMiddleware::~FileDownloaderMiddleware()
117+
{ delete d_; }
108118

109119
bool FileDownloaderMiddleware::addDirectory(const std::string& url_prefix,
110120
const std::string& local_path,
@@ -173,7 +183,7 @@ void FileDownloaderMiddleware::handle(ContextSptr sp_ctx, const NextFunc& next)
173183
//! 查找匹配的目录配置
174184
for (const auto& dir : d_->directories) {
175185
//! 检查URL是否以该目录前缀开头
176-
if (request_path.find(dir.url_prefix) == 0) {
186+
if (tbox::util::string::IsStartWith(request_path, dir.url_prefix)) {
177187
//! 获取相对路径部分
178188
std::string rel_path = request_path.substr(dir.url_prefix.length());
179189

@@ -280,7 +290,7 @@ bool FileDownloaderMiddleware::respondFile(ContextSptr sp_ctx, const std::string
280290

281291
} else {
282292
//! 文件太大就采用子线程去读
283-
d_->worker.execute(
293+
d_->worker->execute(
284294
[sp_ctx, file_path] {
285295
auto& res = sp_ctx->res();
286296
if (util::fs::ReadBinaryFromFile(file_path, res.body)) {
@@ -303,31 +313,32 @@ bool FileDownloaderMiddleware::respondDirectory(ContextSptr sp_ctx,
303313
const std::string& url_path) {
304314
try {
305315
//! 生成HTML目录列表
306-
std::stringstream html;
307-
html << "<!DOCTYPE html>\n"
308-
<< "<html>\n"
309-
<< "<head>\n"
310-
<< " <title>Directory listing for " << url_path << "</title>\n"
311-
<< " <style>\n"
312-
<< " body { font-family: Arial, sans-serif; margin: 20px; }\n"
313-
<< " h1 { color: #333; }\n"
314-
<< " ul { list-style-type: none; padding: 0; }\n"
315-
<< " li { margin: 5px 0; }\n"
316-
<< " a { color: #0066cc; text-decoration: none; }\n"
317-
<< " a:hover { text-decoration: underline; }\n"
318-
<< " .dir { font-weight: bold; }\n"
319-
<< " </style>\n"
320-
<< "</head>\n"
321-
<< "<body>\n"
322-
<< " <h1>Directory listing for " << url_path << "</h1>\n"
323-
<< " <ul>\n";
316+
std::ostringstream html_oss;
317+
html_oss
318+
<< "<!DOCTYPE html>\n"
319+
<< "<html>\n"
320+
<< "<head>\n"
321+
<< " <title>Directory listing for " << url_path << "</title>\n"
322+
<< " <style>\n"
323+
<< " body { font-family: Arial, sans-serif; margin: 20px; }\n"
324+
<< " h1 { color: #333; }\n"
325+
<< " ul { list-style-type: none; padding: 0; }\n"
326+
<< " li { margin: 5px 0; }\n"
327+
<< " a { color: #0066cc; text-decoration: none; }\n"
328+
<< " a:hover { text-decoration: underline; }\n"
329+
<< " .dir { font-weight: bold; }\n"
330+
<< " </style>\n"
331+
<< "</head>\n"
332+
<< "<body>\n"
333+
<< " <h1>Directory listing for " << url_path << "</h1>\n"
334+
<< " <ul>\n";
324335

325336
//! 如果不是根目录,添加返回上级目录的链接
326337
if (url_path != "/") {
327338
size_t last_slash = url_path.find_last_of('/', url_path.size() - 2);
328339
if (last_slash != std::string::npos) {
329340
std::string parent_url = url_path.substr(0, last_slash + 1);
330-
html << " <li><a href=\"" << parent_url << "\">..</a></li>\n";
341+
html_oss << " <li><a href=\"" << parent_url << "\">..</a></li>\n";
331342
}
332343
}
333344

@@ -345,21 +356,22 @@ bool FileDownloaderMiddleware::respondDirectory(ContextSptr sp_ctx,
345356
auto entry_type = util::fs::GetFileType(entry_path);
346357
if (entry_type == util::fs::FileType::kDirectory) {
347358
href += "/";
348-
html << " <li><a class=\"dir\" href=\"" << href << "\">" << name << "/</a></li>\n";
359+
html_oss << " <li><a class=\"dir\" href=\"" << href << "\">" << name << "/</a></li>\n";
349360
} else {
350-
html << " <li><a href=\"" << href << "\">" << name << "</a></li>\n";
361+
html_oss << " <li><a href=\"" << href << "\">" << name << "</a></li>\n";
351362
}
352363
}
353364

354-
html << " </ul>\n"
355-
<< "</body>\n"
356-
<< "</html>";
365+
html_oss
366+
<< " </ul>\n"
367+
<< "</body>\n"
368+
<< "</html>";
357369

358370
//! 设置响应
359371
auto& res = sp_ctx->res();
360372
res.status_code = StatusCode::k200_OK;
361373
res.headers["Content-Type"] = "text/html; charset=utf-8";
362-
res.body = html.str();
374+
res.body = html_oss.str();
363375

364376
LogInfo("Served directory listing for: %s", dir_path.c_str());
365377
return true;

modules/http/server/middlewares/file_downloader_middleware.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <tbox/base/defines.h>
2828
#include <tbox/event/forward.h>
29+
#include <tbox/eventx/thread_executor.h>
2930

3031
#include "../middleware.h"
3132
#include "../context.h"
@@ -45,7 +46,8 @@ class FileDownloaderMiddleware : public Middleware {
4546
/**
4647
* 构造函数
4748
*/
48-
explicit FileDownloaderMiddleware(event::Loop *wp_loop);
49+
explicit FileDownloaderMiddleware(event::Loop *wp_loop,
50+
eventx::ThreadExecutor *wp_thread_executor = nullptr);
4951
virtual ~FileDownloaderMiddleware();
5052

5153
NONCOPYABLE(FileDownloaderMiddleware);

version.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@
2121
# TBOX版本号
2222
TBOX_VERSION_MAJOR := 1
2323
TBOX_VERSION_MINOR := 13
24-
TBOX_VERSION_REVISION := 9
24+
TBOX_VERSION_REVISION := 10

0 commit comments

Comments
 (0)