Skip to content

Commit 94db70d

Browse files
committed
[docs] 文章内容更新
1 parent f75a5bc commit 94db70d

4 files changed

Lines changed: 75 additions & 75 deletions

File tree

docs/blog/08-hical-mysql-crud.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77
## 三种姿势对比
88

9-
| 方式 | 代码量 | 连接池 | 异步 | 防注入 |
10-
|------|--------|--------|------|--------|
11-
|`mysql_query` | 多,手动管理连接 | 手写 | 阻塞 | 手拼字符串,危险 |
12-
| ORM(如 ODB) | 少,但有运行时膨胀 | 内置 | 视实现而定 | 安全 |
13-
| Hical 协程中间件 | 少,原生协程 | 内置 | 非阻塞 `co_await` | PreparedStatement |
9+
| 方式 | 代码量 | 连接池 | 异步 | 防注入 |
10+
| ---------------- | ------------------ | ------ | ----------------- | ----------------- |
11+
|`mysql_query` | 多,手动管理连接 | 手写 | 阻塞 | 手拼字符串,危险 |
12+
| ORM(如 ODB) | 少,但有运行时膨胀 | 内置 | 视实现而定 | 安全 |
13+
| Hical 协程中间件 | 少,原生协程 | 内置 | 非阻塞 `co_await` | PreparedStatement |
1414

1515
Hical 走第三条路:连接池是协程化的,查询全部走 PreparedStatement 防注入,事务在中间件层自动管理,业务代码只关心 SQL 逻辑。
1616

@@ -304,28 +304,28 @@ server.use(makeQueryLogMiddleware(QueryLogOptions{
304304

305305
`QueryLogEntry` 的字段:
306306

307-
| 字段 | 类型 | 说明 |
308-
|------|------|------|
309-
| `sql` | `std::string` | 原始 SQL 文本 |
310-
| `duration` | `std::chrono::microseconds` | 执行耗时 |
311-
| `rowCount` | `size_t` | 返回行数(SELECT) |
312-
| `affectedRows` | `uint64_t` | 影响行数(DML) |
313-
| `isParameterized` | `bool` | 是否使用了参数化查询 |
307+
| 字段 | 类型 | 说明 |
308+
| ----------------- | --------------------------- | -------------------- |
309+
| `sql` | `std::string` | 原始 SQL 文本 |
310+
| `duration` | `std::chrono::microseconds` | 执行耗时 |
311+
| `rowCount` | `size_t` | 返回行数(SELECT) |
312+
| `affectedRows` | `uint64_t` | 影响行数(DML) |
313+
| `isParameterized` | `bool` | 是否使用了参数化查询 |
314314

315315
---
316316

317317
## 连接池参数调优
318318

319-
| 参数 | 默认值 | 推荐场景 |
320-
|------|--------|----------|
321-
| `minConnections` | 2 | 低流量服务保持 2-4,避免冷启动延迟 |
322-
| `maxConnections` | 16 | 单机 Web 服务通常 16-32,不超过 MySQL `max_connections` 的 1/4 |
323-
| `idleTimeout` | 300s | MySQL 默认 `wait_timeout` 8h,设 5 分钟绰绰有余 |
324-
| `acquireTimeout` | 5s | 池满等待上限;超时返回 503 而非无限阻塞 |
325-
| `queryTimeout` | 30s | 防止慢查询耗尽所有连接;OLTP 场景建议设 3-5s |
326-
| `healthCheckInterval` | 30s | 定期 ping 空闲连接,防止 MySQL 服务端主动断开 |
327-
| `pingGracePeriod` | 15s | 距上次 ping 不超过 15s 则跳过,减少不必要的往返 |
328-
| `stmtCacheSize` | 64 | 每连接 LRU 缓存容量,见下节 |
319+
| 参数 | 默认值 | 推荐场景 |
320+
| --------------------- | ------ | -------------------------------------------------------------- |
321+
| `minConnections` | 2 | 低流量服务保持 2-4,避免冷启动延迟 |
322+
| `maxConnections` | 16 | 单机 Web 服务通常 16-32,不超过 MySQL `max_connections` 的 1/4 |
323+
| `idleTimeout` | 300s | MySQL 默认 `wait_timeout` 8h,设 5 分钟绰绰有余 |
324+
| `acquireTimeout` | 5s | 池满等待上限;超时返回 503 而非无限阻塞 |
325+
| `queryTimeout` | 30s | 防止慢查询耗尽所有连接;OLTP 场景建议设 3-5s |
326+
| `healthCheckInterval` | 30s | 定期 ping 空闲连接,防止 MySQL 服务端主动断开 |
327+
| `pingGracePeriod` | 15s | 距上次 ping 不超过 15s 则跳过,减少不必要的往返 |
328+
| `stmtCacheSize` | 64 | 每连接 LRU 缓存容量,见下节 |
329329

330330
高并发写入场景参考配置:
331331

docs/blog/09-hical-logging-guide.md

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# C++ Web 服务日志最佳实践:Hical 日志系统完全指南
22

3-
> **适用版本**:Hical v2.4+
3+
> **适用版本**:Hical v2.5+
44
> **难度**:初中级
55
> **阅读时间**:约 15 分钟
66
@@ -66,14 +66,14 @@ HICAL_LOG_DEBUG_IF(req.method() == HttpMethod::EPost, "POST body size={}", req.b
6666

6767
Hical 定义了六个日志级别,对应不同使用场景:
6868

69-
| 宏后缀 | 枚举值 | 典型用途 |
70-
|--------|--------|----------|
69+
| 宏后缀 | 枚举值 | 典型用途 |
70+
| ------- | -------- | ----------------------------------------------------------- |
7171
| `TRACE` | `hTrace` | 极细粒度调试(循环内、协议字节级),**NDEBUG 下编译期消除** |
72-
| `DEBUG` | `hDebug` | 开发期调试信息,不进生产 |
73-
| `INFO` | `hInfo` | 正常运行信息(启动、请求摘要),**生产默认级别** |
74-
| `WARN` | `hWarn` | 值得关注但不影响服务的异常(重试、降级) |
75-
| `ERROR` | `hError` | 需要处理的错误,服务仍在运行 |
76-
| `FATAL` | `hFatal` | 不可恢复错误,自动 flush 全部缓冲区然后 `abort()` |
72+
| `DEBUG` | `hDebug` | 开发期调试信息,不进生产 |
73+
| `INFO` | `hInfo` | 正常运行信息(启动、请求摘要),**生产默认级别** |
74+
| `WARN` | `hWarn` | 值得关注但不影响服务的异常(重试、降级) |
75+
| `ERROR` | `hError` | 需要处理的错误,服务仍在运行 |
76+
| `FATAL` | `hFatal` | 不可恢复错误,自动 flush 全部缓冲区然后 `abort()` |
7777

7878
### 运行时级别设置
7979

@@ -446,16 +446,16 @@ int main()
446446

447447
## 10. 与 spdlog / glog 的差异
448448

449-
| 特性 | spdlog | glog | Hical Log |
450-
|------|--------|------|-----------|
451-
| API 风格 | `fmt::format` | `<<` 流式 | 两者都支持,`std::format` |
452-
| 异步写盘 | 有(异步 logger) || `AsyncFileSink` 双缓冲 |
453-
| 文件轮转 ||| `LogFile`,大小轮转 + 数量限制 |
454-
| 结构化字段 | 无内置 | 无内置 | `HICAL_LOG_INFO_F` + JSON Lines |
455-
| 通道路由 | sink 可分 logger || `LogChannel` 命名通道,独立 level/formatter/sink |
456-
| HTTP 集成 ||| `makeLogMiddleware()` 一键 trace-id + 访问日志 |
457-
| 运行时调级 | 无 HTTP 端点 | 无 HTTP 端点 | `LogAdmin` REST 端点 |
458-
| 协程友好 | 线程局部安全 | 线程局部安全 | 设计上与 Boost.Asio 协程共存,无 TLS 阻塞 |
449+
| 特性 | spdlog | glog | Hical Log |
450+
| ---------- | ----------------- | ------------ | ------------------------------------------------ |
451+
| API 风格 | `fmt::format` | `<<` 流式 | 两者都支持,`std::format` |
452+
| 异步写盘 | 有(异步 logger) | | `AsyncFileSink` 双缓冲 |
453+
| 文件轮转 | | | `LogFile`,大小轮转 + 数量限制 |
454+
| 结构化字段 | 无内置 | 无内置 | `HICAL_LOG_INFO_F` + JSON Lines |
455+
| 通道路由 | sink 可分 logger | | `LogChannel` 命名通道,独立 level/formatter/sink |
456+
| HTTP 集成 | | | `makeLogMiddleware()` 一键 trace-id + 访问日志 |
457+
| 运行时调级 | 无 HTTP 端点 | 无 HTTP 端点 | `LogAdmin` REST 端点 |
458+
| 协程友好 | 线程局部安全 | 线程局部安全 | 设计上与 Boost.Asio 协程共存,无 TLS 阻塞 |
459459

460460
Hical 日志的差异化在于**和 HTTP 框架的深度集成**:trace-id 的生成、传递、写入访问日志、运行时调级,都是框架层面的一等公民,不需要自己拼装。如果你用的是纯 spdlog,这些都得自己搭。
461461

@@ -467,12 +467,12 @@ Hical 日志的差异化在于**和 HTTP 框架的深度集成**:trace-id 的
467467

468468
5 个常见需求的对应方案:
469469

470-
| 需求 | 方案 |
471-
|------|------|
472-
| 级别过滤 | `setLevel()` + 6 级枚举,TRACE 在 Release 零开销 |
473-
| 文件轮转 | `FileSink` + `LogFile::Options`(大小 + 数量限制) |
474-
| 异步不阻塞 | `AsyncFileSink`(双缓冲 + 背压保护) |
475-
| 结构化字段 | `JsonFormatter` + `HICAL_LOG_INFO_F` |
476-
| 分布式追踪 | `makeLogMiddleware()` 自动 trace-id + 通道路由 |
470+
| 需求 | 方案 |
471+
| ---------- | -------------------------------------------------- |
472+
| 级别过滤 | `setLevel()` + 6 级枚举,TRACE 在 Release 零开销 |
473+
| 文件轮转 | `FileSink` + `LogFile::Options`(大小 + 数量限制) |
474+
| 异步不阻塞 | `AsyncFileSink`(双缓冲 + 背压保护) |
475+
| 结构化字段 | `JsonFormatter` + `HICAL_LOG_INFO_F` |
476+
| 分布式追踪 | `makeLogMiddleware()` 自动 trace-id + 通道路由 |
477477

478478
完整 API 参考:`src/core/Log.h``src/core/LogChannel.h``src/core/LogMiddleware.h``src/core/LogAdmin.h`

docs/blog/10-hical-openapi-swagger.md

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,17 @@ HICAL_SCHEMA_NAME(ErrorResponse, "ErrorResponse")
7070
7171
**类型映射规则**(由 `jsonSchema<T>()` 在编译期推导):
7272
73-
| C++ 类型 | OpenAPI Schema |
74-
|---|---|
75-
| `std::string` | `{"type":"string"}` |
76-
| `bool` | `{"type":"boolean"}` |
77-
| `int` / `int32_t` | `{"type":"integer","format":"int32"}` |
78-
| `int64_t` | `{"type":"integer","format":"int64"}` |
79-
| `float` | `{"type":"number","format":"float"}` |
80-
| `double` | `{"type":"number","format":"double"}` |
81-
| `std::vector<T>` | `{"type":"array","items":{...}}` |
73+
| C++ 类型 | OpenAPI Schema |
74+
| -------------------------------------------------- | ------------------------------------- |
75+
| `std::string` | `{"type":"string"}` |
76+
| `bool` | `{"type":"boolean"}` |
77+
| `int` / `int32_t` | `{"type":"integer","format":"int32"}` |
78+
| `int64_t` | `{"type":"integer","format":"int64"}` |
79+
| `float` | `{"type":"number","format":"float"}` |
80+
| `double` | `{"type":"number","format":"double"}` |
81+
| `std::vector<T>` | `{"type":"array","items":{...}}` |
8282
| 嵌套 `HICAL_JSON` 结构体(有 `HICAL_SCHEMA_NAME`) | `{"$ref":"#/components/schemas/XXX"}` |
83-
| 嵌套 `HICAL_JSON` 结构体(无名称) | 内联展开完整 schema |
83+
| 嵌套 `HICAL_JSON` 结构体(无名称) | 内联展开完整 schema |
8484
8585
`REQUIRED(field)` 会把该字段加入 schema 的 `required` 数组,与业务验证逻辑保持一致。
8686
@@ -149,15 +149,15 @@ struct UserHandler
149149

150150
**builder 函数速查**
151151

152-
| 函数 | 作用 |
153-
|---|---|
154-
| `builder::summary(info, "...")` | 端点一句话摘要 |
155-
| `builder::description(info, "...")` | 详细描述(支持 Markdown) |
156-
| `builder::tags(info, {"tag1", "tag2"})` | 分组标签,Swagger UI 按此折叠 |
157-
| `builder::request<T>(info, "描述", required)` | 请求体 DTO,自动引用 schema |
158-
| `builder::response<T>(info, 状态码, "描述")` | 有 body 的响应 |
159-
| `builder::responseDesc(info, 状态码, "描述")` | 无 body 的响应(204/404 等) |
160-
| `builder::pathParam(info, "name", "type", "描述")` | 路径参数说明 |
152+
| 函数 | 作用 |
153+
| -------------------------------------------------- | ----------------------------- |
154+
| `builder::summary(info, "...")` | 端点一句话摘要 |
155+
| `builder::description(info, "...")` | 详细描述(支持 Markdown) |
156+
| `builder::tags(info, {"tag1", "tag2"})` | 分组标签,Swagger UI 按此折叠 |
157+
| `builder::request<T>(info, "描述", required)` | 请求体 DTO,自动引用 schema |
158+
| `builder::response<T>(info, 状态码, "描述")` | 有 body 的响应 |
159+
| `builder::responseDesc(info, 状态码, "描述")` | 无 body 的响应(204/404 等) |
160+
| `builder::pathParam(info, "name", "type", "描述")` | 路径参数说明 |
161161

162162
---
163163

@@ -336,14 +336,14 @@ HICAL_API(getUserOrders,
336336
337337
Oat++ 是 C++ 生态里另一个有 Swagger 集成的框架,来看看标注风格的差异:
338338
339-
| 维度 | Hical | Oat++ |
340-
|---|---|---|
341-
| 路由标注 | `HICAL_HANDLER` + `HICAL_API` | `ENDPOINT_INFO` + `ENDPOINT` |
342-
| Schema 生成 | 从 `HICAL_JSON` 自动推导 | 需要继承 `oatpp::DTO` 并用 `DTO_FIELD` |
343-
| 响应声明 | `builder::response<T>(info, 200, "...")` | `info->addResponse<Object<T>>(Status::CODE_200)` |
344-
| 新依赖 | 零(复用 Boost.JSON) | 引入 oatpp-swagger 库 |
345-
| 编译期类型检查 | `static_assert` + concepts | 运行时反射 |
346-
| 内存模型 | 零堆分配查找(透明哈希) | 智能指针 DTO 对象 |
339+
| 维度 | Hical | Oat++ |
340+
| -------------- | ---------------------------------------- | ------------------------------------------------ |
341+
| 路由标注 | `HICAL_HANDLER` + `HICAL_API` | `ENDPOINT_INFO` + `ENDPOINT` |
342+
| Schema 生成 | 从 `HICAL_JSON` 自动推导 | 需要继承 `oatpp::DTO` 并用 `DTO_FIELD` |
343+
| 响应声明 | `builder::response<T>(info, 200, "...")` | `info->addResponse<Object<T>>(Status::CODE_200)` |
344+
| 新依赖 | 零(复用 Boost.JSON) | 引入 oatpp-swagger 库 |
345+
| 编译期类型检查 | `static_assert` + concepts | 运行时反射 |
346+
| 内存模型 | 零堆分配查找(透明哈希) | 智能指针 DTO 对象 |
347347
348348
Hical 的核心差异在于 schema 是**编译期从类型信息推导**的,而不是运行时通过 DTO 对象的虚函数反射。这意味着写错类型在编译阶段就能发现,而不是部署后才看到错误的文档。
349349

docs/blog/12-game-server-http-api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 游戏服务器的 HTTP API 层:为什么我们选择 C++ 而非 Go
22

3-
> 作者来自深圳冰川网络远征Online服务器组,日常用 C++/Lua 维护一个运营了十几年的 MMORPG。本文聊的是一个务实问题:**游戏服务器要不要内嵌 HTTP API?如果要,为什么我们不单独起一个 Go/Python 服务,而是直接把 Hical 嵌进 C++ 进程?**
3+
> 本人是 Hical 框架的作者,负责设计和实现 Hical 框架。本文聊的是一个务实问题:**游戏服务器要不要内嵌 HTTP API?如果要,为什么我们不单独起一个 Go/Python 服务,而是直接把 Hical 嵌进 C++ 进程?**
44
55
---
66

0 commit comments

Comments
 (0)