分享嘉宾:极验验证CTO 黄胜蓝
嘉宾简介:黄胜蓝 ,现任武汉极意网络科技有限公司CTO。高中时期NOIP一等奖保送至武汉大学,大学期间曾指导团队获得世界数学建模大赛金奖,同时负责武汉大学学生校园门户网站的运维工作。于2013年加入武汉极意网络科技有限公司,带领团队实现“行为式验证”安全模型,同时构建了高效、稳定的服务架构承载每天数十亿请求。对于技术发展有深刻见解,善于将适合的新技术融入公司技术架构中。
公司简介:武汉极意网络科技有限公司是全球首家“行为式验证”安全技术服务提供商,开创了验证安全从1.0时代到2.0时代的变革,并始终致力于为各大网站、应用、企业提供“更安全、更便捷、更具智慧的验证”服务及解决方案。
极意拥有业内领先的自主知识产权与技术研发实力,其首创的“行为式验证”安全技术,彻底颠覆了传统“码式验证”安全技术的思想,完成了14年以来验证安全领域的第一次飞跃——安全性提高44.78倍以上,平均用户验证时长仅不到以前的1/3,提高用户交互度达20%以上,全面支持移动终端的触屏验证体验。
极意拥有强大创新能力的核心团队,里面有第四届中国侨界贡献奖(创新团队)核心成员负责项目整体运营、有获得世界计算机性能大赛刷新世界纪录的雅虎黑客负责云服务器构架、有世界数学建模大赛冠军负责“多重行为判别算法”的研究。公司自成立以来,就受到国内外诸多投资机构的关注与投资,去年公司接受了来自IDG的数千万投资。目前我们的客户包括新浪博客、斗鱼、战旗、聚美优品、网金社等数万家网站,对于游戏领域更是实现了全行业覆盖。
以下是12月31日CTO讲堂现场完整速记:
主持人:今天讲堂现在开始,欢迎极验验证CTO黄胜蓝,麻烦给大家介绍下自己吧。
黄胜蓝:大家好,我叫黄胜蓝,目前担任武汉极意网络科技有限公司CTO,在公司主要负责带领团队构建高性能的服务架构和行为式安全模型。
看了我的照片应该会有些人想知道我的年龄。我确实是比之前的嘉宾都会年轻很多,其实我今年上半年才刚刚踏出武汉大学的大门^_^。高中时期我通过计算机竞赛一等奖保送到了武汉大学,这个经历对我而言很重要,有了当时对于数据结构和算法较为深刻的学习使得现在在接触实际工程中的一些概念时可以非常快速地了解其中的原理。大学大一大二在学校的自强网做运维工作,这段经历也让我受益匪浅,对于互联网相关技术也有了更多的了解。大二的暑假机缘巧合加入了极验验证团队。
主持人:请介绍一下目前极验验证的情况以及技术团队构成。
黄胜蓝:极验验证今年已经三岁了,目前我们的用户几乎遍布了互联网各个领域,每天处理的验证突破一亿次,每秒数万的并发对我们而言已经是常态。典型的客户包括新浪博客、斗鱼TV、战旗TV、熊猫TV、宝宝树、聚美优品、东方航空等。去年公司收到了来自IDG的数千万A轮投资,目前正在进行B轮,也是一线的投资机构。
比较有意思的有一次我到西电请了一些学生社团的负责人吃饭,十多个人中只有一个人没见到过我们的产品。
这些是我们典型客户的一个集中展示,分别是web端和移动端的。
团队方面,目前员工将近五十人,其中技术团队三十人多有,大部分都来自于武汉这边的几所高校,是一个非常非常年轻的团队。虽然团队在经验层面相对欠缺,不过目前从成果来看,不论是技术的深度还是广度都还算是拿得出手的。
主持人:介绍下极验验证如何兼顾安全性与用户体验?
黄胜蓝:极验验证与传统验证码对于验证技术的理解是有着本质上的区别的。传统验证码本质是人类可以理解图片的内容而计算机程序没有办法理解,这样的想法放在十年前或者五年前还算是靠谱,但是放在现在这样一个计算机程序都可以实现无人驾驶汽车的年代指望通过几张模糊不清的图就想难倒计算机程序实在是太天真了,同时传统验证对于正常用户的上网体验影响极大。而极验验证的“行为式验证“的概念,不再出一个难题作为门槛来限制用户,而是跟用户做一个小小的游戏,在游戏中通过行为来判断用户是正常用户还是恶意的程序请求。
我们根据收集到的海量行为数据构建了人类行为的边界,同时我们还动态实时地监控每个验证一段时间的全部验证行为,当这些行为的特征分布发生变化时我们的验证也会将分布异常集中的验证行为挡住。所以极验验证可以在比对手更加安全的同时对于用户也更加友好,实现安全与用户体验的双重提升。
这个图是某一次有个网站受到了恶意请求,我们将收集到的数据与正常人的数据从三个维度用tsne画出来图,很明显可以看出区别。正是因为极验验证在产品的用户体验和安全性上都完胜了传统的字符验证码,所以在市场上也出现了这样一个现象,一个行业中一旦有一家网站上线了我们的产品,马上就会有很多相同行业的网站主导找到我们接入产品,这也反映了我们的产品确实解决了验证码长期的痛点。
我们在后期也会继续提升技术实力,优化体验,为业界奉献更安全、更便捷、更智慧的验证。
主持人:技术架构是怎样的?用到了哪些技术呢?
黄胜蓝:简单明了的一张图,左半边是提供验证服务的集群,右半边是存储和分析日志的集群。用到的技术都是业界主流的方案,但是为了更加稳定高效承载数万的验证请求并发,我们在一些地方做了修改。
主持人:极验验证采用基于协程的并发方案以及独特的缓存方案,可高效稳定承载每天数十亿次请求,能详细介绍一下该方案么?
黄胜蓝:我们在不断优化优化服务性能的过程中有三个最大的敌人:
- 第一个就是并发本身所带来的开销即新开处理线程、关闭处理线程、多个处理线程时间片轮转所带来的开销。
实际上对于一些逻辑不那么复杂的场景来说这些开销甚至比真正的处理逻辑部分代码的开销更大。所以我们决定采用基于协程的并发方式,即服务进程只有一个(单cpu)所有的请求数据都由这个服务进程内部来维护,同时服务进程自行调度不同请求的处理顺序,这样避免了传统多线程并发方式新建、销毁以及系统调度处理线程的开销。基于这样的考虑我们选择了基于Tornado框架实现api服务的开发。Tornado的实现非常简洁明了,使用python的生成器作为协程,利用IOLoop实现了调度队列。
- 第二个问题是数据库的性能,这里说的数据库包括MongoDB和Redis,我这里分开讲。
先讲MongoDB的问题,MongoDB主要存储不同的用户对于验证的不同设置,比如该显示什么样的图片。
一开始每次验证请求都会查询MongoDB,当时我们的MongoDB是纯内存的,同时三台机器组成一个复制集,这样的组合大概能稳定承载八九千的qps,后来随着我们验证量越来越大,这个承载能力逐渐就成为了我们的瓶颈。
为了彻底搞定这个问题,我们提出了最极端的解决方案,干脆直接把数据库中的数据完全缓存到服务进程里定期批量更新,这样查询的开销将大大降低。但是因为我们用的是Python,由于GIL的存在,在8核服务器上会fork出来8个服务进程,进程之间不像线程那么方便,所以我们基于mmap自己写了一套伙伴算法构建了一个跨进程共享缓存。自从这套缓存上线之后,Mongodb的负载几乎变成了零。
说完了MongoDB再说Redis的问题,Redis代码简洁、数据结构丰富、性能强大,唯一的问题是作为一个单进程程序,终究性能是有上限的。
虽然今年Redis发布了官方的集群版本,但是经过我们的测试,认为这套分布式方案的故障恢复时间不够优秀并且运维成本较高。在Redis官方集群方案面世之前,开源世界有不少proxy方案,比如Twtter的TwemProxy和豌豆荚的Codis。这两种方案测试完之后给我们的感觉TwemProxy运维还是比较麻烦,Codis使用起来让人非常心旷神怡,无论是修改配置还是扩容都可以在配置页面上完成,并且性能也还算不错,但无奈当时Codis还有比较严重的BUG只能放弃之。
几乎尝试过各种方案之后,我们还是下决心自己实现一套分布式方案,目的是高度贴合我们的需求并且运维成本要低、扩容要方便、故障切换要快最重要的是数据冗余一定要做好。
基于上面的考虑,我们确定基于客户端的分布式方案,通过zookeeper来同步状态保证高可用。具体来说,我们修改Redis源码,使其向zookeeper注册,客户端由zookeeper上获取Redis服务器集群信息并根据统一的一致性哈希算法来计算数据应该存储在哪台Redis上,并在哈希环的下一台Redis上写入一份冗余数据,当读取原始数据失败时可以立即尝试读取冗余数据而不会造成服务中断。
- 第三个问题是Python语言的性能问题,这个后面说。
主持人:您带领团队构建了“行为式验证”安全模型,能谈一下在这个过程中遇到了哪些困难以及大致的经历吗?(包括团队管理、技术攻坚等方面)
黄胜蓝:从产品第一版DEMO开发出来到现在我们遇到了数不清的问题,现在回头看可以大致分为三个阶段。
- 第一个阶段是在主要解决性能问题,最早DEMO是用PHP和MYSQL写出来的,每次验证的临时数据也会写入MySQL,可以说整套服务也就只能小范围玩一玩了。随后的几个月时间,我们围绕着提升性能对整套服务不断进行优化,最后形成了用Python语言,Tornado作为框架,Redis存储验证临时数据,MongoDB作为数据库的架构。
- 第二个阶段是解决数据统计与分析的问题,搞定了服务的性能问题之后,用户慢慢多了起来,相应产生的日志也就越来越多。根据日志准确快速统计相关数据、实时监控行为分布以及试验安全模型所需要大量计算能力的问题又出现在我们面前。为了解决这样的问题,我们用建立起自己的运算集群,由Flume收集日志,Spark与Storm分别进行批处理与流处理,HDFS永久存储,Ceph临时存储,Mesos进行调度。
- 第三个阶段是我们对于数据与模型的理解,在提供验证服务的同时我们也在不断根据收集到的数据来更新我们的模型使得验证更加安全,破解更加困难。
而在这个过程中最大的困难在于我们对于我们对于模型与特征的理解。机器学习的算法做的都是一件事情即根据训练样本在特征空间中寻找一个分类面来分割空间,然后利用这个分类面预测新样本。不同的方法采用不同的数学模型来构建这个分类面,不同数学模型有着不同的表达能力,绘制出来的分类面形状和特性就会不同,而如何在选择合适的模型或者合适的模型组合训练准确、有泛化性分类器就需要对数据有着深入的理解。
团队的管理方面我们也在不断探索如何构建一套科学合理的考核评价体系,从而使得项目按时完成的同时保持团队的激情与探索欲望。这方面等会大家可以多多交流。
主持人:请结合实际情况,谈谈Python的多种形式优化。
黄胜蓝:Python这个语言确实有点让人又爱又恨,Python的语法、Python无比成熟的生态环境都是Python的优点。可以说对于一个互联网公司Python几乎可以满足所有的业务需求,从web到自动化运维工具再到数据分析和机器学习,Python都可以搞定。但是Python的问题也很明显,也就是它的性能问题。
好在现在Python世界也涌现出来了适用各种各样情况下的性能优化手段,我在这里结合我们遇到的实际情况简单介绍几个我们用到的。
- 使用C编写Python扩展或者使用Cython。这两种方式我们都有采用,也是业界比较常用的优化Python性能的方式。这里面主要说一下Cython,优化程序性能的本质实际上是在平衡程序员时间和机器运算时间的成本,而利用Cython则可以非常灵活地寻找这中间的平衡。Cython可以使用介于Python和C之间的语法,当语法更接近Python时获得的性能提升也就越少,而语法越接近于C时,性能也更加接近C。
- 使用pypy。这是一个支持jit的Python解释器,其官方测试结果比较好看,就我们实际测试结果来看它的性能优势不是很稳定,大部分项目是领先的但是有的项目又会莫名其妙的很慢。并且它对于C的扩展支持不佳。
- 使用Numba。对于数据分析、机器学习有过了解的人一定会听说过Numpy,Numba就是专门用来优化基于Numpy程序的工具。利用它可以只加入一行代码就将性能提升数倍,而缺点就是这种方式不能作为通用的优化手段,并且Numba虽然使用起来比较简单,但其依赖相对复杂,部署起来会有点麻烦。
主持人:数据分析方面,请您谈一谈如何利用gpu加速数据分析。
黄胜蓝:很多人可能会觉得gpu编程是一件很困难的事情,其实当真正接触了之后就会了解到让你的程序在gpu上运行其实并不难,真正的难点在于理解gpu的特性从而将最合适的任务交给gpu来做,同时采用合适的优化手段。
以我们为例,我们利用PyOpenCl将日志中用户的验证行为进行特征计算。计算流程中上下文的创建、任务队列的创建以及缓冲区的控制都通过Python来控制,kernel部分由C写。
这里面相对麻烦一点的是缓冲区的问题,因为cpu和gpu是两套独立的内存,数据要拷贝才能进行计算,这部分代码PyOpenCl封装的比较好,借用了NumPy的数据类型,操作起来会比用C写方便很多。
其中最核心部分是kernel,也就是将会运行在GPU上的代码,其实这部分代码的编写也不需要掌握什么特殊技能,我们的做法就是几乎移植了在CPU上的版本,只是在GPU上多条数据同时一起计算而已。
所以就像前面说的,找到合适的任务用gpu进行计算其实并不是一件很困难的事情。那么什么样的任务比较适合gpu上进行计算呢?我简单归纳一下就是任务逻辑相对简单(因为第一kernel要用C写,太复杂的逻辑写起来还是有点麻烦。第二优化和调试起来相对麻烦),重复性高的任务。比如排序、统计、查找、过滤、简单的预处理等等。
主持人:深度学习技术方案的选择方面,有哪些思考?
黄胜蓝:深度学习是目前机器学习领域最大的热门,也是互联网巨头们争相角逐的战场。对于中小企业而言,虽然可能没有实力聘请顶尖的研发人员、没有能力获取顶尖的运算能力但是这并不意味着一定会无缘深度学习所带来的变革。
目前开源的深度学习框架非常多,利用这些开源的深度学习库可以非常方便的构建一个神经网络并进行实验。
Python也为我们提供了探索深度学习世界非常有用的工具,我们使用了两个东西,一个是Theano,另一个叫做Kares。
Theano是一个数学表达式编译器,对于普通程序员来说可能会对这个概念很奇怪,实际上很简单,它可以把一系列数学表达式以及相应的符号链接编译成可执行代码,而这个可执行代码还不仅仅是cpu,它同样可以编译出gpu可执行代码。所以基于这样的工具,我们就可以实现从数学表达式自动编译成gpu上的可执行代码,是不是很爽!
再来看Kares,它是一个深度学习库,它将大牛们提出的各种网络结构、激活函数、Cost Function、以及各种Trick做了统一的整理和封装,可以用及其简单的方式将各种方法组合成为一个神经网络进行实验,这个库的底层是基于Theano的,也就是利用Theano将表达式编译成了gpu代码,所以当你真正想去做深度学习的实验时你就会发现用这些工具其实可以非常非常快就构建一个实验项目。
当然,不是有了这些工具就意味着探索深度学习的道路会一帆风顺。理论方面,不仅要透彻了解神经网络背后的数学模型,更要紧跟业界动态,不断学习最新的理论与技巧;实践方面,训练出一个优秀的网络往往需要大量的试验,尝试不同的网络结构、trick与超参数,复杂的网络往往需要更大量的数据来反向传播更新权值,这些意味着对于运算能力、数据存储能力都是极大的考验。
探索深度学习的前提是一定要有一支高水平、全方面的团队!
主持人:如今互联网时代给各行各业带来了巨大的变革,同时也加剧了行业从业者浮躁的心态,该如何沉下心来做事,并不断提升技术能力?
黄胜蓝:的确,这两年行情比较火爆,行业对于技术人员的需求持续高涨,待遇也是水涨船高。带来的结果就是很多技术人员在这样环境下变得浮躁起来,不再深究代码的优化、常常把新技术挂在嘴边却不甚了解、哪些技术待遇高就学什么技术等等。
我认为作为技术人员一定要在互联网浪潮中保持危机感和广阔的技术视野。危机感可以督促自己不迷失在眼前取得的成绩而是继续努力力争上游。广阔的技术视野可以让你更加清楚认识到业界遇到了哪些问题,又是开发了哪些项目提出了哪些方法来解决这些问题的。看清楚了业界发展的方向就可以避免在提升技术能力的道路上走弯路。
主持人:请结合你的切身体会谈谈创业路上您都有哪些收获和思考,对于如今越来越多想要投身创业大海的年轻人,有什么建议?
黄胜蓝:创业是九死一生的事情,首先也确定是否有能力承受可能的失败,这个是最大的前提。第二就是选好方向,创业做一件事情的时候一定要保证你是这行里面对这个行业了解最深的,否则做出来的东西一定没什么意义。
主持人:推荐一些觉得非常不错的资料或者书籍吧。
黄胜蓝:推荐一些比较基础的吧学习Python建议可以看看《Python核心编程》这本书,讲的比较细致。有兴趣了解深度学习的话可以看看UFLDL,很经典的一个教程 http://ufldl.stanford.edu/wiki/index.php/UFLDL_Tutorial