openresty2018大会感想

2018.11.23,我有幸作为演讲嘉宾参加了openresty2018年的大会,前前后后我听了一天半的时间,感觉非常棒,感谢各位讲师带来的满满的干货。想着写一篇博客来记住和沉淀这次分享大会。

早上6点从苏州驱车赶往杭州滨江区的网易大厦,好在时间早,路上路况非常不错,在8点30分的时候准时签到,还无耻的蹭了一顿网易的免费早餐,真是不错哦。


又拍云的or服务实践

一般开场第一讲是最难的,讲师刚上台难免有点紧张,不过随着干货一阵阵抛出之后,讲师也渐入佳境了。又拍云开源了一些or的项目,都放在了github上,丢在upyun/upyun-resty这个项目里,然后介绍了一些了性能分析工具,列举了:perf,systemtap,bcc/ebpf,flamegraph等工具。为了方便线上调试,还把一些常用的调试分析软件和环境打在docker镜像里面,方便直接运行:

1
2
3
4
5
6
docker run --it --rm --privileged \
-v /lib/modules:/lib/modules:ro \
-v /etc/localtime:/etc/localtime:ro \
-v /usr/src:/usr/src:ro \
--net=host \
--pid=host upyun_stap:last

讲师又分享了日常使用or的几个小技巧和注意点,比如尽量使用小写字母作为key去查询请求头,这样可以减少一次字母大小写的转换;另外避免使用全局变量,避免使用低效的字符串拼接;避免过多的table重定义大小,比如疯狂往table里push数据,让table一直处于resize状态;尽量使用lua-resty-core里的函数来编写代码;使用能够被JIT的功能;使用ffi来调用c语言的函数。

然后作者就对一些坑点开始分享,Nginx对于在upstream上的域名的dns解析只会进行一次,所以当域名解析变更之后,就会有问题了。然后又拍云涌lua-resty-domain模块来自由的做域名解析,这样可以兜底和做负载均衡。

最后讲师讲述了在使用or和ssl硬件加速卡碰到的坑,就是使用了ssl硬件加速卡后,luajit代码就有问题了,这个问题困扰了讲师很久,最终通过修改Nginx源码解决了。还贴出了ssl硬件加速卡对于tls性能的帮助,能提升不少吞吐率。

or在腾讯广告系统的运用

讲师来自腾讯广告部门,长的和动作明星甄子丹真的很像,不知道他是不是日常的绰号就是甄子丹,开个玩笑。主要介绍了or在广告系统的运用,他们部门大量使用了c/c++,所以用or结合原来的业务得心应手。讲师很熟练也很有演讲的技巧和经验,一看就是老鸟了,讲了一些广告行业的入门技术知识,也讲了一些他们的性能优化点。

  1. 使用hyperscan替换原来的pcre做正则处理,性能比之前要快3倍,hyperscan这个库性能非常出色,一般的正则任务,当大量产生大量调用的时候,可以考虑用它来替换pcre。
  2. 使用他们自主研发的json库来代替cjson库,来对json进行解析,但是提升个人感觉不大,对于我们日常使用cjson性能绰绰有余了
  3. 他们有一个需求,对于数10亿的key,网关层需要做是否存在的初筛,过滤一部分无效的key的请求,大概能过滤80%,但是10亿多的key如果直接存储在分布式kv系统后,每次查找的性能开销比较大,于是他们使用cityhash算法,把10亿多个key经过hash生成256位散列值,从而做一个初筛的操作,这个也值得学习,相似的算法还有:MurmurHash算法。比如,我们只想对一个长字符串进行hash,可以容忍一部分冲突,同时也没有不可逆转的需求,那么用这种MurmurHash,或者cityhash会比较合适。

春哥的or新特性展望

春哥把录好的视频播放给大家,作为分享了。主要讲述了or将来的发展方向,重点介绍了stream模块,它和http模块是姊妹模块,以后大家估计会和这个模块打交道比较多,目前保证了stream模块和http模块api的统一化。想要自己掌控http2.0协议,就需要stream模块了,还有udp协议等等,总之加上了这个模块之后,or可以有更多的功能了。

春哥还建议,各种开源项目的连接库,大家各个语言都实现一遍,每次升级版本,各个语言就各自升级,这个事情很蛋疼。他提出,只要用一种中间的描述协议的语言,来描述好协议,然后通过这种描述协议语言,自动生成各种语言的类库,这样这些开源项目的sdk的维护就会变得很简单。思路很先进,但是目前似乎还难实现,就靠春哥牵头了。

玩转Nginx监控

下午第一场是阿里巴巴公司的Tegine研发团队的分享,他们把对Nginx的监控和性能挖掘,我感觉做到了极致的细,包括一些我可能根本想不到的性能监控点。但是这样带来的后果就是,Tegine是爆改的Nginx分支代码,可能再也没有机会跟着社区版本升级,使用新功能了。

这也是国内做开源项目的通病,拿到开源项目,看完源码,觉得不符合自己需求,就fork一个版本,爆改一顿代码上线。经过几个迭代之后,发现自己手上的版本,已经远远落后社区版了,合并代码是及其困难的,于是干脆放弃了。记得之前来我司交流的ebay公司和qcon上听网易做云的,他们都用k8s来管理私有云,这个本没有问题,但是因为k8s的一些功能无法满足他们,于是他们就爆改k8s代码,结果导致,每次k8s升级,要么官方实现了他们的需求,要么就是想要的新功能无法快速合并回现有使用k8s集群。于是两者每次k8s升级,都需要花费1个月左右的时间,来合并代码,这样是极其不正确的开源贡献方式。

讲师团队对于Nginx玩转的非常深入,对于我这个平时已经满足or高性能的普通用户来说,大开眼界,敬佩他们对于Nginx性能的剖析,做的这样细致。

or服务架构实践

下午第二场是kong公司的工程师做的分享,主要讲述了如何利用or,kong来为企业做服务网关的实践。他们有一个例子做的很学院派,所有ssl证书,他们都是通过vault来存储的,避免明文存储这些证书,同时利用consul来做事件推送和订阅。

然后介绍了terraform描述语言,用这个描述语言,可以在各个云厂商之间快速的部署基础设施,所以就有了infrastructure as code

讲师演讲的非常自然,肯定是老司机了,个人感觉是我听的本次or大会分享里,台上感觉最好的。

快速分享

下午穿插着一节快速分享的内容,讲师主要讲述了如何用一个描述行语言,来自动生成代码,举的例子大概就是,通过一个描述语言,自动生成了一个restful的对数据库crud操作的代码。对于实际业务场景来说,感觉帮助不大,但是如果能够用一门语言来描述和生成其他任意语言代码,那这门语言肯定巨牛逼,将一统江湖。

同程艺龙or实战

下午第三场,是我做的同程艺龙的or实战,主要介绍了公司各个有趣的or项目,最后还加了点代码,不然不像干货。总体来说,讲的中规中矩吧,把PPT里的内容,完整的分享给里大家。

kong做微服务网关

第一天最后一个讲师,分享里or在各个领域的实践。从网关到waf,从授权到限流等等,大而全的介绍了一些or常用的场景和适合的场景,让大伙系统的对or的使用场景有了一个概念。

讲师有一句话,挺有意思,就算你很能写代码,但是也要按耐住写代码的冲动,先去开源社区看一下,是否有符合我们需求的开源组件已经实现了,说白了就是避免重复造轮子。这句话我部分赞同,当你只是为了完成功能而去造轮子,我觉得没有意义,但是当你真当觉得,原来的轮子不满足你的需求,真想去再造轮子的时候,还是大胆的去造吧,毕竟轮子就是这么进步的。

or的cache

第二天,第一个讲师是美国人,凭借着我三脚猫的英文努力的听着,靠猜,靠看,基本了解了讲师的意图。讲师主要介绍了如何在工程上利用or的缓存,通过lua-resty-worker-eventsngx_lua_ipc这两个包来进行进程间的通信。然后介绍了他们开源的一个or的缓存管理组件lua-resty-mlcache,这个包分三级缓存,L1,L2,L3,其中L1缓存是lua内存缓存,L2缓存是sharedict缓存,而L3缓存,则是用户自定义的外部缓存存储,例如:redis,mysql等。

总体缓存的设计思路和我当时做or项目是一致的,都是这样来划分三级缓存的。唯一的难点就进程间通讯,多个worker之间如何通知通信。

or的性能调优

接着,讲课的是or公司的一个小孩,别看是小孩,牛逼的很,中间直接上汇编指令跟我们讲述JIT如果做到性能优化的,ffi为什么性能好的原因。春哥公司招聘的都是奇才,不得不佩服。他的分享,也是我手机上拍照ppt最多的一个。

  • nginx -t/ nginx -s 都会去重新执行一次init_by_lua阶段的代码
  • 详细对比来os.time, ngx.now(), ngx.update()+ngx.now(), current_ms_time(),这几个之间的性能差距和区别。总结一下,就是能接受缓存的,性能同时也是最好的,就是ngx.now(),准确的时间戳,又要快的,用current_ms_time()
  • current_ms_time代码如下:
1
2
3
4
5
6
7
local function current_ms_time()
local rc = ffi.C.gettimeofday(tv[0], nil)
if rc ~= 0 then
error(errno())
end
return tonumber(tv[0].tv_sec) + tonumber(tv[0].tv_usec)/1e6
end
  • ngx.timer受限于三个参数,worker=connections,lua_max_pending_timers, lua_max_running_timers,保证他们都足够大,
  • 如果想跑定时任务,开源使用ngx.timer.every来执行
  • string是不可变的,减少string的直接加减和使用,可以使用table来做引用传递,减少开销。使用table.concat和stirng.format来减少string的创建,用string.byte来代替string.sub。
  • table中应该避免存储nil,nil会对#table取长度,unpack, ipairs产生不良影响,要想表达nil值,应该用ngx.null来代替。
  • 尽量使用resty.core的方法和功能来写代码,所以得出的结论就是,无脑加:
1
require "resty.core"

最后,讲师讲述了JIT优化的相关内容了,JIT的Tracing过程dump到文件中,如下代码:

1
2
local dump = require "jit.dump"
dump.on("abimstx", filepath)

ffi可以有效的减少lua到c的数据序列化时间,如果调用c到借口,尽量使用ffi来做。比如ffi对ngx.time的优化帮助就很大,因为c代码很快返回,实践都消耗在lua和c的数据格式序列化上,所以使用ffi就可以得到很好的效果。

接下来的内容都是会后看视频的

7层流量Tengine硬件加速

阿里的一个讲师分享的,主要介绍了他们使用QAT加速卡,不仅仅加速了ssl,还加速了gzip,让Tengine的性能,整体提升了20%左右,当然中间踩了不少坑,通过各种优化,分析system的cpu执行,来找问题,分享还是非常精彩的。

企业网关应用

讲师是硅谷留洋归来,果然眼界很宽,做的后台系统很高大上,主要用openresty做了一个rbac的openapi服务,有签名,授权,限流等功能,还有详细的日志记录和查询。

脑洞很大,还把or安装在路由器内,通过nchan来做多播组播,nchan性能非常好,但是内存存储,所以网游服务器,聊天室这种场景非常受欢迎。

好像是,讲师还介绍了lua-resty-execlua-resty-shell,这2个非阻塞的执行shell命令的包。

cc攻击防护

后来看了网上的视频,回播看了关于cc攻击的防护,讲师大部分思路都是基于waf来做的,然后会配合前端js的sdk来一起做cc防护,演讲的不错,整体思路也很好。最后介绍了2个工具,我记下来了,据说分分钟打垮小网站,最后的福利啊。

总结

听完性能调优,我就去西湖那边拿东西了,总体感觉这类单方向的分享大会的干货,要远远高于类似qcon这种大而全的会议,可能档次,环境不如qcon,但是,我通过or这次分享大会确实学习了不少东西,收获满满,期待下次再相聚了。