Skip to main content

利用Docker开启持续交付之路

持续交付即Continuous Delivery,简称CD,随着DevOps的流行正越来越被传统企业所重视。持续交付讲求以短周期、小细粒度,自动化的方式频繁的交付软件,在这个过程中要求开发、测试、用户体验等角色紧密合作,快速收集反馈,从而不断改善软件质量并减少浪费。然而,在我所接触的传统企业中,对于持续交付实践的实施都还非常初级,坦白说,大部分还停留的手工生成发布包,手工替换文件进行部署的阶段,这样做无疑缺乏管理且容易出错。如果究其原因,我想主要是因为构建一个可实际运行且适合企业自身环境的持续发布流程并不简单。然而,Docker作为轻量级的基于容器的解决方案,它对系统侵入性低,容易移植,天生就适合做自动化部署,这些特性非常有助于降低构建持续交付流程的复杂度。本文将通过一个实际案例分享我们在一个真实项目中就如何使用Docker构建持续发布流程的经验总结,这些实践也许不是最先进的,但确是非常实际和符合当时环境的。

项目背景

我们的客户来自物流行业,由于近几年业务的飞速发展,其老的门户网站对于日常访问和订单查询还勉强可以支撑,但每当遇到像双十一这样访问量成倍增长的情况就很难招架了。因此,客户希望我们帮助他们开发一个全新的门户网站。

新网站采用了动静分离的策略,使用Java语言,基于REST架构,并结合CMS系统。简单来说,可以把它看成是时下非常典型的一个基于Java的Web应用,它具体包含如下几个部分:

  • 基于Jersey的动态服务(处理客户端的动态请求)
  • 二次开发的OpenCMS系统,用于静态导出站点
  • 基于js的前端应用并可以打包成为一个OpenCMS支持的站点
  • 后台任务处理服务(用于处理实时性要求不高的任务,如:邮件发送等)

以下是系统的逻辑软件架构图:

01

面临的挑战以及为什么选择Docker

在设计持续交付流程的过程中,客户有一个非常合理的需求:是否可以在测试环境中尽量模拟真实软件架构(例如:模拟静态服务器的水平扩展),以便尽早发现潜在问题?基于这个需求,可以尝试将多台机器划分不同的职责并将相应服务按照职责进行部署。然而,我们遇到的第一个挑战是:硬件资源严重不足尽管客户非常积极的配合,但无奈于企业内部层层的审批制度。经过两个星期的努力,我们很艰难的申请到了两台四核CPU加8G内存的物理机(如果申请虚拟机可能还要等一段时间),同时还获得了一个Oracle数据库实例。因此,最终我们的任务就变为把所有服务外加持续集成服务器(Jenkins)全部部署在这两台机器上,并且,还要模拟出这些服务真的像是分别运行在不同职责的机器上并进行交互。如果采用传统的部署方式,要在两台机器上完成这么多服务的部署是非常困难的,需要小心的调整和修改各个服务以及中间件的配置,而且还面临着一旦出错就有可能耗费大量时间排错甚至需要重装系统的风险。第二个挑战是:企业内部对UAT(与产品环境配置一致,只是数据不同)和产品环境管控严格,我们无法访问,也就无法自动化。这就意味着,整个持续发布流程不仅要支持自动化部署,同时也要允许下载独立发布包进行手工部署。

最终,我们选择了Docker解决上述两个挑战,主要原因如下:

  • Docker是容器,容器和容器之间相互隔离互不影响,利用这个特性就可以非常容易在一台机器上模拟出多台机器的效果
  • Docker对操作系统的侵入性很低,因其使用LXC虚拟化技术(Linux内核从2.6.24开始支持),所以在大部分Linux发行版下不需要安装额外的软件就可运行。那么,安装一台机器也就变为安装Linux操作系统并安装Docker,接着它就可以服役了
  • Docker容器可重复运,且Docker本身提供了多种途径分享容器,例如:通过export/import或者save/load命令以文件的形式分享,也可以通过将容器提交至私有Registry进行分享,另外,别忘了还有Docker Hub

下图是我们利用Docker设计的持续发布流程:

02

图中,我们专门设计了一个环节用于生成唯一发布包,它打包所有War/Jar、数据库迁移脚本以及配置信息。因此,无论是手工部署还是利用Docker容器自动化部署,我们都使用相同的发布包,这样做也满足持续交付的单一制品原则(Single Source Of Truth,Single Artifact)。

Docker与持续集成

持续集成(以下简称CI)可以说是当前软件开发的标准配置,重复使用率极高。而将CI与Docker结合后,会为CI的灵活性带来显著的提升。由于我们项目中使用Jenkins,下面会以Jenkins与Dcoker结合为例进行说明。

1.创建Jenkins容器

相比于直接把Jenkins安装到主机上,我们选择把它做为Docker容器单独使用,这样就省去了每次安装Jenkins本身及其依赖的过程,真正做到了拿来就可以使用。

Jenkins容器使创建一个全新的CI变的非常简单,只需一行命令就可完成:

docker run -d -p 9090:8080 ——name jenkins jenkins:1.576

该命令启动Jenkins容器并将容器内部8080端口重定向到主机9090端口,此时访问:主机IP:9090,就可以得到一个正在运行的Jenkins服务了。

为了降低升级和维护的成本,可将构建Jenkins容器的所有操作写入Dockerfile并用版本工具管理,如若需要升级Jenkins,只要重新build一次Dockerfile:

FROM ubuntu
ADD sources.list /etc/apt/sources.list
RUN apt-get update && apt-get install -y -q wget
RUN wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
ADD jenkins.list /etc/apt/sources.list.d/
RUN apt-get update
RUN apt-get install -y -q jenkins
ENV JENKINS_HOME /var/lib/jenkins/
EXPOSE 8080
CMD ["java", "-jar", "/usr/share/jenkins/jenkins.war"]

每次build时标注一个新的tag:

docker build -t jenkins:1.578 —rm .

另外,建议使用Docker volume功能将外部目录挂载到JENKINS_HOME目录(Jenkins会将安装的插件等文件存放在这个目录),这样保证了升级Jenkins容器后已安装的插件都还存在。例如:将主机/usr/local/jenkins/home目录挂载到容器内部/var/lib/jenkins:

docker run -d -p 9090:8080 -v /usr/local/jenkins/home:/var/lib/jenkins ——name jenkins jenkins:1.578

2. 使用Docker容器作为Jenkins容器的Slave

在使用Jenkins容器时,我们有一个原则:不要在容器内部存放任何和项目相关的数据。因为运行中的容器不一定是稳定的,而Docker本身也可能有Bug,如果把项目数据存放在容器中,一旦出了问题,就有丢掉所有数据的风险。因此,我们建议Jenkins容器仅负责提供Jenkins服务而不负责构建,而是把构建工作代理给其他Docker容器做。

例如,为了构建Java项目,需要创建一个包含JDK及其构建工具的容器。依然使用Dockerfile构建该容器,以下是示例代码(可根据项目实际需要安装其他工具,比如:Gradle等):

FROM ubuntu
RUN apt-get update && apt-get install -y -q openssh-server openjdk-7-jdk
RUN mkdir -p /var/run/sshd
RUN echo 'root:change' |chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

在这里安装openssh-server的原因是Jenkins需要使用ssh的方式访问和操作Slave,因此,ssh应作为每一个Slave必须安装的服务。运行该容器:

docker run -d -P —name java java:1.7

其中,-P是让Docker为容器内部的22端口自动分配重定向到主机的端口,这时如果执行命令:

docker ps
804b1d9e4202       java:1.7           /usr/sbin/sshd -D     6 minutes ago       Up 6 minutes       0.0.0.0:49153->22/tcp   java

端口22被重定向到了49153端口。这样,Jenkins就可以通过ssh直接操作该容器了(在Jenkins的Manage Nodes中配置该Slave)。

有了包含构建Java项目的Slave容器后,我们依然要遵循容器中不能存放项目相关数据的原则。此时,又需要借助volume:

docker run -d -v /usr/local/jenkins/workspace:/usr/local/jenkins -P —name java java:1.7

这样,我们在Jenkins Slave中配置的Job、Workspace以及下载的源码都会被放置到主机目录/usr/local/jenkins/workspace下,最终达成了不在容器中放置任何项目数据的目标。

通过上面的实践,我们成功的将一个Docker容器配置成了Jenkins的Slave。相比直接将Jenkins安装到主机上的方式,Jenkins容器的解决方案带来了明显的好处:

  • 重用更加简单,只需一行命令就可获得CI的服务;
  • 升级和维护也变的容易,只需要重新构建Jenkins容器即可;
  • 灵活配置Slave的能力,并可根据企业内部需要预先定制具有不同能力的Slave,比如:可以创建出具有构建Ruby On Rails能力的Slave,可以创建出具有构建NodeJS能力的Slave。当Jenkisn需要具备某种能力的Slave时,只需要docker run将该容器启动,并配置为Slave,Jenkins就立刻拥有了构建该应用的能力。

如果一个组织内部项目繁多且技术栈复杂,那么采用Jenkins结合Docker的方案会简化很多配置工作,同时也带来了相率的提升。

Docker与自动化部署

说到自动化部署,通常不仅仅代表以自动化的方式把某个应用放置在它应该在的位置,这只是基本功能,除此之外它还有更为重要的意义:

  • 以快速且低成本的部署方式验证应用是否在目标环境中可运行(通常有TEST/UAT/PROD等环境);
  • 以不同的自动化部署策略满足业务需求(例如:蓝绿部署);
  • 降低了运维的成本并促使开发和运维人员以端到端的方式思考软件开发(DevOps)。

在我们的案例中,由于上述挑战二的存在,导致无法将UAT乃至产品环境的部署全部自动化。回想客户希望验证软件架构的需求,我们的策略是:尽量使测试环境靠近产品环境。

  1. 标准化Docker镜像

很多企业内部都存在一套叫做标准化的规范,在这套规范中定义了开发中所使用的语言、工具的版本信息等等,这样做可以统一开发环境并降低运维团队负担。在我们的项目上,依据客户提供的标准化规范,我们创建了一系列容器并把它们按照不同的职能进行了分组,如下图:

03

图中,我们把Docker镜像分为三层:基础镜像层、服务镜像层以及应用镜像层,下层镜像的构建依赖上层镜像,越靠上层的镜像越稳定越不容易变。

基础镜像层

  • 负责配置最基本的、所有镜像都需要的软件及服务,例如上文提到的openssh-server

服务镜像层

  • 负责构建符合企业标准化规范的镜像,这一层很像SaaS

应用镜像层

  • 和应用程序直接相关,CI的产出物

分层后, 由于上层镜像已经提供了应用所需要的全部软件和服务,因此可以显著加快应用层镜像构建的速度。曾经有人担心如果在CI中构建镜像会不会太慢?经过这样的分层就可以解决这个问题。

在Dockerfile中使用FROM命令可以帮助构建分层镜像。例如:依据标准化规范,客户的产品环境运行RHEL6.3,因此在测试环境中,我们选择了centos6.3来作为所有镜像的基础操作系统。这里给出从构建base镜像到Java镜像的方法。首先是定义base镜像的Dockerfile:

FROM centos
# 可以在这里定义使用企业内部自己的源
RUN yum install -y -q unzip openssh-server
RUN ssh-keygen -q -N "" -t dsa -f /etc/ssh/ssh_host_dsa_key && ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN echo 'root:changeme' | chpasswd
RUN sed -i "s/#UsePrivilegeSeparation.*/UsePrivilegeSeparation no/g" /etc/ssh/sshd_config \
&& sed -i "s/UsePAM.*/UsePAM no/g" /etc/ssh/sshd_config
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

接着,构建服务层基础镜像Java,依据客户的标准化规范,Java的版本为:jdk-6u38-linux-x64:

FROM base
ADD jdk-6u38-linux-x64-rpm.bin /var/local/
RUN chmod +x /var/local/jdk-6u38-linux-x64-rpm.bin
RUN yes | /var/local/jdk-6u38-linux-x64-rpm.bin &>/dev/null
ENV JAVA_HOME /usr/java/jdk1.6.0_38
RUN rm -rf var/local/*.bin
CMD ["/usr/sbin/sshd", "-D"]

如果再需要构建JBoss镜像,就只需要将JBoss安装到Java镜像即可:

FROM java
ADD jboss-4.3-201307.zip /app/
RUN unzip /app/jboss-4.3-201307.zip -d /app/ &>/dev/null && rm -rf /app/jboss-4.3-201307.zip
ENV JBOSS_HOME /app/jboss/jboss-as
EXPOSE 8080
CMD ["/app/jboss/jboss-as/bin/run.sh", "-b", "0.0.0.0"]

这样,所有使用JBoss的应用程序都保证了使用与标准化规范定义一致的Java版本以及JBoss版本,从而使测试环境靠近了产品环境。

  1. 更好的组织自动化发布脚本

为了更好的组织自动化发布脚本,版本化控制是必须的。我们在项目中单独创建了一个目录:deploy,在这个目录下存放所有与发布相关的文件,包括:用于自动化发布的脚本(shell),用于构建镜像的Dockerfile,与环境相关的配置文件等等,其目录结构是:

├── README.md
├── artifacts   # war/jar,数据库迁移脚本等
├── bin         # shell脚本,用于自动化构建镜像和部署
├── images       # 所有镜像的Dockerfile
├── regions     # 环境相关的配置信息,我们只包含本地环境及测试环境
└── roles       # 角色化部署脚本,会本bin中脚本调用

这样,当需要向某一台机器上安装java和jboss镜像时,只需要这样一条命令:

bin/install.sh images -p 10.1.2.15 java jboss

而在部署的过程中,我们采用了角色化部署的方式,在roles目录下,它是这样的:

├── nginx
│   └── deploy.sh
├── opencms
│   └── deploy.sh
├── service-backend
│   └── deploy.sh
├── service-web
│   └── deploy.sh
└── utils.sh

这里我们定义了四种角色:nginx,opencms,service-backend以及service-web。每个角色下都有自己的发布脚本。例如:当需要发布service-web时,可以执行命令:

bin/deploy.sh -e test -p 10.1.2.15 service-web

该脚本会加载由-e指定的test环境的配置信息,并将service-web部署至IP地址为10.1.2.15的机器上,而最终,bin/deploy.sh会调用每个角色下的deploy.sh脚本。

角色化后,使部署变的更为清晰明了,而每个角色单独的deploy脚本更有利于划分责任避免和其他角色的干扰。

  1. 构建本地虚拟化环境

通常在聊到自动化部署脚本时,大家都乐于说这些脚本如何简化工作增加效率,但是,其编写过程通常都是痛苦和耗时,需要把脚本放在相应的环境中反复执行来验证是否工作正常。这就是我为什么建议最好首先构建一个本地虚拟化环境,有了它,就可以在自己的机器上反复测试而不受网络和环境的影响。

Vagrant(http://www.vagrantup.com/)是很好的本地虚拟化工具,和Docker结合可以很容易的在本地搭建起与测试环境几乎相同的环境。以我们的项目为例,可以使用Vagrant模拟两台机器,以下是Vagrantfile示例:

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.define "server1", primary: true do |server1|
server1.vm.box = "raring-docker"
server1.vm.network :private_network, ip: "10.1.2.15"
end
config.vm.define "server2" do |server2|
server2.vm.box = "raring-docker"
server2.vm.network :private_network, ip: "10.1.2.16"
end
end

由于部署脚本通常采用SSH当方式连接,所以,完全可以把这两台虚拟机看做是网络中两台机器,调用部署脚本验证是否正确。限于篇幅,这里就不多说了。

4 构建企业内部的Docker Registry

上文提到了诸多分层镜像,如何管理这些镜像?如何更好的分享?答案就是使用Docker Registry。Docker Registry是一个镜像仓库,它允许你向Registry中提交(push)镜像同时又可以从中下载(pull)。

构建本地的Registry非常简单,执行下面的命令:

docker run -p 5000:5000 registry

更多关于如何使用Registry可以参考地址:https://github.com/docker/docker-registry

当搭建好Registry后,就可以向它push你的镜像了,例如:需要将base镜像提交至Registry:

docker push your_registry_ip:5000/base:centos

而提交Java和JBoss也相似:

docker push your_registry_ip:5000/java:1.6
docker push your_registry_ip:5000/jboss:4.3

使用下面的方式下载镜像:

docker pull your_registry_ip:5000/jboss:4.3

总结

本文总结我们在实际案例中使用Docker一些实践,它给我们的印象就是非常灵活,几乎是一个多面手,给整个流程带来了极大的灵活性和扩展性,并且也展现了极好的性能,符合它天生就为部署而生的特质。

Share

敏捷咨询日记——匠人精神

“敏捷,是一种匠人阶层的唤醒”

我曾经拜访过印度某个Freemason(共济会)分所,这个世界上最大地下组织来源于传说中制造巴比伦神殿的三个石匠。教谕认为石匠是人类中掌握自然奥秘的一群人,常人只是“神有缺陷的复制品”,而只有靠匠工的不懈努力才能修补人类缺陷使其更接近于神。这也是为什么共济会的标志便是圆规和方矩,方圆规矩的隐喻在六芒星下变得直白。

也许西欧文明开化来自于匠工阶层精英化,不论是对技能技巧的极致追求,或是家族荣耀的逐代传承,这样的阶层似乎在可以营造一种近乎偏执的质量文化。之后,匠人阶层的经验和行规在大生产时代演变成各种制造业雏形,最终演化成一种现代的规模化的制造业体系。从匠人阶级到现代制造业体系,必然是某种技能精益,经验积累,和规则验证极致后模式化规模化的演变。而究其根本,其核心充满着精益中两大核心:“以人为本”-社区荣誉(community honor)和家族传承;“持续改进”-技能演进,经验积累。

相对于西欧文明,我一直苦恼于为何从未断代的华夏文明始终未曾在历史的任何时刻诞生一个类似的匠人阶层。匠人这个在欧洲曾经被认为是改造自然改造人类的职业,在中国被关闭在始皇帝的骊陵中殉葬。不止一次在伦敦的大英博物馆感叹同时期中国的器物精细之程度远胜于欧洲其他文明,但惋惜的是,繁荣延续的匠人阶层未曾出现,更未曾产生过一个趋于成熟的制造业体系。

值得一提的是,欧洲文明善于制作工具,华夏文明善于制作器物本身。工具的目的是为了传承技术,传承技术的目的是为了改进技术,而若只关注于极致精细器物本身,只能理解为中国曾经出现的伟大匠人更关注于“孤品”,或者是更关注于权威绑架。

从精益中衍生的质量文化实际上是对匠人阶层的一种传承,近乎偏执的关注质量,并使用专属的工具和执行相关的流程保证质量,这必是对16世纪共济会繁荣时代(也是工业时代开始的萌芽期)致敬。

很多次,我被告知“以人为本”不可能实现,我忍不发,因我明白匠人们自古以来只是领导者手中更高级的工具,只需做,不必问。而我真正希望做的,是在某种程度上唤醒我们缺失了千年的匠人荣耀,让他们清晰地听见,如果人类走向完美的历程为敏捷项目,他们便是骄傲的交付者。

本文转自:http://i25zt5.lawrence-gd.diancloud.cn/agile-craftman/

Share

20天3D打印总结

Screen Shot 2015-04-22 at 12.24.17 PM

mbot cube 3D打印机拿到手也有20多天了,有空就玩玩,还是做了一些好玩实用的东西出来,总结一些经验来分享。总体来讲3D打印技术还不是太难掌握,对于打印素材来源及模型选择有一些讲究,要特别注意一些模型打印起来非常困难,甚至无法打印。

模型来源

我自己的3D模型主要来源于thingiverse网站,丰富的模型分类及社区的力量提供了非常多的资源。很可惜的是中国访问奇慢,主要原因是网站使用了亚马逊S3和cloudflare云,这两个基本被中国屏蔽,要不就是慢的死人。所以一个给力的代理是唯一的解决方案,否则你会失去很多的乐趣。代理可以参考我之前的shadowsocks在digitalocean上用的例子。

国内有一个叫“天工社”的论坛,上面有很多的模型可供选择,我看大部分还是来自于thingiverse网站的,有些人靠这些来赚积分。

在thingiverse网站上,我做自己做了一些东西,请直接打开网站看

一些成功的例子

失败的例子

模型的选择

尽量不选择太复杂太精细的模型,有些细小的部件,打印机会吐出来一点材料,根本无法顺利的打印出来。有些结构一次性打印的话需要很多的支撑材料,这些支撑会产生很大的麻烦,去除材料的时候会显得很郁闷。当然如果你的打印机是双头的,并且有水溶的材料,那就另当别论了。

所以比较好的模型都是一些稍微简单,甚至是组装的模型。组装的模型比较好打印每个部件,但是有些接插件会遇到无法插入的问题。内孔一般会缩小,外孔一般会变大,这和孔的大小有关。一般得后处理一下。由于我的材料一直是PLA的,所以试过用钻枪扩孔,但是效果不好,钻头会卡在洞里面。另外要注意有些模型如果提供了细杆之内的,强度一般都不会够,对于PLA很容易就折断了。

完全插不进去的外壳,其中一个装齿轮的细杆已经折断

打印模型的时候的方向也比较重要,要看你的模型在什么方向上需要什么的精度。Z方向的精度似乎比较差,XY的还比较靠谱。对于一些比较尖的部件,如果到最后只有这个尖的东东,则打印头会持续的在附近一栋,造成温度很高,下层的尖会软化,导致整个模型报废。所以可以在旁边比较远的地方放一个无关紧要的物件,这样打印头会移动开,等再回来的时候就已经冷却了。

翘边问题

刚拿到打印的时候,基本上都会翘边,还是PLA材料啊。后来打电话给售后问有没有比较好的办法,他们推荐用3M胶带。但是3M胶带实在是太难贴了,而且贴完了打印后会影响底层的平整度。如果贴的位置不是很恰当,还是会造成一些翘边,甚至中间凹陷的情况。

3M胶没有hold住,很难知道哪些地方需要贴
3M胶,造成底部凹凸不平

后来买了蓝色的3M美纹纸胶带,完美解决问题。非常好贴,而且效果很好。
美纹胶,完美解决
儿子很喜欢

打印软件

ReplicateG

这个开源软件很古老了,已经停止更新。试过一两个模型速度都非常的慢,而且界面不好用。还是最好别用这个了。

MPrint

MBot3D自己出的软件,易用性还算过得去,生成速度也挺快的,能够预览生成的路径,看到打印时间和材料克数。win平台和mac都有。作为初学及简单的配置还是很方便的。

不方便的地方在于没有像Slic3r或者Cura提供的打印一个底层边界的功能(不是底垫哈),这样刚开始打印的时候打印后没有材料挤出,要等上几秒钟才连续出料,造成一部分底层打印失败。办法是自己做个物体放在旁边,或者打印底垫。
Screen Shot 2015 04 22 At 12.24.17 PM

Slic3r和Cura

开源利器,两个软件不相上下,我还是比较喜欢Cura,界面比较好用一些。

刚开始用的时候,需要设置好边界,mbot cube我最大设置为200左右,太大的话会造成XY移动到最外面撞到。打印机是没有限位开关的,所以会导致电机堵转或者跳齿,很伤机械。还有一个Machine Settings选项:Machine Center 0,0,如果没有设置,则会按照左上角为0,0,会撞车。

0,0
具体设置可以参考:https://github.com/derekhe-3dprinting/print-settings

材料

当时买机器的时候给了一卷透明的PLA,但似乎材料有些问题,打印效果不好,比较粗糙。后来买了个橘红色的PLA,就好了。

PLA还是比较脆的,有一些玻璃的质感。橘红色的打印出来还是比较好看,但是透明的就完全瞎火。
比较漂亮
修锁扣,强度还是不错
透明的很难看

上色

最安全的方式上色还是用丙烯材料好了,需要涂得比较厚一些后期才不会开裂和掉色。可以借助吹风机速干。
涂的太薄,干了就掉

吐槽打印机

这个打印机价格还是不便宜,要是双头的价格都5200多了。打印的噪音还是比较大,关了门还能听得到明显的噪音。可能是出厂的时候质量有一些问题,Y轴似乎是直线轴承出了问题,方向移动的时候嘎嘎嘎的响。联系的厂商给免费维修,只不过要寄回去比较麻烦。

为了减少噪音,是否需要在外面加一层盖子,这个我还在考虑之中,看轴承修好了以后会不会好一些。

对比Flashforge的creator pro,这个机子的底板能够能够取下板子比较好,毕竟在机器里面拆模型不是非常的方便,贴胶也不好贴。

 

本文转自:http://www.april1985.com/2015/03/25/2015-03-25-3d-printing/

Share

2015.5 技术雷达 | 平台篇

   点击这里可以下载最新中文版本PDF

Apache Spark(spark.apache.org)作为一种快速和通用的大规模数据处理引擎已取得稳步进展。该引擎基于Scala实现,非常适合于那些在多并行操作之间重用数据工作集的应用程序。它即可以作为一个独立集群,也可以作为Hadoop的YARN集群的一部分来工作。它可以从不同的源来访问数据,比如 HDFS,Cassandra,S3 等。不仅如此,Spark还提供了许多更高级的操作符,以便简化数据并行应用程序的开发。作为一种通用的数据处理平台,它使许多更高级别的工具的开发成为可能,如交互式SQL(Spark SQL),实时流媒体(Spark Streaming),机器学习库(MLib),R-on-Spark等。

一段时间以来,Hadoop 社区一直在尝试把低延迟和交互式 SQL 查询能力带到Hadoop平台中(称为SQL-on-Hapdoop)。开源数据库引擎 Cloudera Impala,Apache Drill 和 Facebook的 Presto 都在2014年应运而生。我们认为,SQL-on-Hadoop 这一趋势标志着一个重要的转折,它将 Hadoop 的定位从与数据库互补的批处理,转变为某种可以与之竞争的技术。

Cloudera Impala(cloudera.com/content/cloudera/en/ products-and-services/cdh/impala.html)是早期的SQL-on-Hadoop 平台之一。它是一个基于C++的,支持大规模并行处理的分布式查询引擎。Impala 守护进程是这个平台的核心组件,其负责协调 Impala 集群中跨一个或多个节点间 SQL 查询的执行。 Impala 充分利用了 Hive 的元数据目录来共享两者的数据库和表。Impala 还提供了命令行工具以及 JDBC 和 ODBC 驱动程序供应用程序使用。

密码仍然是一种糟糕的用户认证机制。近来我们看到有公司(如Yahoo!)采用了“无密码”的解决方案——每当你需要从一个新的浏览器登录时,一个一次性验证码会被发送到你的手机来进行认证。如果你仍在使用密码认证,我们推荐您采用能够显著提高安全性的双阶段认证(two-factor authentication)机制。基于时间的一次性密码算法(TOTP)(en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm)是目前这个领域的标准,在 Google(play.google.com/store/apps/details?id=com.google.android.apps.authenticator2)和 Microsoft(windowsphone.com/en-us/store/app/authenticator/e7994dbc-2336- 4950-91ba-ca22d653759b)智能手机中都这样免费的认证应用。

Apache Kylin (kylin.io),是一个来自 eBay 公司的开源数据分析解决方案,它能够在超大数据集上进行基于 SQL 的多维度分析(OLAP)。Kylin 旨在构建一个基于 Hadoop 的混合 OLAP (HOLAP) 解决方案,最终将能够支持 MOLAP 和 ROLAP 风格的多维分析。你可以使用 Kylin 所提供的立方体设计器来定义立方体,并启动一个离线进程来构建它们。离线进程会进行一个预连接的步骤,将事实表和维度表连接到一个扁平化的结构中。下一个是预聚合阶段,各个单独的立方体被 Map Reduce 任务会构建出来。其结果被存储在 HDFS 序列文件中,之后被载入 HBase 。数据请求可以由基于 SQL 的工具提交 SQL 产生。查询引擎(基于 Apache Calcite)会决定目标数据集是否在 HBase 中存在。如果存在,该引擎会直接访问 HBase 中的目标数据,以次秒级延迟返回结果。如果目标数据集不存在,该引擎会将这些查询转向 Hive(或者是集群中任何其它可以用 SQL 查询 Hadoop 的方案)。

CoreCLR (github.com/dotnet/coreclr) 和 CoreFX (github.com/dotnet/corefx) 是 .NET 的核心平台和框架。虽然算不上是什么新闻,他们最近被微软开源了。一个主要的变化是这些依赖是基于二进制文件来部署的,不再需要事先安装在机器上。这使得并行部署变得容易,允许应用程序可以无冲突的使用不同版本的 .NET 框架。你可以安装 .NET 依赖到任何环境中,基于 .NET 编写代码成为了一个实现细节。从外部依赖的角度来看,一个用.NET实现的工具与用 C 语言编写的东西并没有什么不同,这就使它成为编写通用应用程序和工具的一个更有吸引力的选择。CoreFX 也已被分解为独立的 NuGet 依赖,从而使应用能够按需使用,这让 .NET 的应用和库占的空间的更小,并使得替换部分框架更加容易。

Heroku 用它的12要素应用模型改变了我们关于构建、部署、托管 Web 应用的方式。Deis (deis.io) 将 Heroku PaaS 模型封装到一个开源框架中,部署在可被托管在任何地方的 Docker 容器中。Deis 仍在进化当中,但对于那些符合12要素模型的应用来说,它具备大大简化部署,并在你自选的环境中进行托管的潜力。Deis 也已成为 Docker 周边丰富的平台和工具生态系统中的又一鲜活事例。

预测分析在越来越多的产品中被使用,而且通常出现在面向最终用户的功能上。H2O (docs.0xdata.com) 是一套非常有意思的新开源工具包(其背后是一家创业公司),因为其易用的用户界面设计,使得预测分析对项目组更可用。同时它还集成了数据科学家最喜欢的一些工具:R 和 Python 语言,以及 Hadoop 和 Spark。H2O提供了很高的性能,并且依我们的经验,非常易于在运行时集成,特别是在基于 Java 虚拟机的平台上。

当 Oracle 决定停止对 Sun 公司的 OpenSSO(一个开源的访问管理平台)进行开发时,ForgeRock 决定接管它并将它集成进他们的 Open Identity Suite 中。现在它被命名为 OpenAM (forgerock.com/ products/open-identity-stack/openam) ,成为了一个支撑 OpenID 连接和 SAML 2.0的可扩展的开放源码平台。不过,由于 OpenAM 历史悠久,导致它的代码库很庞大,并且文档也很难理解。希望在不久后,一个更轻量级的,对自动化部署和配置提供更好支持的替代方案将会出现。

Spark 是基于云的互联设备全栈解决方案,Spark Photon 是一个带 wifi 模块的微控制器,而 Spark electron 是连接到移动网络的变体。Spark 操作系统为这些设备添加了 REST API 服务。这套解决方案降低了进入物联网,并构建你自己的可连接设备的门槛。

时间序列数据库(TSDB)是一种针对时间序列数据的处理做了优化的系统。它允许用户对各种以时间序列组织起来的数据库对象进行 CRUD 操作。同时它还可以在整个序列上执行统计计算。虽然时间序列数据库不是一个新的技术,但是我们还是在这些数据库应用中看到了一些新的热点,尤其是在物联网应用领域。在许多开源和商业平台(比如OpenTSDB, InfluxDB, Druid, BlueFloodDB 等等)的促进下,时间序列数据库技术发展迅猛。另外还值得一提的是,其中一些数据库产品还使用了类似 Cassandra 和 HBase 的分布式数据库作为他们的底层存储引擎。

容器技术,PhoenixServer 以及持续交付的崛起已经开始让我们摆脱昔日部署 Web 应用的方式。传统方式是我们需要构建出应用工件,然后将工件安装到应用服务器中。这种方式会导致较长的反馈周期,构建时间的变长,以及在生产环境中管理这些应用服务器的开销变大。除此之外,这些应用服务器也很难做自动化。在与我们一同工作的很多团队中,开始倾向于将 HTTP 服务器嵌入到应用中。有很多可以选择的嵌入式服务器:Jetty, SimpleWeb, Webbit 和 Owin 等。更容易做自动化,更容易做部署,对基础设施的投入也会减少,因此我们推荐在未来的项目中使用嵌入式的应用服务器而不是传统的应用服务器。

Google 从2009年开发了一个实验性质的协议 SPDY (chromium.org/spdy/spdy-whitepaper),作为一个替代协议,它用于解决 HTTP/1.1中的一些性能短板。新的 HTTP/2 标准协议包含了很多 SPDY 中性能优化的关键特性,Google 已经宣布从2016年初就会停止在浏览器中支持 SPDY。因此,如果你的应用需要 SPDY 中的特性,我们推荐你去尝试 HTTP/2。

点击这里可以下载最新中文版本PDF

Share

敏捷咨询日记——消除浪费

waste

当我们追根溯源敏捷最先被发明的初期,可以发现,敏捷所消除的便是因为频繁业务需求改变带来的潜在浪费,而一切关于杜绝浪费话题到最后,都变成为对价值的纯粹追求。任何商业模式都基于创造新用户和挽留老用户,最终也被细化为为新用户提供不可替代的新价值和为老用户提供持续改进的旧价值(当然同样可为新价值)那么两件事情被认为是杜绝浪费最重要的两个方面:

  • 只给客户想要的;
  • 让客户简单地用到他们想要的;

简而言之,做了没用的和没用已经做了的是最普遍的两种浪费。二者间的关系是:做了没用的往往的结果是未使用,但未使用往往不止是因为没有用(也许你不够好)。

一个简单的对话可能会揭示这个道理。gigix在贴卡片的时候使用了没有ThoughtWorks logo那一面,我问:用反面的价值是什么?gigix说:我顺手写在了反面。我说:那你就把 logo marketing的价值浪费了。gigix便马上在正面重写。可以看出,在卡片的正面印上公司标志是一件具有市场推广和提高品牌认知价值的事情,我们也同意这种价值是实际需要,但是有50%的情况我们可能会忽略这个价值,于是,这个价值便被浪费了。

据说这个卡片的成本是两毛钱,而印刷logo的成本可能是1毛钱(印logo的唯一价值就是展示出来,于是不展示出来的浪费就是100%),每年全球范围内整个公司的卡片消耗量估计有51万张(一个人一年大概消耗300张,一年就是300X1700=510000张)于是理论上每年因为没有展示公司logo造成的浪费就是25500元。

解决这个办法有两个,长期的,如果每个TWer都有一种价值驱动的自然反应,把浪费扩展到日常生活中去,这个价值被浪费的几率可能减少;短期的,两面都印logo的成本理论上比一面印一面不印还要低,而当两面都有的时候,这种浪费便不可能发生,甚至成本更低。

这就是为什么用户体验被拔高到一个很高的地步,良好的用户体验可以更容易地把有用的价值传递到用户使用过程中,而很可能,往往被忽视,这是一个投入低于可能产生的价值浪费的过程。

敏捷当中关于杜绝浪费的阐述,绝对不应该只是个适用于软件开发(或精益制造)的概念,它应该贯彻到所有日常管理开发的过程中。有时候,我会刨根问底地询问某个内部管理表格上某行小字表述的意思,或者某个状态图中某个多余标签颜色的目的,甚至关于饮水机摆放位置的斟酌。

当各种询问进行之后,你会惊奇地发现,这样的价值最后一定被认为阻塞在一个更高级阶层人物的脑中,而所有人要做的只是忍受一次便接受这种浪费。而这样的现象成为一种奇特的人类自适应习性,特别是在一个具有组织结构的环境里,人们不加思索地游走忍受各种浪费,或者说有意识的拿出可能百分之一的生命作为浪费,而不去质问这个所谓深藏在高阶人士脑中的某个模式。而更神奇的是,这样的组织结构似乎就是为了种容忍浪费的习性提供养料,他们用权威语言(community language)描述这种可能产生浪费的活动,用意识形态的方式提高质问的门槛,他们用一种容忍浪费的高明手段来杜绝“浪费”,这种“浪费”被理解为更多的投入,或者改变,或者干脆就是自己权重更大的时间。

更深层次讨论这个问题这样的浪费被打造成一种十分有效的管理手段,因为我们的文化里,当你不懂我的时候,浅意识里我高过你,当你懂我的时候,你可能高过我,换言之,阻塞价值传递带来的心理慰籍多于价值广达于人。于是,如同状元可当驸马入赘皇族给天下清苦寒士打一针鸡血一样,这种“你不必懂,你只需做”的潜台词,成为底层工作者努力上进的“状元奖品”。同时,不可避免的是,各种浪费在这庞大的机器里不停被产生,讽刺地是,某种意义来说这样的浪费便成了机器运转的润滑剂,我们的发展不也是基于更庞大的物质浪费吗?

或许,我说到了最苦恼的地方,我努力尝试把敏捷方法跳出制造业(基于流程的软件业也是一种制造)而更多地作为一种现代企业管理方法论引入企业日常管理当中去,而似乎,敏捷原则的桎梏在于对人的依赖,以及是不是还有权威与非权威的概念,回到刚才的例子,如何保证所有质问的价值都是低于浪费本身的-万一大部分人的质问都是无理取闹?权威“不必问,只需做”的方式是不是本身也是一种杜绝浪费?

就此来看,敏捷方法还有很多值得思考的东西,但杜绝浪费初衷本身是值得肯定的。

本文转载自:

Share