天天看点

移动云平台的基础架构之旅(二):云代码

云代码的由来

随着MBaaS的发展,取代移动企业应用程序平台的趋势也越来越明显。MBaaS系统为了让企业能方便快捷的开发自己移动应用程序,提供了诸多移动客户端支持,有最通用的REST API,也有方便移动开发者的软件开发工具包,还有一定程度的监控和分析服务提供。而对于相对比较复杂的应用程序,开发者有时不想也不必在移动设备上运行很复杂或很费时或无法实现的业务逻辑,这种需求催生了云代码的产生。

移动云平台的基础架构之旅(二):云代码

云代码的愿景

想象一下,如果你想要少量结果信息,但却必须要向设备发送大量对象列表,或者调用大量REST API才能完成此项工作时(比如统计汇总操作),这种操作显然会消耗你大量的带宽和用户流量。

想象一下,如果你想要设备周期性定时完成某个任务或者想在后台一直运行某个任务(比如资源回收垃圾清理),这种操作显然很不可靠,一方面用户可能会随时关闭设备上的应用,另一方面在后台一直运行某个任务显然也会耗费用户设备电量等资源,得不偿失。

想象一下,当你需要调用第三方平台API时需要对方回调时比如完成某个支付操作,服务提供商在支付成功后执行回调,你需要根据回调结果完成后续操作比如同步记录到数据库中,这种操作在移动应用在没有自己的后端服务器时也很难完成。

想象一下,你的某个App应用有iOS,Android,JavaScript等多个设备平台版本,当你新增一项功能,同一套业务逻辑需要在所有平台做同步开发,当你修改一项功能,同样需要在所有设备平台做新版本发布更新操作,如果产品迭代很迅速那这种频繁的操作显然会大大增加移动开发的成本和效率,但效果却可能不见得很好。

想象一下,当某个用户注册了你的应用,你需要对该用户增加一些信息来用于统计,或者用户购买了应用里的某个商品,你需要收集除订单外额外的信息,这类在用户触发某些特定操作时会自动额外产生的逻辑(Hook操作),这些Hook操作并不适用在移动端编写。

伴随移动开发,类似上面的情况多有发生,此时MBaaS系统提供的云代码功能就是为移动应用量身定做的解决类似上面问题的方案,云代码的愿景就是方便移动开发者彻底摆脱服务器,随心所欲的开发各种移动应用程序。

MaxLeap作为一款优秀的MBaaS平台系统,其云代码的功能如何,是如何实现的,又有哪些加分项,接下来将为大家一一揭晓。

MaxLeap云代码的功能

有了云代码的背景愿景,那云代码需要提供的基础功能就很显然了

  • 首先得提供基础服务和框架,方便用户开发云代码
  • 其次得提供代码托管,能很方便的让用户快速部署代码到云端运行
  • 最后提供日志和相关监控工具,能对线上代码的错误及性能特征有更多了解,以便优化自己的程序

MaxLeap云代码的实现

1、让开发者如何开发云代码

如何提供基础服务和框架来方便用户开发?由于用户的开发环境和擅长的开发语言各种各样,比如使用Java,使用NodeJs,使用Python,使用JavaScript的等等,我们提供对应的各个开发语言的基础云代码SDK,丰富用户的选择,降低用户开发门槛和成本,这样云代码在CloudCode SDK基础上开发就会非常便捷,这些CloudCode SDK和MBaaS对外提供的移动SDK不同的地方在于它并不在移动设备上运行,而是在云端运行。也就是说开发者先要选择自己喜欢的云代码SDK,比如我很擅长JAVA,所以我会选择cloud-code-java-sdk来开发我的云代码,同时云代码SDK还要提供本地开发测试框架,总不能让用户线上开发调试吧,本地开发本地调试完成后再部署到云端。当然为了开发者更快的开始,MaxLeap同时提供了Demo和Quick-Start项目来让开发者更快接触云代码。

2、云代码如何为用户提供服务

开发者在使用云代码部署到云端后该如何访问云代码?MaxLeap的云代码是通过基础的REST API来访问,云代码SDK负责提供Http服务对外暴露REST API,因为基于Http可以很好的兼容不同开发语言,实现跨平台访问,当然这些API不会直接暴露在用户面前,用户只有通过调用MBaaS的云代码服务API才能间接访问。

移动云平台的基础架构之旅(二):云代码

3、云代码能为用户提供哪些服务

不同开发语言的基础云代码SDK其实都具有相同的功能,最重要的是数据存储服务,CloudCode SDK通过封装一系列REST API来让开发者很便捷的访问基础MBaaS服务。除此之外还要提供云函数、后台任务、Hook操作、消息推送、日志、安全访问、分布式计数器、分布式锁等功能。

移动云平台的基础架构之旅(二):云代码
  • 数据存储服务

通过SDK可以很方便的使用MaxLeap的存储服务,例如对象的CRUD操作,同时集成了手机行业主流的金币系统。

  • 云函数

运行在MaxLeap云端的函数,定义好云函数后可以通过REST API方式来访问,这个API是同步的。同时云函数提供白名单功能(通过界面设置),方便被其他第三方网络服务调用。

  • 后台任务

同样是运行在MaxLeap云端的函数,对于长期运行的任务而言,后台任务非常有用,例如与响应时间较长的外部网站集成或分批发送推送通知。如果您在运行云函数时经常遇到超时错误,则可以考虑使用后台任务,同时当您部署云代码后,可通过后台界面进行计划任务,你可以计划一次性任务或者周期性任务,这不但可以方便管理你的后台任务,同时也能清楚的追踪你的任务状态。

  • Hook操作

Hook用于在对 Cloud Data 进行任何操作时(包括新建,删除及修改)执行特定的操作。例如,我们在用户注册成功之前,可以通过beforeCreate Hook,来检查其是否重名。也可以在其注册成功之后,通过afterCreate Hook,向其发送一条欢迎信息。Hook能很好地实现与数据操作相关的业务逻辑,它的优势在于,所有的业务在云端实现,而且被不同的应用/平台共享。

  • 消息推送

在移动应用中,为每个客户端用户推送系统消息或定制消息必不可少,通过该功能开发者可以很便捷的将消息推送到所有或指定设备上。

  • 分布式计数器/锁

云代码在云端是一个分布式应用,提供计数器、锁相关的功能以便多个实例之间可以共享同一份数据。

  • 日志

提供Logging功能,以便您能记录Function,Hook或者Job在运行过程中出现的信息。

  • 命令行工具

可以方便用户云代码项目的上传,部署,停止及版本管理。

4、云代码该如何管理

云代码作为在云端部署的代码,MaxLeap是如何管理它们的呢?在这项重中之重方面我们可能会遇到下面这些问题:

  • 每个开发者的环境不同,操作系统也不相同,如何降低搭建各种环境的成本以及降低对操作系统的依赖、降低硬件要求和应用环境之间耦合度同时降低虚拟化消耗?
  • 管理的应用可能成千上万,但是服务器资源就那么多,该如何对每个应用实现虚拟化来整合应用和服务器降低成本?
  • 每个应用的重要程度也不同,有重度用户需要高可用高性能的服务,有低度用户可能一天也不会有几个请求,资源该如何分配?
  • 用户的代码部署在云端,如何保证用户的应用代码安全?
  • 用户代码服务如何做到高可用,出现故障该如何转移,如何做到服务不间断,新发布的代码出现异常该如何回滚?

基于上面遇到的问题,我们把用户的云代码作为一个松耦合的单个服务,也就是现在流行的微服务架构,通过docker来实现对微服务容器化,因为docker本身就是源于Paas,在MBaaS系统也非常适用,我们不用为每个云代码应用开启一个虚拟机来降低硬件要求和应用环境之间的耦合度,这能大大降低虚拟化消耗,降低成本,而且docker还能为应用提供一个从开发到部署上线都一致的环境,非常便于管理代码的流水线,让我们可以对云代码从开发到发布部署简单可靠的控制。同时Docker隔离应用的能力非常适用于用户的云代码,能让我们比通过虚拟机更好的整合云代码应用和服务器,基于docker,我们能为每个不同的云代码应用创建隔离的环境,并为他们分配指定的服务端口、内存资源等来隔离应用。

移动云平台的基础架构之旅(二):云代码

在我们看来用户每次的代码发布都是一个构建镜像并推送镜像到私服上的过程,每次代码部署都是从私服上获取镜像并启动一个容器的过程,每次停止部署都是一个容器卸载的过程,每次升级代码都是一个重新生成不同标签的应用镜像的过程。用户每次上传发布云代码都需要为它指定一个版本,不同的版本会生成不同的镜像标签,可以同时部署多个版本,但我们做了限制,最多只能同时发布2个版本,我们称之为灰度发布,这是为了能让你的代码能平滑过渡升级,在灰度发布过程中用户需要设置版本负载均衡比重,以做到服务不间断,基于版本控制你可以回滚你的代码,你可以选择你发布过的任意版本进行部署,这真的非常方便。

移动云平台的基础架构之旅(二):云代码

对于用户的云代码镜像、启动的容器、部署的策略以及容器所在的宿主机我们会有一个专门的CloudCode-Manager服务来进行管理,我们称这个服务为hydra(海德拉)。它希腊神话中的九头蛇,传说它拥有九颗头,其中一颗头要是被斩断,立刻又会生出两颗头来,在这里我们寓意用户的云代码可以达到高可用,如果用户部署的任何一个云代码实例出现故障达到服务不用,系统会自动在其他宿主机上重新启动一个相同实例。为了达到高可用、故障转移,云代码SDK需要提供心跳接口,在用户部署云代码后每隔一段时间hydra都会做心跳检查,检查失败重试一定次数后便认为该服务已经失效,我们会在另一台宿主机上重新部署一个和故障实例一模一样的实例,然后再卸载故障实例,如果卸载故障实例失败,比如故障实例所在的宿主机发生宕机,那么该故障实例会永久成为一个孤岛实例等待被强制回收。如果应用的云代码被重度使用超过负荷可以随时扩容,或者通过缩容来较少成本,通过任意扩容和缩容也就是通过部署容器任意实例数量来真正达到高可用,最常用的使用场景是商家在做活动时有访问高峰可以快速增加实例资源来减少压力,日常时则减少实例以低成本运行。

通过docker来整合应用和服务器,一台宿主机上可能部署了上百个容器应用,那应用是如何分发的呢,在云代码SDK中我们提供了REST服务,比如云函数、后台任务、心跳等API,所有应用的这些REST服务在启动后都是监听在容器的8080端口,容器需要允许外部访问就必须要映射容器端口到宿主机,所以在应用分发过程中,宿主机的端口管理非常必要,我们使用mysql来存储所有宿主机的信息,包括所有提供给云代码容器使用的可用端口,通过乐观锁来保证端口的并发分配,启动任意云代码容器时都会分配一个映射端口给容器,同时在zookeeper中同步应用的云代码服务地址提供给MBaaS云代码服务使用。这个过程使用事务来保证容器启动和数据库信息的一致性,同时使用zookeeper分布式锁来防止同一个应用被同时操作。云代码服务的REST层实时监控zookeeper中云容器访问地址信息变更,通过hosting形式提供路由功能,通过负载均衡算法选择可用地址来访问宿主机上的云代码达到分流效果,这样就能做到简单有效的应用分发。

上面我们说到云代码容器通过端口映射来允许外部访问,但考虑到用户的代码安全,并不是任何机器都可以访问云代码容器,这就需要一个网络安全体系来对用户的访问和网络进行限制。在网络隔离安全方面,我们在Docker的标准网络桥接接口docker0上启用内核防火墙iptables规则来限制Docker容器的源IP地址范围与外界通讯,所有的云代码宿主机只能由zcloud和hydra服务所在的机器访问,而云代码访问zcloud内部服务需要通过反向代理实现。

移动云平台的基础架构之旅(二):云代码

在宿主机和容器之间安全隔离方面,通过访问控制的安全策略,使用selinux配置Linux内核安全模块,从而实现强制性的访问控制(MAC)用以将进程约束在一套有限的系统资源或权限中。在容器与容器之间通过cgroups防止通过耗尽系统资源引发拒绝服务(DoS)攻击,比如限制容器的CPU使用、内存使用、存储使用。

5、云代码该如何监控

使用微服务容器化云代码能为应用开发者省去部署和维护方面的负担,但代价是一定程度上减弱了线上环境的透明性,为了能对线上代码的错误和性能特征有更多了解以便优化自己的代码或者扩容、缩容来达到水平扩展,我们需要给很好的监控云代码。

移动云平台的基础架构之旅(二):云代码

1、首先是日志信息的收集,云代码的系统日志、用户的日志这些都需要收集起来提供给用户查看,MaxLeap的云代码使用主流的Logstash+elasticsearch来完成日志收集工作,我们会在每台宿主机上启动一个logstash-forwarder服务作为shipper来收集指定的云代码日志,Logstash汇聚日志后转发到ES存储。

2、其次是对容器资源的监控,Docker容器通过namespace做资源隔离,通过cgroup来做资源限制,我们有个专门的docker-monitor服务来监控所有宿主机上云代码容器的指标,它会周期性获取已注册的宿主机上所有云代码容器的cgroup stats,收集指标包括CPU MEM IO等,然后将数据PUSH到ES里。

3、最后是展示给用户,MaxLeap通过后台界面的方式展示出所有容器实例的性能和状态,还有部署的云代码版本所有的日志信息,用户可以很直观的了解到自己的云代码有什么错误的信息,在什么地方有瓶颈,该在哪方面优化代码。而我们内部会通过Kibana来展示,并通过Nagios来报警。

MaxLeap云代码的衍生-云容器

有客户看到这里说:你说了那么多,我就是不想用你的云代码SDK来写,熟悉你的SDK都要花费好长时间,用看官方文档头都大了,我就想用关系型数据库,我就是想用我自己写的后端服务或者之前公司已经写好的程序,咋办?嘿,MBaaS系统的愿景是让用户完全摆脱服务器,但遇到这种已经有自己服务器和数据库并大量线上使用的客户让他们选择MBaaS系统便得仔细考量是否值得了。考量到这类需求,MaxLeap在云代码的基础上衍生出了云容器的概念,它是可以帮助用户部署及运维其后端应用程序的代码托管服务,用户只需要提供服务端的业务逻辑,包括静态网站或者动态应用程序,而服务端的高可用、多实例、负载均衡、不中断服务的平滑升级等都由云容器提供支持。没错,云代码有的功能它都可以有,云代码没有的功能它也有,一个是数据源功能,很多企业客户内部使用的数据库都是mysql这种关系型数据库,让他们一下切换到MBaaS上的NoSql数据库会很不放心,特别对事务要求很严格的业务逻辑,人家可能一看到你的数据库是使用Nosql就放弃了,能很方便的迁移也不行,就是这么直接,云容器的数据源功能则会帮让他们放下很大一部分顾虑,它可以让用户使用并管理自己的关系型数据库,而另一个二级域名功能可以让用户在部署云容器后可以直接访问他的云服务。作为云代码的升级版,云容器的底层架构都是基于云代码的实现,这完全降低了用户Dev&Ops上的难度。由于篇幅原因,更多云容器相关的信息本篇文章不再赘述了。

MaxLeap云代码的展望

看到这我们发现MaxLeap的云代码、云容器的架构基本都是围绕docker容器这个生态圈来实现的,那么如何更好的维护和优化这个生态圈将是我们将来的重中之重,在这里我们给出一些我们未来一段时间将要实现和优化的关键信息:

移动云平台的基础架构之旅(二):云代码
  • 所有容器资源通过Mesos申请
  • 所有容器生命周期通过Marathon管理
  • 更智能的资源分配机制,更智能的压力监控实现自动扩容/缩容
  • 用户云代码托管方式支持git等第三方仓库
  • 用户上传云代码、云容器支持增量上传来减少等待时间
  • 更多容器安全方面的优化
  • 更多云代码/容器操作的Dev&Ops自动化
  • 更多基建架构方面的调整优化

MaxLeap更强大更优秀的云代码/云容器服务敬请大家期待。