0.前言
随着 Docker 技术的日渐火热,本就火爆的云计算行业进入了一个加速阶段。云计算最大的特点是弹性和灵活,帮助企业应对复杂的业务需求。由于云计算的IT构架和上一代的IT构架有很大不同,云原生应用(Cloud Native Application)概念应运而生。
云原生应用的优点体现在具有良好的可扩展性、伸缩性和容错性;不过想要享用云原生应用的种种良好特性并不是轻松的事,企业开发人员在开发业务应用的时候,还要考虑未来应用的可扩展性和容错性,不免增加了开发的复杂度。PaaS 的出现,正是要帮助开发人员降低云原生应用的开发复杂度,让开发人员还是专注于业务应用的开发,为开发人员屏蔽底层细节。
早器的 PaaS 平台过于复杂和笨重,没有得到广泛的应用,而基于 Docker 和 Mesos 打造的 DCOS 是下一代轻量级 PaaS 平台的典型代表。DCOS 极大地降低了 PaaS 平台的复杂度,更加方便企业开发人员实现各种业务应用,帮助企业轻松打造基于云计算的软件基础设施。
DCOS 主要带来以下几方面好处:
横向扩展,自动恢复
快速部署,高效迭代
混合部署,提高资源利用率
如果对 PaaS、DCOS 不太了解的人一一解释这些概念,不免有些晦涩。本文将从实际案例出发,结合不同的使用场景,为各位介绍 DCOS 的这些特性。
登陆爬虫
通过本案例说明,如何在DCOS上从头开始设计一个微服务架构的应用,在获得弹性扩展、高可用的特性下,如何进行服务发现
在线会议系统
通过本案例说明,如何改造原有的互联网应用上云,以及借助容器的快速部署特性,架构持续集成
文章分类与热词统计
通过本案例说明,如何在DCOS上实现大数据应用,以及借助 Mesos 实现混合部署,提高资源利用率
名词说明
Mesos:Mesos是一个分布式资源管理器,支持在多种计算集群框架(frameworks)间共享服务器集群资源,提高了集群资源占用率的同事,避免了每种框架的资源冲突。为了满足复杂的资源调度方法,Mesos 通过资源提供(resource offer)实现了基于 DRF 算法的二层资源调度机制。Mesos是未来数据中心操作系统(DCOS)的核心。
Marathon:Marathon 是一个 Mesos 的框架,能够支持在集群环境中管理长运行服务,可以理解是分布式的 Init.d,它能够运行任何 Linux 二进制发布版本如 Nginx 等,并可以对应用的分布式多进程进行管理。
Chronos:Chronos 是一个具备容错特性的作业调度器, 也是一个 Mesos 的框架,支持使用 Mesos Slave 作为作业执行器,用于在分布式环境下替代 cron。
服务发现:服务发现是指,任何一个应用的实例能够以编程的方式获取当前环境的细节,而新的实例可以嵌入到现有的应用环境而不需要人工干预。简单地说,在一个集群环境下,随着应用实例的增减或迁移,服务发现保证该服务仍然可以通过服务访问地址被访问。
持续集成:持续集成(Continuous Integration)是一种实践,可以让团队在持续的基础上收到反馈并进行改进,不必等到开发周期后期才寻找和修复缺陷。通俗一点儿说,就是对于开发人员的代码提交,都自动地把代码库中的代码进行编译、测试、打包。
微服务:微服务是一种新兴的应用软件架构,它通过一组服务的方式来构建一个应用,服务独立部署在不同的进程中,不同服务通过一些轻量级交互机制来通信,例如 REST。每个服务可独立扩展伸缩,并且定义了明确的边界,不同的服务甚至可以采用不同的编程语言来实现,由独立的团队来维护。
数人云:数人云是国内第一款数据中心操作系统,基于Mesos管理容器生产环境,并集成了 Marathon、Chronos 等组件,对企业数据中心提供集群管理,容器管理,服务发现,持续集成等服务。
1.登陆爬虫-微服务架构典型
该系统是一套实时的登陆爬虫系统,用户输入待爬取网站的用户名和密码,系统会自动登陆账号,并爬取账号内页面数据,以报告的形式提供给用户。这套系统常用于金融征信,评级机构获得用户的登录信息,通过爬虫系统爬取该用户的信用相关信息,形成信用报告。
先了解一下微幅架构的几个主要的设计理念:
通过服务实现组件化。微服务使用服务的形式来实现各个功能组件模块,各个模块间的依赖通过服务的方式来组织,即一个模块通过远程过程调用来依赖另一个模块,每个模块是一个微服务。
企业按照业务功能来组织团队,每个团队负责一个微服务,可以做到“谁构建,谁运行”,这将极大降低运维复杂度,缩短上线周期。
微服务可以方便地做到离散化数据管理。每个微服务可以自行管理各自的数据,包括不同业务的数据、不同微服务的配置等等,更加切实匹配业务需求。
微服务构架使得持续集成和持续交付变得更加便捷。有了微服务,集成和交付的单元从大而全的整体应用变成了各个微服务,每个微服务都可以灵活地集成和交付。
这个系统在设计之初就考虑采用微服务架构,以便部署在 DCOS 环境,并享受 DCOS 所带来的各种特性。
系统痛点:微服务架构
该系统希望依照微服务架构原则进行设计,将功能模块组件化,每个模块实现一个独立的功能,可单独部署,模块之间松散耦合。每个模块可根据业务负载灵活地增加或缩减可承载容量,同时每个模块由多个实例构成,避免整个系统由于单点故障而造成系统瘫痪。
第一步:系统设计
系统的业务需求大致如下图所示。
在得到授权的情况下,用户输入所要爬取的网站的登陆用户名和密码,提交爬取任务;
模拟用户行为登陆,登陆过程中要判断用户名、密码的正确性,如果有验证码,需要让用户判断验证码图片并输入验证码信息;
成功登陆后,即开始爬取账户页面,根据报告要求,从页面中抽取出有效信息,形成报告;
由于数据是多实例并行爬取的,需要在爬取结束后进行数据整合;
异步获取结果;用户登陆成功后,会提供一个查询码,并提示一段时间后进行查询;待爬取结束并形成后,用户方可查询到数据报告;
根据这些需求,需要以下系统组成:
一个 web ui,与用户交互;
模拟登陆模块Loginer;
爬取模块 Fetcher;
信息抽取模块 Extractor;
信息整合模块 Combiner;
ETL 模块:用于清洗数据,形成最终报告;
系统设计如下图所示。
用户通过 Access portal 输入待爬网站的用户名和密码,有些网站还需要输入验证码;
Loginer 接收到用户信息后,开始模拟用户登陆;模拟登陆可以采用 Selenium 或 Http Client 两种,需要渲染页面时使用 Selenium,否则用 Http Client 就够了;
登陆成功后,Logginer 会将 cookie 和爬取任务一同写入消息队列,Fetecher 负责领取任务,进行页面爬取; 爬取过程中,Fetcher 需要携带 Cookie 访问网站页面;
Fetcher 将爬取的页面存入消息队列,由 Executor 负责从页面中抽取需要的元素信息,并将这些信息放入缓存系统;
Combiner 负责将缓存中的数据进行拼装,并判断爬取是否结束;若结束,将爬取结果存入数据库;
ETL 模块负责将爬取结果进行清洗和整理,形成最终的报告;
用户在等待一段时间后,可以查询爬取结果,下载报告。
其中,Fetcher、Extractor、Combiner 三个组件都需要了解本次抓取需要有多少 task,以及每个 task 的状态,以便判断本次任务是否结束。
由于整个系统的每一个处理环节都是多实例的,模块之间都不直接发生依赖关系,而是采用消息队列或者存储系统进行解耦。
注:为了防止被某些网站限制 IP,还需要在 Loginer 前面增加一个代理层,每次使用随机的代理服务器进行网站访问和登陆,这样就避免了被封的风险。
第二步:服务发现
1 为什么需要服务发现
从上面的设计中可以看出,大部分服务之间都通过分布式消息队列或存储系统进行交互,这样做的好处使得服务之间实现了异步交互,降低了耦合性。但这种异步方式并不适应于任何场合,例如 Loginer 的设计就必须采用同步调用的方式,主要原因是:
用户在输入用户名、密码后,需要 Loginer 立刻进行模拟登陆以验证输入的正确性;
如果网站登陆页的验证码是在用户名、密码输入后才显示,则还需要将验证码图片返回给用户,由用户判别并输入验证码信息(有的验证码可通过打码服务直接获取验证码信息,但并这并不适用于所有验证码系统)后,再进行登陆操作;
Loginer 采用 Selenium 或 Http Client 进行模拟登陆,当网站登录页需要进行 JS 渲染的时候,就需要用到 Selenium;Selenium 通过浏览器 driver 打开浏览器,访问登录页,开始进行模拟操作;为了简化浏览器状态的维护,在设计时限定每个 Loginer 实例同时只能处理一个登录请求,直到本次登录完全结束,关闭浏览器,才可以处理下一个登录请求。可见,每个 Loginer 需要维持一个状态机。
正因如此,Loginer 需要部署较多的实例数;另外,由于浏览器 driver 不够稳定,时而出现调用无效的情况,Loginer 需要有重启机制;
2 服务发现
数人云提供了一套完善的面向微服务架构的服务发现方案,如下图所示。
现有服务发现根据 marathon+zookeeper+bamboo+haproxy 一起工作解决,具体说明如下:
应用动态变化导致 marathon 将状态信息写入 zookeeper(包括所在的主机 IP、端口等),然后把变化事件发给事件订阅用户, bamboo 作为订阅用户, marathon-leader 会将变化事件发送给 bamboo。
bamboo 拿到事件后,按照事件给定的应用标示去 zookeeper 中取对应的状态数据。
bamboo 拿到数据后按照预先设定的 haproxy 模版生成一个临时配置文件。
bamboo 将临时配置文件和现有 haproxy 配置文件进行对比。
bamboo 对比后,如果一致将直接结束任务。如果不一致,检查一下配置文件格式。
bamboo 如果配置文件格式异常,将结束任务。如果正常,将 reload haporxy 加载新配置文件。
将 Loginer 通过数人云发布,发布应用时指定应用地址,即在 haproxy 上配置一个访问端口,再有服务发现机制将请求转发到具体的应用实例,具体请见数人云用户手册。
如果某个 Loginer 实例在处理登陆任务时出现异常,只需要结束进程,该 Docker 容器会自动 stop;Marathon 监听到有应用容器停止,会重新启动一个新容器以保证服务容量。注意,新容器不一定运行在结束运行的旧容器所在的主机,可以是指定集群范围内的任何主机,而服务发现会帮助我们自动发现该容器并进行请求转发。
当然,在横向扩展时,增加 Loginer 的实例数,不仅可以做到快速地平滑扩展(业务不停),也会将新实例通过服务发现加入到转发列表中。
数人云还在 Haproxy 设置了会话保持,如果是基于 cookie 的会话,Haproxy 会将同一会话请求转发到同一容器。
小结
至此,一套具备横向扩展能力,高可用的登陆爬虫系统就设计完了。
回头来看,整个系统就是一个数据处理的 pipeline,每个环节之间松散耦合,具备高可用,可以独自做到横向扩容或缩减,基本符合了微服务架构的特性。这样的架构也为持续集成创造了良好的基础,我们会在下一个案例介绍基于DCOS的持续集成。
注:数人云新版的服务发现功能已经修改了策略,不再需要用户选择将代理部在某几台主机上,而是由系统默认安装在集群除了 Master 之外的所有主机上,构成一个覆盖全计算资源的代理集群,确保服务发现的高可用;同时对 proxy 进行了优化,降低了运行带来的系统开销。
2.在线会议系统-互联网持续集成典型
这是一个在线会议工具,用户可以通过微信登陆并接入系统,邀请好友开始远程会议。该应用架构复杂度中等,为典型的互联网应用。
该应用的技术架构如下图所示。
如图所示,其架构图中包括 Redis,Mysql,OSS,file-server 等存储节点,也包括 web-server,api-server,push server 等服务节点,还有前端的 nginx 反向代理等。
服务节点间存在相互依赖。
所有节点都部署在阿里云,部分存储服务使用了阿里云服务。
系统痛点:
部署耗时:由于我们的服务较多,版本发布的时候,需要每个服务都单独编译、打包、部署,一般要1到2个小时才能完成部署任务;迁移麻烦:如果需要部署新的机器,每个新机器还需要配置环境,很麻烦;扩展性差:现在的服务依赖都是单向直接依赖,没有做负载均衡,不能扩展。
第一步:系统 Docker 化 & 上云
经过对其业务流进行梳理,我们大致得到以下架构。
架构图中包括以下内容:
每个服务的端口使用;
服务间依赖关系;
服务是否有状态;
分别标注对外服务、对内服务及存储;
对应用大致做了以下改造:
服务节点 Docker 化;
服务节点无状态化,具备横向扩展能力;
抽离配置文件,解耦组件间依赖;
多实例化的服务之间进行服务发现。
上云步骤:
为每一个子项目编写 Dockerfile
安装私有 Docker Registry
部署应用
监控与测试
第二步:持续集成
持续集成是一种软件开发实践,即团队开发成员经常集成它们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。而Jenkins是一个自动构建服务,使用Java实现,有成百上千插件,使用他可以很方便实现持续集成。
-
搭建 Jenkins
对于 Jenkins 的安装和部署,这里不再累述。
值得一提的是,数人云集群使用 Apache Mesos 进行资源的统一调度,通过数人云可以快速搭建 Jenkins。把Jenkins运行到 Mesos 上,或者说利用 Mesos 向 Jenkins 提供 slave 资源,一方面通过分布式特性加快构建过程,另一方面也提高了资源利用率。通过配置 Jenkins-on-Mesos 插件,Jenkins Master 可以在作业构建时根据实际需要动态的向 Mesos 申请 slave 节点,并在构建完成的一段时间后将节点归还给 Mesos。
具体教程请见 快速搭建 Jenkins 持续集成环境加速产品迭代。
代码库创建工程
需要内部的代码库或者公共代码库为每一个组件创建一个项目。本案使用了 Github 作为代码库,Jenkins 已原生支持 Github。这里要注意的是,需要保证 Jenkins 有权限 pull/push 上面我们所创建的 git repo。另外,工程要包含 Dockerfile,以便在构建过程中生成 Docker 镜像。
镜像构建任务
在 Jenkins 里创建构建任务, 任务从 git repo 拉取代码,指定 release 的 tag,使用 repo 里的Dockerfile,构建 Docker 镜像,并推送镜像到 Registry 里。
根据不同的系统架构,可以将构建任务拆成不同的粒度。最简单的,一个任务构建所有的子项目。如果项目比较复杂的情况下,每次构建时间会比较长,造成不必要的资源浪费,那么可以将构建任务拆分到颗粒度更小的子项目。
构建触发设置,可以为每次 push 后进行构建。但一般情况下,每个子项目也是有多人协作的,而且并不是每一次代码提交都需要进行构建,因此构建触发策略设为 Tag push 触发,及每当增加 tag 时,触发构建任务。
镜像发布任务
在 Jenkins 里新建任务, 在这个任务里,通过调用数人云 Rest API 获取认证token, 发布应用到 Mesos 集群。
可以设置发布任务的自动触发,比如当一个构建任务完成后触发,或者每天晚上2点触发,要根据不同的环境需要来进行选择。
发布脚本中,通过调用数人云 Rest API 获取认证 token, 以应用的形式发布到数人云平台。这里用curl命令发布应用。也可以用 python、shell 等脚本调用 API 发布应用,我们也推荐这样做,可以更好的检查调用API的返回。
后续
以上,实现了整套系统上云以及构建持续集成的过程。下一步便是构建从开发、集成到生产的完整运维体系。一般情况下,针对一个互联网产品,开发环境由开发进行构建和发布,可以设置为 push 触发或者前面提到的 tag push 触发;集成环境由 QA 进行构建和发布,QA 定期发布并进行集成测试,发现问题后再回退到之前版本;生产环境往往通过手动方式触发发布,在发布前需要做好客户通知、应急处理等各项准备。
值得注意的是,将多份环境进行统一发布管理,还需要配备配置服务器用于管理不同环境的配置信息,而这是另一个话题了。
重要提示:数人云新版已发布了持续集成服务,上述通过 Jenkins 部署和配置持续集成过程仍显得比较繁重,那么通过数人云管理界面,通过简单的操作就可以实现自动构建的全过程,具体请参见数人云用户手册。
3.文章分类与热词推荐-混合部署、大数据典型
这是DCOS上的大数据项目。项目来源自一个互联网媒体客户,需求是将积累的媒体文章进行分类,并找出能代表一篇文章的关键词作为文章标签,用于进行文章的分类或热词统计等数据分析,文章数量近5万余篇,且在不断增加。
项目选用 Apache Spark 作为计算框架,并通过 Spark MLlib 提供的 LDA 算法对文章进行聚类,得到“文章-主题”和“主题-关键词”矩阵,并以主题词作为文章标签,对文章进行归类。
Apache Spark 作为一个分布式大数据计算框架,与 Apache Mesos 完美结合。Mesos 作为 Spark 集群的资源调度器,可以将 Mesos 集群的资源以粗、细两种粒度分配给 Spark;在 Spark 完成计算任务后,Mesos 可以将资源回收,供其他服务使用。
从上图看出,项目一共包括数据预处理、模型训练、预测训练集三个离线计算任务,和一个提供预测、添加文章、热词查询等功能的服务模块。
系统痛点:
Spark 计算任务需要大量计算资源,主要工作时间在凌晨时间,这些资源在白天是闲置的。该系统还需要 Nginx、MySQL 等服务组件,如果能将它们混补在同一组服务器上,则可以降低成本,提高资源利用率。
本案通过数人云管理 Mesos 集群,通过 Marathon 管理长运行的服务型应用,通过 Chronos 管理离线计算任务,同时在集群中部署了 HDFS 分布式文件系统以及私有 Docker Registry。
其中,MySQL 用于存放每天的新文章数据,以及预测后的结果数据集;Nginx 用于对外提供服务。每天晚上2点运行 Spark 计算任务,更新模型并对训练集数据重新预测。
第零步:搭建 Spark 计算环境
Spark 采用 Mesos 作为资源调度器时,由 Mesos 统一调度计算资源,因此,Spark 集群无需部署,Mesos 集群即为 Spark 集群。
制作 Spark base 镜像,这部分不再累述,请参见使用数人云运行 Spark,或者也可以使用数人云开放的 Spark base 镜像:index.shurenyun.com/spark:1.5.0-hadoop2.6.0
。
本案存储层选用了 HDFS。Spark 连接 HDFS 时拥有数据位置识别能力,并会从集群内距离最近的节点处读取数据,从而最大程度降低数据在网络中的传输需求。为了充分发挥 Spark 的数据位置识别能力,大家应当让 Spark 计算任务与 HDFS 节点共同部署在一个集群中。
数人云提供为主机打标签的服务。如果 HDFS 只部署在集群的部分主机上,可以为这部分主机打上标签,在部署 Spark 计算任务的时候,可以限定在该标签范围内执行。具体请参见数人云用户手册。
第一步:部署 Chronos 任务
将 Spark 计算任务通过 Chronos 发布到集群中,Chronos 是一个具备容错特性的作业调度器,支持使用 Mesos 作为作业执行器,用来在分布式环境下替代 cron。
制作任务镜像
因为代码和配置文件变动相对频繁,因此基于 Spark base 镜像制作一个包含二进制包和配置文件的任务镜像。
Spark 项目的目录如下:
├── README.md
├── build.sbt
├── conf
├── project
├── src
└── target
其中,conf 中包含了 Spark 的配置文件:spark-env.sh,spark-defaults.conf。
任务镜像的 Dockerfile 如下:
FROM index.shurenyun.com/spark:1.5.0-hadoop2.6.0
ADD target/scala-2.10/spark_lda.jar .
ADD conf .
CMD ./run.sh
Spark 程序通过 SBT 编译,二进制包生成在 target/scala-2.10/spark_lda.jar
。
根据调试或部署的需要,将 Spark 的配置目录导入并替换原文件,便于配置更新。
运行脚本run.sh
是具体的 spark-submit 指令:
bin/spark-submit --class com.dataman.omega.service.Boot /opt/dist/spark/spark_lda.jar
将三个离线计算任务分别制作成镜像,然后将制作好的镜像上传到到镜像仓库。
发布任务
Chronos 是一个具备容错特性的作业调度器,支持使用 Mesos 作为作业执行器,用来在分布式环境下替代 cron。数人云已经集成 Chronos,并对外开放了发布定时任务的 REST API。为三个离线计算任务分别创建 Chronos 任务,名为preprocessJob
,trainJob
,predictJob
。一个具体的定时任务发布指令如下:
curl -X POST https://api.shurenyun.com/api/v3/clusters/88/jobs \
-H Content-Type: application/json \
-H Accept: application/json \
-H Authorization: 6d8c5051f09242408f966f762cc9b674 -d '{
"name": "preprocessJob",
"imageURI": "index.shurenyun.com/Spark_preprocess",
"imageversion": "v1",
"cpu": 4,
"mem": 8192,
"owner": "yma@dataman-inc.com",
"ownerName": "yma",
"schedule": "R/2016-03-15T02:00:00.000Z/P1D",
"command": "",
"parents": [
""
],
"volumes": [
],
"constraints":[["Tags", "LIKE", "HDFS"]]
}'
有几个注意的地方:
schedule:
R/2016-03-15T02:00:00.000Z
表示任务定为晚上2点开始执行,P1D
表示每隔一天执行一次;parents:该任务执行的先决条件,不能和 schedule 字段同时使用;由于 preprocessJob 是第一个执行任务,因此设置 了 schedule,后面的任务比如 trainJob,则要设置 parents 为
preprocessJob
;command:原生 Chronos API 不允许该字段为空,数人云已经修补了该 bug。
具体的 API 说明请参见数人云 API 文档。
第二步:部署长运行服务
Nginx,MySQL 这类长运行服务,通过 Marathon 发布。数人云已集成 Marathon,并提供了简洁的 UI,具体方法请参见数人云手册。
小结
由于服务访问大部分发生在白天,而 Spark 计算只在晚上进行,因此完全可以把以上任务和服务都混合部署在同一集群内,提高了整体资源利用率。
Mesos 具有处理各种异构任务负载的特性,因而使得在同一个平台上管理大数据应用和 Web 应用成为可能。数人云集成了平台监控工具,可以方便地监控集群、主机、应用三个层面的资源使用情况以及各种应用状态,简化了运维工作。
注:HDFS 也可以通过 Mesos 部署,如果有的小伙伴觉得部署原生 HDFS 很麻烦的话,可以参考将 HDFS 搬上数人云:轻松实现集群的扩展收缩。
4.总结
本文针对不用的应用场景,提供了基于数人云 DCOS 的应用上云方案,并分别说明了 DCOS 的特性;其实,只要处理得当,每一个场景都是可以受用 DCOS 的多种特性的。
由于应用的多样性和复杂性,应用上云并不止以上内容,更多内容请咨询数人云。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。