hi 春哥,all: 最近在做敏感词过滤,匹配算法用的是 jgrahamc 的 ac 实现 https://github.com/jgrahamc/aho-corasick-lua(此君也是 cloudflare 的,哈哈) 有个敏感词库动态更新的问题 由于敏感词比较多,ac 算法在生成 自动机 的时候耗时比较多(上秒)了,现在是把生成的 自动机 缓存在module里 为了不影响正常过滤,当敏感词库变动的时候,也不能直接 -s reload 来更新(重建自动机耗时太多) 现在我是这么设想的: 1. 在 ac 算法中 生成自动机的过程中插入了 ngx.sleep(0.001) ,将大计算切分了,这样是可以将大计算切分了,更新 自动机的时候也同时处理新来的请求 2. 提供更新module里缓存的自动机的接口,当关键词库变动时,循环调用接口确保每个worker都能更新,接口根据提供的词库版本号来确定是否需要更新 (貌似请求的时候不能指定worker进程哦) 初步实验是可以满足需求的,请教各位这么做是否有问题,或者推荐更好的方式,多谢~ --
Hello! 2013/8/29 Lance: > 怎么保证循环通知到每个worker呢?我之前做的一个需要类似更新缓存的东西,是在每个请求启动时访问DICT里一个变量比较本地module缓存的版本来判断是否需要更新。 > 对的,应该让各个 nginx worker 自己主动检查版本号来进行更新。 -agentzh
Hello! 2013/8/29 朱德江: > 由于敏感词比较多,ac 算法在生成 自动机 的时候耗时比较多(上秒)了,现在是把生成的 自动机 缓存在module里 > 我觉得这个问题应该使 ac 算法生成的自动机可以序列化成 JSON 或者 Lua 代码等形式。这样自动机的生成过程可以离线进行,然后线上只需直接加载事先生成好的状态机数据或者代码就可以了。 Regards, -agentzh
怎么保证循环通知到每个worker呢?我之前做的一个需要类似更新缓存的东西,是在每个请求启动时访问DICT里一个变量比较本地module缓存的版本来判断是否需要更新。Lance 2013/8/30 朱德江 <douj...@gmail.com> hi 春哥,all: 最近在做敏感词过滤,匹配算法用的是 jgrahamc 的 ac 实现 https://github.com/jgrahamc/aho-corasick-lua(此君也是 cloudflare 的,哈哈) 有个敏感词库动态更新的问题 由于敏感词比较多,ac 算法在生成 自动机 的时候耗时比较多(上秒)了,现在是把生成的 自动机 缓存在module里 为了不影响正常过滤,当敏感词库变动的时候,也不能直接 -s reload 来更新(重建自动机耗时太多) 现在我是这么设想的: 1. 在 ac 算法中 生成自动机的过程中插入了 ngx.sleep(0.001) ,将大计算切分了,这样是可以将大计算切分了,更新 自动机的时候也同时处理新来的请求 2. 提供更新module里缓存的自动机的接口,当关键词库变动时,循环调用接口确保每个worker都能更新,接口根据提供的词库版本号来确定是否需要更新 (貌似请求的时候不能指定worker进程哦) 初步实验是可以满足需求的,请教各位这么做是否有问题,或者推荐更好的方式,多谢~ -- class="HOEnZb"> --
hi 春哥,all: 最近在做敏感词过滤,匹配算法用的是 jgrahamc 的 ac 实现 https://github.com/jgrahamc/aho-corasick-lua(此君也是 cloudflare 的,哈哈) 有个敏感词库动态更新的问题 由于敏感词比较多,ac 算法在生成 自动机 的时候耗时比较多(上秒)了,现在是把生成的 自动机 缓存在module里 为了不影响正常过滤,当敏感词库变动的时候,也不能直接 -s reload 来更新(重建自动机耗时太多) 现在我是这么设想的: 1. 在 ac 算法中 生成自动机的过程中插入了 ngx.sleep(0.001) ,将大计算切分了,这样是可以将大计算切分了,更新 自动机的时候也同时处理新来的请求 2. 提供更新module里缓存的自动机的接口,当关键词库变动时,循环调用接口确保每个worker都能更新,接口根据提供的词库版本号来确定是否需要更新 (貌似请求的时候不能指定worker进程哦) 初步实验是可以满足需求的,请教各位这么做是否有问题,或者推荐更好的方式,多谢~ -- class="HOEnZb">
Hello! 2013/8/29 朱德江: > 由于敏感词比较多,ac 算法在生成 自动机 的时候耗时比较多(上秒)了,现在是把生成的 自动机 缓存在module里 > 我觉得这个问题应该使 ac 算法生成的自动机可以序列化成 JSON 或者 Lua 代码等形式。这样自动机的生成过程可以离线进行,然后线上只需直接加载事先生成好的状态机数据或者代码就可以了。 Regards, -agentzh --
Hello! 2013/8/30 朱德江: > 我设想的是统计更新接口返回成功的数量,达到worker数了,就不循环请求了 > 不过这样确实是要提前直到每台机器开启的worker数了 > 这种做法不靠谱,因为 worker 调度并不是轮询,所以需要较大的并发压力才能保证每个 worker 都被调度到,而这无疑是很大的资源浪费,同时行为不可控。 > 我尝试了一下 json 串,生成之后有 几十M,cjson.decode 这个大的串耗时 > 也上秒了,lua 代码应该好很多,回头试试 cjson 的解码效率不算高,建议换用戴冠兰的 lua-cmspack 库的 fork 来进行序列化: https://github.com/guanlan/lua-cmsgpack 我记得这个库的解码效率比 cjson 高很多。 Best regards, -agentzh
Hello! 2013/8/30 朱德江: > 我设想的是统计更新接口返回成功的数量,达到worker数了,就不循环请求了 > 不过这样确实是要提前直到每台机器开启的worker数了 > 这种做法不靠谱,因为 worker 调度并不是轮询,所以需要较大的并发压力才能保证每个 worker 都被调度到,而这无疑是很大的资源浪费,同时行为不可控。 > 我尝试了一下 json 串,生成之后有 几十M,cjson.decode 这个大的串耗时 > 也上秒了,lua 代码应该好很多,回头试试 cjson 的解码效率不算高,建议换用戴冠兰的 lua-cmspack 库的 fork 来进行序列化: https://github.com/guanlan/lua-cmsgpack 我记得这个库的解码效率比 cjson 高很多。 Best regards, -agentzh --