Monday, October 27, 2014

云计算时代应用设计十二要素

云计算时代应用设计十二要素

  • 什么样的软件才是可用性和可维护性好的软件?
  • 什么样的代码才能避免后续开发的上手障碍?
  • 什么样的实行才能稳定的运行在分布式的环境中?
Heroku (一家 PaaS 服务提供者,2010 年被 Salesforce 收购)平台创始人 Adam Winggins 提出了推荐的应用十二风格,对我们设计和实现云时代(特别是 PaaS 和 SaaS 上)高效的应用都有很好的参考意义。

代码

每个子系统都用一个代码库管理,使用版本管理,实现独立的部署。

依赖

显式声明依赖,通过环境来严格隔离不同依赖。

配置

在环境变量中保存配置信息,而避免放在源码或配置文件中。

后端服务

后端服务作为可挂载资源来使用,这样系统跟外部依赖尽量松耦合。

生命周期

区分不同声明周期的运行环境,包括创建、发布、部署,各个步骤要相互隔离。

进程

以一个或多个无状态的进程来运行应用,即尽量实现无状态,不要在进程中保存数据。

端口

通过端口绑定来对外提供服务。

并发

通过进程控制来扩展,即以多进程模型进行扩展。

可丢弃性

快速启动,优雅关闭,并尽量鲁棒(随时 kill,随时 crash)。

开发与生产环境的差异性

尽量保持从开发到生产部署环境的相似性。

日志

将日志当作事件流来进行统一的管理和维护(使用 Logstash 等工具)。

管理

将管理作为一次性的系统服务来使用。

Friday, October 17, 2014

Docker 1.3 发布


Docker 1.3 已经正式发布,新的特性包括镜像签名、进程注入、新的创建和运行容器命令、安全选项和 Mac OS 上进行目录共享。特别是针对安全方面的改进,成为本地发布的亮点。
镜像签名
支持对镜像的发布者和镜像文件进行验证。
进程注入
除了通过 nsinit 和 nsenter 的方式查看容器内应用之外,可以使用更方便的 docker exec 命令。这将给容器 debug 带来便利。
例如 
$ docker exec ubuntu_bash -it bash 
会在 ubuntu_bash 容器中运行 bash 命令。
新的创建和运行容器命令 create 和 start
传统的 docker run 会创建容器并运行它,现在可以通过 create 和 start 进行细粒度的控制。 
例如,先创建一个容器(并不处于运行态): 
$ docker create -t -i fedora bash 6d8af538ec541dd581ebc2a24153a28329acb5268abe5ef868c1f1a261221752 
然后,让它运行: 
$ docker start -a -i 6d8af538ec5 
bash-4.2#

安全选项
在运行容器的时候通过 --security-opt 选项来指定系统的安全选项,包括 SELinux 和 AppArmor 的标签等。 例如 
$ docker run --security-opt label:type:svirt_apache -i -t centos \ bash 
这个功能将大量减少使用 --privileged,从而提高使用容器的安全性。
Mac OS X 上的共享目录 
基于 boot2docker,支持在本地 Mac 系统和容器之间直接共享目录 例如, 
$ docker run -v /Users/bob/myapp/src:/src [...] 
将直接挂在本地的/Users/bob/myapp/src 目录到容器内。
更多改进,参考 https://github.com/docker/docker/issues?q=milestone%3A1.3.0。

Thursday, October 09, 2014

也谈并发和并行

并发(concurrency)和并行(parallelism)都是常见的概念,并且很多时候并不容易进行区分,甚至被用作表达同样的概念。
网上最流行的解释,并发是一个人吃三个馒头;并行是三个人吃三个馒头。
这样理解简单概况了主要区别,但其实并不是太完整。

从对象的角度,并发是一种任务分配模式,指的是同一个处理器被调度处理不同的任务,这些任务往往都是同一性质的任务。例如浏览器打开多个页面,浏览器自身虽然是单进程的,但是它可以(一般都使用多线程方式)轮流打开页面,也可以打开一个页面一半后跑去打开另外一个页面,然后再回来。

而并行是一种运行的方式,指的是多个处理器同时处理若干个任务,这些任务往往是不同的任务。例如多核系统,一个核上正在处理视频渲染,另外一个核同时处理了网络收发包。强调同时性和多处理者。

从架构设计上看,使用并发主要是因为处理资源有限,而多个任务往往存在block情况(例如io block),可以通过适合的调度来隐藏任务的block,即降低响应延迟。
而并行则往往是因为处理资源比较多(多核),通过同时运行多个任务来充分利用资源,提高整体的吞吐量。现在的大数据运算平台如hadoop等就是典型的并行的概念。

因此,某些场合下,两者可以结合使用,以提高系统整体的性能。这是很考验架构师的地方。

网络虚拟化基础协议之Geneve

网络虚拟化最基础的技术莫过于分层(Overlay、Underlay),要实现分层有两种手段,一个是映射(Mapping),一个是封装(Encapsulation)。


映射,主要思路是转发时替换报文语义,如何替换将需要设备进行查询。
封装,则是把需要的报文语义添加到网包中,处理的时候一层层的解封装即可,尽量对设备透明。


不少协议都实现了封装的部分或完整功能,包括IP-in-IP、Vlan、MPLS、VXLAN、NVGRE、STT等。这些协议各有各的特点,不少都是为了简单地隔离或者通过隧道连通不同网络。特别是后面几种,设计理念大同小异,只是实现细节不同。


对通用的封装协议标准的需求已经越来越强烈,于是有了Geneve: Generic Network Virtualization Encapsulation。


Geneve的出发点是解决封装时候添加的metadata信息问题(到底多少位,该怎么用),尝试适应各种虚拟化场景,Underlay的协议是最通用的IP协议(准确的说是UDP)。


跟大部分的封装协议类似,实现Geneve一般需要两类设备:隧道终端(tunnel endpoints)和传输设备(transit devices)。前者用来处理封装头终止隧道,后者则是非必需的,通常是支持IP转发的设备。


具体来看Geneve的封装帧,从外到里依次是
外层以太头
外层IP头(V4或V6)
外层UDP头
Geneve头(变长)
内层以太头
Payload
外层以太头的FCS


其中UDP的目标端口默认是IANA分配的6081,并且支持可配置。UDP的校验和必须计算正确,也可配置为0。


Geneve支持单播、多播和广播。