单位绝大部分服务语言为Java,使用的是过去很长一段时间非常流行的SSM框架:spring+springmvc/springboot+mybatis。众所周知,这些框架经过了无数次、高强度的验证,证实具有高稳定性、高规范性、高敏捷性。也正因此,现在非常多的公司都在采用这一技术架构。
虽然SSM框架有着如此多的优点,在特定场景下,其还是存在一定的不足之处,而恰巧机器学习中的一些领域就对应这些特定场景。由于python语言的简单、易学,其在机器学习领域的日常开发中被广泛使用。因此自机器学习发展至今,绝大多少机器学习工具包都为python实现。而我们算法团队这边为了方便日常开发,试图使用python作为我们的开发语言。因此,对于技术选型,就显得尤为重要了。
目前头条、豆瓣、迅雷等很多公司都在使用flask+uwsgi这一架构。Flask是一个比较轻量级的web service,上手简单,但是功能相对较少,其将很多网络请求工作交给了uWSGI服务器。
其缺点比较明显:异步能力不足,处理能力有限。当请求量过大的时候,可能响应不及时。Flask在版本迭代过程中使用过两种模型:poll、select。
目前包括百度、facebook等一些大公司都在使用tornado这一框架。相对flask来讲,tornado还是比较重量级的,内部实现了服务器功能。通过eventLoop机制,其使用epoll模型实现了事件池、tcp server、http server。基于此,tornado异步性能相对更好。
而NLP服务综合考虑响应耗时、请求量,我们最终选择了tornado服务作为我们的web service。
Pigeon:
单位目前使用的点评的rpc框架pigeon,Pigeon实现了请求的均衡、端开重连,功能全面。
但是pigeon并没有python的客户端,因此无法使用pigeon作为我们的rpc选型。
Grpc:
从中间件团队了解到有使用golang+grpc+protobuffer的同事。
Grpc为google开源的rpc框架,目前使用量较大,比较安全可靠。Proto3也是目前比较流行的序列化方法。考虑到各部门同事沟通的顺畅,我们选择了grpc作为我们的rpc框架。
1)rabbitMQ
优点:Erlang语言开发,server端逻辑细节比较难以掌握。但是目前比较稳定,使用量也还可以。
缺点:遇到问题不好迅速定位问题,历史数据保留不够完善;安全性和kafka、rocketMQ相比略显不足,可能出现丢数据的问题。
由于可能出现丢数据的现象,最终我们选择放弃rabbitMQ,考虑其他方案。
2)Kafka
优点:Kafka实现优美,架构完善,可以最大程度保证数据不丢失。因此没有任何理由不使用kafka作为我们方案之一。
3)RocketMQ
优点:
Rocketmq为阿里开源,java语言开发,比较方便java系程序员定位异常。
其内部实现类似kafka,包括nameserver、broker、producerGroup、consumerGroup。
对于异常处理,具有重试队列和死信队列。
其心跳机制为自己实现的简易心跳监测功能,相对zk更加轻量级。
而consumer中的pull和push方式使得使用方式更加多样。
缺点:
RocketMQ由于实现了诸多功能,很大程度上类似于kafka的封装,因此在保证性能的同时,可能使其响应时间略慢。不过对于我们工具类型的产品,安全相对差异并不太大的响应时间来看,我们更需要考虑安全性。
因此综上考虑,我们认为rocketMQ可以作为我们的方案之一。
Mysql为当前使用较为广泛的数据库,其作为我们单位的数据库选型之一,单位对其进行了进一步的封装,包括MHA迁移、读写分离等。因此我们使用python语言进行了一次类似封装,保证了我们可以使用单位封装包。
1)open-falcon是一套比较完善的架构体系,从接口到界面到存储,但是界面和存储性能较差。其存储使用的是rrd。
2)Prometheus作为存储工具类似tsdb,但是集群效果较差。
3)Grafana作为监控工具,数据源可以采用tsdb或者Prometheus。Tsdb集群效果较好。
之前考虑的是使用sentry作为告警工具,但是精力有限,没有足够的人力进行维护,因此考虑更加简便的钉钉告警,这样方便大家即使发现服务中存在的问题。
1)Python服务的log指向指定地址。
2)Kibana通过filebeat监测log文件更新,增量到Kibana。Grafana读取kibana的数据并展示出来。
①转发:内外网服务对本python服务都有网络请求,因此运维同事帮忙配置了线上环境内外网nginx转发配置。
②网关:服务对外开放,因此需要保证接口的安全性。单位特提供eureka保护内部接口的安全。所以对外接口需要接入eureka,这样当外部服务请求进来时,nginx判断属于自己转发范围,则会讲配置了eureka的接口转发到eureka,eureka判断location是否注册,如果注册,则准许请求进入;否则请求打回。
③请求预处理:
1)SSO:单位内部网站登陆的时候需要考虑单点登陆问题,因此加入了**_passport等单点校验参数。对于需要登陆获取cookie的网站,我们需要在预处理阶段,针对改参数判断是否已在其他地点登陆;此外还需要校验用户身份信息。
2)CORS:由于和前端系统不在同一个域名下,因此需要设置跨域。
3)日志:由于需要统计qps等数据,因此需要在请求进入服务的时候需要统计请求信息。
4)异常:对于所有的异常,我们采用钉钉告警的形式通知开发人员。
由于现有机器学习工具包在某些场景下并不适用,因此需要进行部分源码进行耗时优化。
优点:部署系统可以一键式实现批量发布,自动重启。有效规避手动发布过程中的误操作。
缺点:系统工作原理为从物理机划分虚拟机,无法做到资源隔离。
由于需要和中间件的同事、运维同事沟通日志采集实现方式,中间存在诸多沟通不畅的问题导致花费很长时间没能实现日志的收集。
由于不清楚中间件同事lion实现方式,导致服务在被请求过程中实时处理lion的请求,后来发现lion所在机器性能有限,所幸请求量不是太大,没有造成过大影响,后来将lion实时请求部分改为启动请求。
由于代码bug,导致弹性云部署实现后,服务持续性重启。后经和运维同事沟通,解决持续重启的问题。
整个服务从零搭建花费1个月,后期实现各种中间件的结合、和运维、中间件同事沟通发布细节问题又花费了1月余。最后成功上线、实现弹性云发布,收获颇多。