第11章 配置示例
Configuration Examples
配置示例
本页提供了常见使用场景的配置文件。关于更多演示不同场景和拓扑结构的示例,请参阅 route 库源代码中的 examples 目录。
基础一致性哈希到服务器池
最简配置。 无高层路由:仅将 key 对池中的后端列表进行哈希。 这应等效于标准 memcached 客户端的行为。
```toml pools { main = { backends = { "127.0.0.1:11214", "127.0.0.1:11215", } } }
routes { default = route_direct { child = "main" } } ```
基础复制以实现可用性或速度
关于 memcached 中“复制”的含义详情,请参阅 REPLICATE.md。
```toml pools { -- 创建一个由3个池组成的匿名集合,每个池包含一个服务器。 -- 这样可以在不修改其他配置的情况下,通过向每个池添加服务器来无缝扩展缓存总大小。 set_main = { { backends = { "127.1.0.1:11211" } }, { backends = { "127.1.0.2:11211" } }, { backends = { "127.1.0.3:11211" } }, }, }
routes { cmap = { -- 出于性能原因,重写特定命令以仅从单个服务器获取。 get = route_failover { children = "set_main", stats = true, -- 在 `stats proxy` 中获取额外统计计数器 miss = true, -- 未命中时也进行故障转移,而不仅仅是针对宕机服务器 shuffle = true, -- 每个代理实例将有不同的顺序 }, -- 如果使用了 gat/gets/mg 等命令,在此处进行重写。 }, -- 默认情况下,将命令复制到所有服务器 default = route_allfastest { child = "main", }, } ```
前缀路由器
在此示例中,我们在逻辑上拆分缓存:默认情况下,key 分布在一个服务器池中,以最大化可用内存。然后,将一组访问频率极高的“热”key 复制(replicate)到多个服务器。
```toml pools { main = { backends = { "127.0.0.1:11211", "127.0.0.2:11211", "127.0.0.3:11211", "127.0.0.4:11211", "127.0.0.5:11211", } }, -- 这些甚至可以是上述服务器列表的子集,但是我们必须将其描述为三个池,每个包含一个后端。 set_hot = { { backends = { "127.1.0.1:11211" } }, { backends = { "127.1.0.2:11211" } }, { backends = { "127.1.0.3:11211" } }, }, }
-- 前缀为 "hot/" 的 key 将被路由到特殊处理程序。 routes { map = { hot = cmdmap { -- 默认将所有命令发送到所有池 -- 仅等待一个响应即返回结果 all = route_allfastest { children = "set_hot" }, -- 出于性能原因,重写特定命令以仅从单个服务器获取。 get = route_failover { children = "set_hot", stats = true, miss = true, -- 未命中时也进行故障转移,而不仅仅是针对宕机服务器 shuffle = true, -- 每个代理实例将有不同的顺序 }, -- 如果使用了 gat/gets/mg 等命令,在此处进行重写。 }, }, -- 默认情况下,所有命令映射到大池中的确切一台服务器。 default = route_direct { child = "main", }, } ```
命令映射
如果你不想基于前缀路由,而是仅基于使用的命令进行路由,在构建 routes{} 时将 map 替换为 cmap。
```toml pools { foo = { backends = { "127.0.0.1:11214", "127.0.0.1:11215", } }, bar = { backends = { "127.0.0.1:11216", } }, }
routes { cmap = { get = route_direct { child = "foo", }, }, default = route_allfastest { children = { "bar" } }, } ```
基于监听端口的标签路由
可以根据监听端口拥有不同的路由树。如果你希望仅通过端口路由到不同的池,或为不同服务使用不同的前缀树,这将非常有用。memcached 必须使用类似以下的选项启动: `-l 127.0.0.1:12051 -l tag_b_:127.0.0.1:12052 -l tag_cccc_:127.0.0.1:12053` 这将为 12051 提供默认监听器,为 12052 添加“b”标签,为 12053 添加“cccc”标签。
```toml pools { foo = { backends = { "127.0.0.1:11214", } }, bar = { backends = { { host = "127.0.0.1", port = 11215, retrytimeout = 5 } } }, baz = { backends = { "127.0.0.1:11216", } }, }
-- 未提供标签时,这是 "default" 路由器。 routes { default = route_direct { child = "foo", } }
-- 此路由树仅在客户端连接到端口 12052 时执行 routes { tag = "b", default = route_direct { child = "bar" } }
-- 此路由树仅在客户端连接到端口 12053 时执行 routes { tag = "cccc", default = route_direct { child = "baz" } } ```
嵌套路由处理程序
路由处理程序可以接受另一个路由处理程序作为任意 child 类型条目。这允许你将复杂的行为从简单的路由处理程序中自由组合。
```toml pools { one = { backends = { "127.0.0.1:11214", "127.0.0.1:11215", } }, two = { backends = { "127.0.0.1:11216", } }, three = { backends = { "127.0.0.1:11217", } }, }
routes { map = { foo = route_split { child_a = "foo", child_b = route_allfastest { children = { "two", "three" } }, }, }, } ```
请求日志记录
可以在配置中选择性启用后端池请求结果的记录。然后通过连接并运行 `watch proxy` 查看日志。日志行只有在有连接正在读取它们时才会生成,但仍建议配置 rate 选项或其他约束。日志样式如下:`ts=time gid=num type=proxy_req elapsed=us type=num code=num status=num res=num cfd=fdnum be=host:port detail=tag req=get key`
```toml settings { backend_options = { log = { rate = 5, -- 随机记录每5个请求中的1个 errors = true, -- 记录所有错误 deadline = 250, -- 记录所有慢于 250ms 的结果 tag = "all" -- 日志的信息标签 } } }
pools { main = { -- 每个池的日志记录选项。 --[[backend_options = { -- 如果没有给出约束条件,记录所有内容(很慢!) log = { tag = "mainpool" } },--]] backends = { "127.0.0.1:11214", "127.0.0.1:11215", } } }
routes { default = route_direct { child = "main" } } ```
Gutter 故障转移处理宕机后端
这是一个减少宕机缓存服务器影响的示例。 例如,我们有一个包含三个缓存服务器 a, b, c 的池。 如果缓存节点 ‘b’ 失败,在 ‘b’ 服务器被替换之前,客户端将收到错误。 在此示例中,我们使用故障转移和 TTL 调整路由,允许在服务器故障期间临时重新路由缓存请求。我们首先通过“故障转移”请求从故障服务器转移到其他服务器,并提供多种可选方法。 接下来,如果请求已发生故障转移,我们将调整所有 ‘set’ 命令的 TTL 使其更低。在此示例中,我们使用五分钟。这防止了已“故障转移”的缓存条目在长时间内保留,如果服务器 ‘b’ 反复失败,这可能会引起问题。 较短的缓存时间应能为正在立即复用的对象(例如:用户在网站上浏览,或速率限制计数器)提供良好的命中率。
问答:
*我们需要将所有的 deletes 复制到 gutter 池吗?* 如果使用足够低的 TTL 且服务器通常不抖动(flap),则不需要。根据具体配置,可能需要这样做。
*那么 touch/gat 命令呢?* 这取决于你的需求。如有疑问请联系我们。
*如何处理抖动的后端(即有时超时但未完全死亡)?* 你可以调整“防抖动”设置,这将强制后端使用退避算法保持宕机状态:
```toml settings { backend_flap_time = 30, -- 稳定 30 秒意味着未抖动 backend_flap_backoff_ramp = 1.2, -- 退避等待时间的乘数 backend_flap_backoff_max = 3600, -- 至少每小时尝试一次 } ```
Gutter 示例配置:
```toml local be_list = { "127.0.0.1:11214", "127.0.0.1:11215", "127.0.0.1:11216", }
pools { main = { backends = be_list, }, -- 在某个示例中,我们使用专用的 gutter 池。除非其他服务器故障或服务中,否则该服务器将空闲。 gutter = { backends = { "127.1.0.0.1:11311" } }, -- 在此示例中,我们复用主要的后端集,但改变 key 哈希种子,使 key 映射到后端列表的方式不同。 -- 这可以最大程度减少服务器维护,同时避免空闲的 "gutter" 服务器。 -- 缺点是 key 可能会映射到相同的位置,特别是当你的后端列表很小时。 -- 可以通过使用具有不同种子的多个 gutter 并多次故障转移来部分缓解此问题。 -- 仍可能有无法故障转移的 key,但希望数量很少,服务可以坚持到缓存节点恢复。 -- -- 要使用此方法,将下方的 "gutter" 替换为 "gutter_same" gutter_same = { options = { seed = "failover" }, backends = be_list, }, }
routes { cmap = { set = route_failover { children = { "main", route_ttl { ttl = 300, child = "gutter" } }, stats = true, miss = false, -- 未命中时不进行故障转移,仅针对错误! -- 也不要 shuffle 池列表! }, -- 根据需要,对 add, cas, ms 重复此操作 }, -- 默认故障转移至 gutter 处理其余命令。 default = route_failover { children = { "main", "gutter" }, }, } ```
配置内置代理 运行内置代理