给互联网圈子的朋友们介绍下运营商网络

按:事情从“微信收费”一说起来的,看到Shell发了一篇blog,深感电信和互联网两个领域互相不知根知底啊,作为前兼职3G讲师,来简单介绍一点吧。首先,这篇blog和微信一事的关系仅限于此段,我个人认为这纯粹是某公司的炒作,看了移动的宁宇的博客,我更确信这一判断;其次,这篇文章不涉及所有运营商网络,运营商网络各有不同,我主要说说我更熟悉的移动网领域,尤其是 GSM/GPRS/EDGE/WCDMA(部分地包含TD),如果没有特殊说明,不包含固化网和CDMA/CDMA2000。嗯,这么说明严谨了吧,呵呵。

另外,其实从领域说,一般叫电信网,我怕大家和中国电信混了,所以改说运营商网络,下文凡是提到电信网,而不是中国电信的,泛指全球电信运营商的网络,而非中国电信。另外,全球电信运营商如一丘之貉,对比看,其实中国的也不过分,所以,骂的时候不必对比啊。

运营商网络是什么样的

从大面上说,电信网络分为三大部分:接入网、交换网和传送网。从大家的终端设备,到电信网络的交换机,这是接入网,选择目的地,进行电话交换的那个是交换网,长途传输的是传送网。从传输的内容看,还要分成数据平面和控制平面,控制信令(signaling)的传输一般是走专用的信令网的,比如著名的7号信令系统(SS7),以及为了在IP上承载信令网而搞的SCTP……

继续,传统地说,固话的接入网是从各位的家里一直到交换机的那根双绞线,这对线是独享的,电话56Kbps,DSL可以超过8Mbps,都是用的这一对线,除非别人盗用,否则这对线是你独享的,线路质量越好,你能达到的DSL速度也越高,当然,这是接入速度,端到端速度还有很多制约因素,这个大家都懂。

但无线网络有一点不同,没有电话线区分开大家,所以,大家是共享同一个“信号空间”的,这个空间由时间、频率、空间以及功率组成,毫无疑问,共享信道系统的资源总是很紧张。

历史上,让无线/移动通信第一次成为公众可以使用的服务,就来自于对空间的划分。无线信号总是会衰减的,而且衰减的很快,所以,把上述“信号空间”中的“空间”提取出来,将地面划分为很多蜂窝状的小块,相邻小区的其他信号空间要素不同,同样要素相邻一段再重新使用,互相的干扰会接近忽略,这样,就把资源的利用率极大提高了,于是,人人都可以用手机了。这也就是为什么移动网络又叫蜂窝网络了。顺便说一句,中国移动的LOGO就是一个蜂窝的形状,多数人应该看不出来,呵呵,反正中国移动员工知道这个的都不多,呵呵。

但是,划分小区不是没有代价的,系统需要知道你在哪个小区,才能和你通信,尤其有了终端耗电和节省信号空间的资源约束,移动网络的控制开销是比固定网络大的(包括网络结构上的开销和信令传输量的开销),小区越多,用户移动产生切换的概率就越高,随之而来的消耗就越高,所以1G-4G的在接入网演进的重点就在于频谱利用率的提高。各位可能觉得不移动就不需要有这些开销了,实际也是不准确的,网络需要知道用户的状态,来在有通信的时候找到用户,所以,即使是没有移动,也会在小时级的时间内(一般是2小时左右吧),进行周期性位置更新。所以,大家抠掉电池之后(神马?iPhone用户抠不掉?可以扔到水里啊),拨打它,首先是无法接通(或不在服务区),过一两个小时再播,就是“已关机”,因为它没有定时汇报。

微信带来的开销有可能和长时间连接带来的更多小区重选、位置更新有关,我不确定,但我认为核心问题是,网络是按照旧业务规划的,不适应新应用的新用法,移动希望双方合作,共同优化,这是一个合理的提议,收费的说法,我觉得炒作成分很大。

为什么会有电话网和数据网

Shell表示,他完全无法理解,在VoIP技术如此成熟的今天,为什么运营商还死抱着电路交换不放。实际上,简单地说,现在运营商的电话网全都是“软交换”(Soft switch)网络,就是一种VoIP技术,也靠这项技术节约了不少成本,大家电话资费的下降,和上面说的频谱利用率提高以及软交换的使用都密不可分,话说,要不是技术提高节约成本了,运营商会发善心,出让利润,给咱们省电话费么。不过,细说起来,电话网和数据网仍然不是一个网络,至少要到4G的核心网技术非常成熟的时候,才会逐渐统一起来。

在GSM的时代,用户的电话是占用一条专用链路的(电路交换称为CS),当然,电话本身就是双向实时传输的这不算浪费。但如果用来上网就比较浪费了,大家连上网,一般不会不停上传下载,占满线速,所以,虽然GSM电路交换体制下,有高速(其实也不快,跟3G差远了)数据的支持(HSCSD),但太浪费资源,不会有运营商采用的。运营商采用的方式是,小区基站那里不懂,叠加一张数据专用的交换网络让用户看起来一直在,但是只有在传送数据的时候裁占据资源,这个就是GPRS。因为GPRS是后加入的,GPRS和GSM 是几乎两张独立的网络,它们分别要管理各自用户的接入状态等,比如位置更新系统就有两套,因为GPRS同时有通信的用户远比电话网多,所以,为了控制信令规模,它的位置更新机制要更细一些,所以,网络的一直在线,比电话的一直在线开销高,这个不是扯淡,是真的。

这个CS/PS彼此独立,从GSM/GPRS开始,到3G仍是如此,EDGE只是提高了频谱利用率,3G(确切说是R4以后)进一步提高了频谱利用率,并在核心网引入了软交换,但一方面为了向前兼容,一方面为了在低资源消耗的情况下保障语音和视频电话网络的QoS,电路和是分组交换网一直是分离的,在未来4G的时代,趋势是两者统一,但短时间内,还是彼此独立的。

至于为什么IP电话还要加拨前缀,我得说,其实电话都是IP的,只是有些更IP一些—— 有质量保障上面的差异,当然也有纯营销手段在里面,大家都是做技术的,但技术和商品名之间的不同,应该还是可以理解的吧。

后记

嗯,不在电信网络圈子很多年了,这些东西不一定非常确切,也不算是中立立场,仅供互联网圈子的朋友们参考下吧。

from 我有分寸: http://wangxu.me/blog/p/767

再次改动了 tornado-memcache

在上次(http://wangxu.me/blog/p/758)之后,再次改动了 tornado-memcache 模块,commit 信息如下:

Add gets method and simplify connection estabilish

- simplify connection estabilish procedure, as tornado.iostream
  permit write before connection estabilished, I removed the
  callback and connection timeout procedure in _get_server()
- add `gets(self, keys, callback, failcallback)` method, receive
  a list of keys as parameter and return a dictionary of results
  result = {key1:value1, key2:value2...}, only return the got
  keys from memcached
- some debug info, might be cleanup later

Signed-off-by: Wang Xu <gnawux……

简单地说就是两件事情:

  • 读了文档,发现 tornado 的 iostream 允许在连接建立未完成的时候就write,既然我之前已经用 iostream 管理 socket 了,这里就省掉上次在这里加上的callback 和 timeout,直接 write command,等 write 的超时或返回就好了;
  • 读了memcached 协议,发现取信息(get),是支持一次取多条信息的,于是加入了这个支持,这样,批处理操作时会提高不少效率。

里面还插入了好多调试的时候的 debug 信息,差不多都注掉了,回头都稳定了再清理一下。

嗯,代码都在 github 了:https://github.com/gnawux/tornado-memcache

from 我有分寸: http://wangxu.me/blog/p/764

Tornado 的 stack context

按:本人 python 菜鸟,对 tornado 更没什么研究,这两天小摆弄了一下,记一下,有不对的还请指正

这两天在用 tornado 做一个 memcached 的 proxy,作为一个 Python 的高性能异步框架,tornado (实际是 epoll/kqueue… )的思想是——单线程+异步化,线程的运行时间不等待任何东西,这样就要求 memcached 的访问也必须异步化。如果线程在等待中消耗了,就无法达到高并发的目的,这个问题是无法通过简单地交给线程池或什么其他东西来达到的。

于是,这里就不能用常用的 python-memcache 来做了,实际上有几个基于 tornado 的 memcache 客户端,这个是维护得相对好的一个,也是一年前的了,而且,有两个问题:

  • 连接建立是同步的,不是异步的
  • 没有超时机制

这样,在 server 或网络出现问题的时候,就可能遇到大麻烦,所以,我的目的就是绞尽脑汁加入超时机制,这个初步做出来了,等把 get 之外的方法也都异步化之后就反馈出来。这里主要依赖的机制就是 tornado 的 stack context——再次声明,我是这个方面的菜鸟,有什么不对的地方大家嘘之余给指出来呗。

Stack context 的意图就是为执行程序保存一个上下文,在需要的时候,可以回到这个上下文执行,包括异常,都可以更好地、统一地处理。这个功能的代码不是很多,也比较清晰,但是文档……嗯,至少我是没看明白,结合 httpclient 的源码作为例子,加上看 stack_context 的代码,大概明白了是怎么用了。

首先,在希望抓住问题的入口的地方要留住上下文:

        #......
        context = partial(self._cleanup, fail_callback = fail_callback)
        with stack_context.StackContext(context):
            getattr(c, cmd)(*args, **kwargs)

这里,后面的执行内容,包括回调、触发事件,都可以通过抛出异常退到这里,而管理异常的就是 context,这里,用 functools.partial 包装了一下 _cleanup,_cleanup 的写法大致是这样的:

    @contextlib.contextmanager
    def _cleanup(self, fail_callback = None):
        try:
            yield
        except _Error as e:
            print "gotcha", e
            if fail_callback:
                fail_callback(e.args)

这里,异常会被捕获,并调用用户指定的出错回调函数进行处理。后面的代码里,遇到故障,抛出异常就可以了,比如,可以用这个异常来返回超时:

    def _on_timeout(self, server):
        self._timeout = None
        server.mark_dead('Time out')
        raise _Error('memcache call timeout')

这个异常是通过 io_loop 的 timeout 方法来触发的:

            self._timeout = self.io_loop.add_timeout(
                    time.time() + self.request_timeout,
                    stack_context.wrap(partial(self._on_timeout, server)))

这样,就可以在异步程序里比较干净地处理掉超时问题了。

这个代码对我这个水平的初学者还是比较晦涩的,大家可以参考下 HTTPClient 的源码,等我把这个 memcached client 的代码改完之后,也会放出来供参考指正的。

from 我有分寸: http://wangxu.me/blog/p/758

一点expect心得

最近用了几下 expect,  记几个心得,以备不时之需

循环式匹配: exp_continue

expect 的匹配可以看做是一个循环,通常匹配之后都会退出语句,但如果有 exp_continue 则可以不断循环匹配,输入多条命令

expect{
    "$passprompt"    { send "$password"; exp_continue }
    "$prompt" {send "$c\r"}
}

在这个例子里,遇到密码提示的时候,送出密码,然后继续 expect,遇到命令提示,送出命令,然后退出 expect,当然,可以做得更复杂,一条一条送命令,送没了再退出。这样,expect 的结构会比较漂亮,而且容易扩展。

正则匹配: -re

作为一种 tcl 的分支,expect 支持 tcl 的正则表达式,正则表达式这里就不多说了,正则匹配的一个重要用途是,对多个匹配关键字进行相同的操作,比如

expect {
    -re "$prompt|$rootprompt" { send "$c\r" }
}

这里是对普通用户的提示和root用户的提示进行同样的操作。

利用PS1环境变量

在 expect 里,根据程序的返回状态做操作不是件容易事,很多做法都不是十分干净,我的一个方法是,根据 $? 的值设置 PS1 环境变量,这样,下一次出现的 Shell 提示就不是之前的提示了,只要特别 expect 这个提示,进行操作就行了。

嗯,这算是个野路子,不正规哈,欢迎指正。

抓取远程的输出到本地:expect_out 和 full_buffer

我们经常需要抓取远程的输出,这时,可以借助 expect_out 来抓取两次 expect 之间的内容,它有两个用法:

  • expect_out(buffer) 这个直接抓取两次 expect 之间的全部 buffer
  • expect_out(1,buffer) 这个抓取正则匹配的部分

后者这里不多说了,前者有个问题,就是当两条命令之间输出很多时,可能 buffer 会满,在这种情况下,expect_out(buffer) 不是全部的 buffer 内容,而是最后的,这时要靠 full_buffer 帮助了,这里举个例子

set result ""
expect {
    "$prompt" {
        append result $expect_out(buffer)
        puts stderr $result
        set result ""
        send "$newcmd"
        exp_continue 
    }
    full_buffer {
        append result $expect_out(buffer)
        exp_continue
    }
}

这时个示例,注意 full_buffer 是特殊匹配事件,类似 timeout,不是字符串。

嗯,暂时记这些吧。

from 我有分寸: http://wangxu.me/blog/p/752

一点expect心得

最近用了几下 expect,  记几个心得,以备不时之需

循环式匹配: exp_continue

expect 的匹配可以看做是一个循环,通常匹配之后都会退出语句,但如果有 exp_continue 则可以不断循环匹配,输入多条命令

expect{
    "$passprompt"    { send "$password"; exp_continue }
    "$prompt" {send "$c\r"}
}

在这个例子里,遇到密码提示的时候,送出密码,然后继续 expect,遇到命令提示,送出命令,然后退出 expect,当然,可以做得更复杂,一条一条送命令,送没了再退出。这样,expect 的结构会比较漂亮,而且容易扩展。

正则匹配: -re

作为一种 tcl 的分支,expect 支持 tcl 的正则表达式,正则表达式这里就不多说了,正则匹配的一个重要用途是,对多个匹配关键字进行相同的操作,比如

expect {
    -re "$prompt|$rootprompt" { send "$c\r" }
}

这里是对普通用户的提示和root用户的提示进行同样的操作。

利用PS1环境变量

在 expect 里,根据程序的返回状态做操作不是件容易事,很多做法都不是十分干净,我的一个方法是,根据 $? 的值设置 PS1 环境变量,这样,下一次出现的 Shell 提示就不是之前的提示了,只要特别 expect 这个提示,进行操作就行了。

嗯,这算是个野路子,不正规哈,欢迎指正。

抓取远程的输出到本地:expect_out 和 full_buffer

我们经常需要抓取远程的输出,这时,可以借助 expect_out 来抓取两次 expect 之间的内容,它有两个用法:

  • expect_out(buffer) 这个直接抓取两次 expect 之间的全部 buffer
  • expect_out(1,buffer) 这个抓取正则匹配的部分

后者这里不多说了,前者有个问题,就是当两条命令之间输出很多时,可能 buffer 会满,在这种情况下,expect_out(buffer) 不是全部的 buffer 内容,而是最后的,这时要靠 full_buffer 帮助了,这里举个例子

set result ""
expect {
    "$prompt" {
        append result $expect_out(buffer)
        puts stderr $result
        set result ""
        send "$newcmd"
        exp_continue 
    }
    full_buffer {
        append result $expect_out(buffer)
        exp_continue
    }
}

这时个示例,注意 full_buffer 是特殊匹配事件,类似 timeout,不是字符串。

嗯,暂时记这些吧。

from 我有分寸: http://wangxu.me/blog/p/752

Mac 下用自定义脚本配置 Tunnelblick 的自定义路由

Mac下的 Tunnelblick 是个很好用的 openvpn 管理工具,嗯,这年月谁还没几个 VPN 啊,你懂的。

不过呢,总有一些路由希望不走 VPN,比如内网,又比如某些网站,话说原来是在 ovpn 配置文件里用 route 命令配置路由到 net_gateway 的,比如

route 192.168.0.0 255.255.0.0 net_gateway

不过,如果有多个VPN配置文件,要修改 IP 列表的时候就很麻烦,放在脚本里,集中起来保持同步才是好办法,根据 openvpn 的文档( https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage ),这是可以通过 up/down 或 route-up/route-pre-down 做到的,简单说一下,以 up 为例,配置文件要这么写

up "/path/to/your/up-script optional parameters"

之后,脚本里还会跟进一些 openvpn 送来的参数,比如设备名、mtu、本机和远端 ip 地址等,还有很多环境变量,我们要用的是 route_net_gateway ,这个是开 VPN 之前的缺省网关。

但是,这么放脚本之后,你会几乎无可置疑地发现脚本根本就没有运行,这个脚本并没有被执行,通过日志可以看出,原因在于——Tunnelblick 会用命令行加入它的自定义脚本,覆盖掉我们指定的,这样我们的就白写了。

根据 Tunnelblick 的文档(http://code.google.com/p/tunnelblick/wiki/cUsingScripts ),我们知道,这组脚本是用来获取/设置 DNS 的,只要在配置中选择不设置DNS,就可以执行我们的自定义脚本了。

但是,我们还是需要这组脚本运行的,我们可以替它调用这些脚本的,这样办法就来了——在配置文件里这么写:

up-restart
up "/Users/gnawux/bin/bypass-route.sh up"
down /Users/gnawux/bin/bypass-route.sh
route-pre-down "/Applications/Tunnelblick.app/Contents/Resources/client.route-pre-down.tunnelblick.sh -m -w -d -atADGNWradsgnw"

上面第二、三行是指定到我们的脚本,用一个参数区分up和down就可以了,第四行是 tunnelblick 的 route-pre-down 脚本,up和down脚本我们会通过我们自己的脚本来调用,脚本如下,注意最后调用了 tunnelblick 的脚本

#!/bin/bash

PREFIX=/Users/gnawux
LOGFILE=${PREFIX}/bin/route.log

echo "Cmd run on `date` with arguments: $@; Original Net Gateway: ${route_net_gateway}" > ${LOGFILE}

if [ $# -lt 6 ] ; then
	echo "[WARN] not enough arguments: $@" >> ${LOGFILE}
	exit 1
fi

OPERATION=delete
TB_SCRIPT=/Applications/Tunnelblick.app/Contents/Resources/client.down.tunnelblick.sh
if [ "$1" = "up" ] ; then
	OPERATION=add
	TB_SCRIPT=/Applications/Tunnelblick.app/Contents/Resources/client.up.tunnelblick.sh
fi

while read scope ; do
	echo /sbin/route ${OPERATION} -net ${scope} ${route_net_gateway} >> ${LOGFILE}
	/sbin/route ${OPERATION} -net ${scope} ${route_net_gateway} 2>> ${LOGFILE}
done <<ENDLIST
10.53.0.0/16
58.215.0.0/16
ENDLIST

exec bash ${TB_SCRIPT} -m -w -d -atADGNWradsgnw $@
#route-pre-down /Applications/Tunnelblick.app/Contents/Resources/client.route-pre-down.tunnelblick.sh -m -w -d -atADGNWradsgnw

中间的 IP 网段列表各位就自行选择吧,最后,别忘了给这个文件执行权限就好了。

 

from 我有分寸: http://wangxu.me/blog/p/746

十年

10年了,今天太阳升起的时候,我们将重新踏进母校的校门,不过这次没有挂科的压力了……不仅是成功校友,我们屌丝也可以找个黄道吉日回到母校,真是神奇啊。

在开始多愁善感的日志之前,我想问问我上铺的兄弟——张世谦:你还记得十四年前的九一八,你放在自己钱包里的那张纸条么?你还记得那一晚,我们军训宿舍里的那些散落一地的伤感么?

大学影响了每个人,即使不是成功人士,我也被位列“四大染缸”之首的母校改变了很多,不仅是老师,更是那些朝夕相处的同学们。在今天,回头看,我不知道自己是否在正确的路上,但知道,现在这条路的起点就是大学,确切地说是拿到工大录取通知书的一刻。

十八岁的生日,我拿到了大学的录取通知书,好吧,说点开心的,这是我第一次被自己填写在《志愿书》上的一个学校、一个专业接受了,即使它是第二行。这太神奇了,之前的两次,我都是靠“服从调剂”那个勾来摇奖决定未来三年的,这次毫无疑问是个巨大的成功。当然,回头看是如此的轻松,不过你只要问问曾经往钱包里塞纸条的张世谦,或者想想差点挂掉的陈峥宇,还有那个开学时还在学车的袁方就知道,那几天真的不好过,真的很漫长……

呃……重复失败不是什么让人开心的事,对我这样的缺心眼儿也是如此,但还能怎么办呢?这么痛苦的一个大学的开始,也在刺激我更深刻的自省(嗯,我们班居然有个同学叫申科,但我说的是深刻的自省,和这位隔壁的同学关系不太直接)。回头看看,我今天总结出来的一句话是——“做人是自己学的,不是别人教的”,之前的挫折不止是改变了我人生的轨迹,更让我开始努力去学习该怎么做人,我觉得这才是真正的财富。在整个大学期间,我做了几件让我回忆起来很满足的事情:

首先,是我在学习面对,是的,不再躲避、不再逃避,面对问题,接受问题,承认问题,同时学会的还有把所谓的“自尊”踩在脚下,当我开始颤抖着嘲笑自己的弱点的时候,我发现,我真的开始改变它、征服它了。真正的自尊不怕嘲解,真正的自信源于自我认知。面对、接受了自己的缺陷、不足、过错之后,我逐渐成长为一个强大而不要脸的屌丝了。

然后,我开始不断把自己推出自己的“安全区”,不断强迫自己面对挑战。在上大学之前,我从来都是反应慢+手笨+协调性不足的,可大学一开始我就强迫自己在各种实验课上到处出溜,到处乱捅乱动,我不知道当时的同学到底是怎么看这个手笨脸皮厚的家伙的,他们可能想看我出更多丑吧,居然说我动手能力强,在大一假期就把我扔到实验室去了,在这里还真觉得对不起张印春老师的实验室啊。后来,我觉得自己胆子小,不敢在大场面说话,还一有机会就把自己推上讲台去,颤颤巍巍地讲东西去,我不知道当时被我代表的同学们都什么心情,应该有不少人觉得自己上去会比我说得好多了吧。

再然后,我也想不起来了,我能记得的自己的变化大概就是这样一个趋势。在这些变化里,少不了老师和同学们对我的影响,我相信他们中的很多人可能都没有想到自己的那句话或那件事对我影响那么大,不过,这真的发生了,这里挑几个比较有代表性的:

  • 第一个影响就是第一任班长李学峰,他一开学就交了14页的思想汇报,从此我就和党组织绝缘了,我相信,写这样的思想报告的人和我,绝对不是一个组织的;
  • 还有一个是第一任班主任张延华,呃……这个是好事啊……我记得他第一次来我们宿舍——可能是唯一一次?至少是我记住的唯一一句话,他告诉我们,在宿舍里打牌是浪费时间的,没有意义的,从此,我们班的宿舍在开学的时候差不多从来没打过牌,当然了,那些打游戏的同学都出去打游戏了,那些上自习的同学都去自习室了,留下我这样的一两个,想打也打不起来啊;
  • 另一个影响就是几个四中的同学,他们彪悍的表现让我坚信,以后孩子要是能上四中就好了;
  • 还有堡哥和袁方啊,他们对数学的热爱和执着让我这个曾经在小学时候当过数学科代表的人不得不承认,人和人是有差距的,我真不是这块料;
  • 还有张世谦,他的很多言论都让我记到现在且深以为然,比如那个“自卑”理论,基本就是把一切性格或多或少缺陷的表现都认定是自卑的表现,我觉得这个基本可以解释一切,更重要的是,这个理论也在迫使我不断的自嘲啥的,以免被人发现我内心的自卑啊;
  • 还有那谁,他告诉我做人是不能这样的;
  • 还有头人,嗯,这个我们私下说啊。
  • ……

嗯,算了,就这么多吧。

其实呢,如果不说这是10年,一切都会这么继续过下去,生活一直在变,从没停下,可能再10年之后,我发现我写的这一切十分2B,也可能10年之后,咱成温拿了,会拼命掩饰,不让人看到这么落魄时对人生的吐槽。可是,我还是愿意,在今天把这一切记下来,这就是我的生活,我的心声。

from 我有分寸: http://wangxu.me/blog/p/743

Bash 的 Process Sub

Shell这东西,如果你真会用的话,你可能永远不敢说你会用。

前两天看了Process Sub,一种结合了管道和命令替换(command sub)的使用方式,非常有趣。

嗯,这得先说说命令替换,就是反引号或者 “$()”,非常好用,但是,你能把它当成文件用么,有点时候,你要把命令输出送给其他命令处理,而这个命令只是接受文件参数,无法用管道,或者,你要两个命令的输出,没法用管道,怎么办呢,process_sub 来啦,看这个:

diff -u <(grep "^5076" strace.log |sed -ne 's/.*futex(\(0x[0-9a-f]\+\),.*/\1/p' |sort|uniq) <(grep "^5061" strace.log |sed -ne 's/.*futex(\(0x[0-9a-f]\+\),.*/\1/p' |sort|uniq)

嗯,不解释了,自己理解哈。

Process sub 的另一种场合,下面这两个命令几乎是等价的,试图用个循环来做 wc 的工作:

while read x; do ((y++)); done < <(netstat -nr)

netstat -nr | while read x; do ((y++)); done

不留心很难看出差别,但是,如果这两条命令之前,先把 y 置空,那么,第一个命令之后,y是有值的,第二个则不会。这是因为,管道命令可以看作是

cmd1 | (cmd2)

也就是说,后面的命令是在子 shell 里运行的,因此,无法改动父 shell 的内部状态,而 process sub 方式运行的命令则没有这个问题。

嗯,则个很好玩,前两天刚看到的,参考了 TLDP 的 Advanced Bash-Scripting Guide 。

from 我有分寸: http://wangxu.me/blog/p/738

云计算中的持久化与安全性

按:此文准备投稿中

前几天,亚马逊的云服务(AWS)连续发生大规模服务中断,使得默默无闻的EBS(弹性块存储)服务再次被推上风口浪尖。实际上,过去一两年间,差不多所有AWS服务大规模中断,都可以听到EBS的叹息,难怪新浪的程辉兄说:“EBS仍然是公有云最大的难点和故障点”。

作为国内为数不多的,也大概是最早提供商用EBS服务的团队成员,我当即跳出来为EBS说了几句“公道话”,之后的图灵生日会上,和刘江老师聊天的过程中,他建议我把这些想法写出来,也让用户和相关产业了解,一个EBS服务的设计者是怎么看待自己这个“故障点”的。

首先说说我的总体观点,EBS是最后一道防线,所以重大故障才往往在EBS身上体现出来。只要存储不出问题,再大的问题也不容易造成长时间、大范围的停机,不论是网络还是计算,都是无状态的,有电、有链路就可以工作,而这些也是最容易通过冗余来保障可用性的;但存储则不同,对存储来说,数据正确是我们第一要保障的,如果真发生严重故障,我们不可以为用户迫切要求的可用性而冒险牺牲正确性。

系统设计的哲学:熔断器与冗余

没有系统能避免异常情况的出现,大系统的设计中,最复杂、最难处理的地方往往是不常遇到的意外(超负荷)情况,在这里经常用到的两种策略是熔断器和冗余——

  • 系统常常设计为可以承担远高于其标称值的负荷,从而在出现异常的情况下,也能持续工作,这是所谓服务能力的冗余
  • 对于另外一些情况,我们会采取一种看起来和服务可用性背道而驰的策略——停止服务,以避免更严重的损失,这个就类似于电子设备中的熔断器,或者叫保险丝。

这两种策略几乎总是同时用到的——对普通的困难,我们争取用设计上的冗余来克服,让它对用户透明。但是,当系统无法承受的时候,就需要果断地中断服务。什么情况下中断服务,总是设计者最为头痛的地方,他们不愿意让用户暴露自己脆弱的一面,但也不能背弃对用户的承诺——如果你无法保证数据的持久写入,就不能欺骗用户说数据你已经存储好了。

而没有程序是没有Bug的,这些最极端的情况,往往是设计实现者自己也最难以枚举的,他们的测试很难涵盖到类似的情况,于是,对于包容性比较好的存储系统设计,在这样的困境下,尽力保持现场地退出服务,让独立的运维程序,甚至是人工来介入,恢复服务状态是一种负责任的态度。对于亚马逊的EBS故障情况,我个人基本是这么理解的。

那么好了,我想,一定有人要问一个问题,既然EBS可能会造成这样的窘境,为什么一定需要这么一个服务呢。

让人又爱又恨的EBS服务

如果你想成为最好的云服务商,请做EBS服务,这是杀手服务;如果你想成为被人唾骂的云服务商,请做EBS服务,这是你的最大故障点。(改自《北京人在纽约》的经典台词)

亚马逊大多数的AMI(操作系统镜像)都放在EBS上,亚马逊很多虚拟机都用到了EBS服务,很多数据库都放在EBS磁盘上……亚马逊的EBS需要额外付费,亚马逊的EBS的性能并不稳定,甚至可以说亚马逊的EBS性能公认的不好……这一系列的事实同样是这么矛盾,一遍又一遍地问:为什么人们要用EBS服务呢?

  • EBS服务是便宜的——是的,单独额外付费的EBS反而可能是更便宜的,使用EBS作为操作系统镜像,这会让虚拟机在不需要工作的时候,可以处于stop状态,这个状态是不计费的;而且,使用EBS作为数据盘,可以在不需要计算的时候,销毁虚拟机实例,而在需要时在申请新的虚拟机,直接使用已有EBS上的数据。(后者盛大云已经提供,前者即将提供)
  • EBS服务是可靠的——即使虚拟机发生故障,服务器的硬盘发生故障或其他问题,EBS作为一种可靠的持久化存储服务,仍然可以保证数据的可靠性。
  • 在上面两个优异特性的基础上,更让人兴奋的是,EBS服务居然真是能用的,而且,你的程序可以直接像用本地磁盘一样用EBS,这简直是上天赐予我们的礼物。
  • 此外,EBS服务有更多的玩法——可以使用RAID,组合多块EBS盘,在一定程度上提高EBS的性能;可以创建快照,可以用快照来恢复成多块EBS盘。(盛大云硬盘的快照功能即将提供)

概括地说,EBS提供了持久化的、具有独立于主机的生命周期的、高可用的块存储设备,在这一设备上可以创建支持POSIX语义的本地文件系统(或是Windows本地文件系统)。这些独一无二的特征,让用户们在口诛笔伐这个服务的同时,也离不开这个服务。

云中的存储服务的差异

实际上,云服务里的存储服务并不少,有对象存储服务(亚马逊的S3和盛大的云存储服务皆在此列),也有块存储服务(亚马逊的EBS和盛大的云硬盘),当然,还有各种关系型、非关系型的云数据库…… 但是,为什么只有EBS服务受到这么大的争议呢。我们知道,数据存储服务可以分为结构化和非结构化,或分为块、对象、文件……但是,抛开数据的形式,不同的存储系统仍然有一类决定性的参数——时延。

Google的Jeff Dean在一次演讲中,引用了这样一组时延数字(节选, 引用链接: https://gist.github.com/2841832):

  • Main memory reference 100 ns
  • Round trip within same datacenter 0.5 ms
  • Disk seek 10 ms
  • Send packet CA->Netherlands->CA 150 ms

这也就是说,使用硬盘的本地程序,期待的是毫秒级的时延,而对于 Web 应用来说,上百毫秒的时延仍然是可以忍受的。

这也就决定了按照毫秒级时延设计的EBS系统的服务对象是运行在虚拟机上的本地应用,其最主要用法就是包括Ext2/¾, XFS, NTFS在内的各种本地文件系统,这些文件系统将数据和元数据存放在存储设备上,并认为存储是不常出错误的,相信存储设备一定会在可以盼望的时间里返回,而不需要考虑设备突然消失之类的事情。

与此相反,设计为面向Web应用的对象存储服务的客户应用,包括浏览器中的静态或动态网页、各种客户端的API请求。所有这些访问都通过HTTP API来执行,调用者期待这些服务在上百毫秒,甚至几秒钟内返回,甚至暂时的无法获取也不会对应用有太大的影响。

既然EBS需要满足毫秒级的时延需求,它的访问方式就必然是在一个数据中心内部的,而且,为保证数据可靠的多副本也必须在一个数据中心内部,否则,数据副本复制的时延和副本故障的切换将很难满足需求。当然,这不是说不可以进行跨数据中心的备份,只是,不可能实现跨数据中心的强一致性副本。

这样,我们可以发现两点:

  • 虚拟机中运行的应用强烈依赖EBS存储自身的可靠性,没有考虑,也很难特别考虑EBS的特殊性;
  • 如果一个数据中心出现大规模断电,比如这次亚马逊的事故,任何EBS服务都是不能保证0服务中断的,因为完美恢复只能依赖这个数据中心中的数据,而存储这些数据的服务器集体断电,需要时间来确保这些数据的正确性。

EBS做了什么

尽管我们知道EBS的脆弱性了,但是,我们得说,这种整个数据中心多路断电,同时切换到油机供电也发生故障的情况是极为罕见的,面对这样或更严重的(比如911)的事故,任何机构的民用级别的数据中心中的计算机也很难幸免,这样的故障可能暴露了亚马逊的某个Bug,但并不是说云服务商就比“前云时代”的主机托管安全性差了。

相反,具备了EBS服务的亚马逊AWS或盛大云服务会给用户更多安全保障,这些保障包括:

  • 不依赖于虚拟化服务器的本地硬盘。硬盘是PC服务器故障的重灾区,而且不论是服务器的电路故障还是硬盘物理故障,都会导致依赖于本地硬盘的服务无法继续;
  • 可以透明处理单机/单块硬盘的故障,在系统内任何一台服务器出现故障时,都不会影响存储服务的正常工作;
  • 良好设计的EBS系统,在更严酷的故障面前,可以进行较好的自我保护,在服务被迫中断时,也尽量避免数据不一致等问题出现;
  • 相对于SAN设备,成本低廉,对于用户来说,成本同样也更低。

基于这些考虑,我为EBS追加的辩护词里写到:虽然在极端故障下,EBS可能成为命门,但在更多情况下,EBS为云服务提供了更好的保障。持久存储仍然是故障面前你最可以依赖的。

如何使用EBS

对于EBS的使用,实际上和本地硬盘区别不大,可以直接使用,甚至做RAID,利用条带化来提高一定的性能。所有这些都非常简单易用。但是,EBS毕竟和本地磁盘还是有一定差异的,尽管应用无法感知,但用户还是需要在使用时有所注意。

首先,EBS的时延略高于本地磁盘。由于加入了网络传输过程,EBS的时延会比本地磁盘访问略高一点,这样,单线程、串行小请求的qps一定会受到比较大的影响,无法充分利用EBS的带宽。因此,在应用选择与架构设置时,如果可以更多地并发进行IO访问,会在IO性能方面有不错的收益。在Windows上观测,用FastCopy复制数据就会比Windows自带的复制程序快,用IOMeter加高outstanding IO值,就会获得很好的性能数据。特别地,对于Linux,利用预读设置

/sbin/blockdev --setra 1024 /dev/xvdb
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px; white-space: normal;">来增大块设备预读大小,可以明显地提升顺序读的性能,对于其他读写操作没有影响。我们也已经对盛大云计算的EBS缺省加入了这个设置参数。</span>

其次,EBS是共享存储带宽的服务,因为在很多应用中,存储本身不像CPU那样,是持续访问的,而是簇发方式地读写,为充分利用带宽,也为了让有需要的主机得到更好的性能,在其他卷不工作时,是允许某些卷占据超出平均值的存储带宽的。这样,在不同的时间,不同虚拟机得到的IO带宽是会有比较大的波动的。用户无法应该期待所有IO访问性能都是一致的。用户需要合理地利用系统缓存或缓存服务,并在必要时对数据进行分区,从而满足应用的需求。

from 我有分寸: http://wangxu.me/blog/p/735

改变互联网的IaaS服务

原文发于5月号《程序员》

改变互联网的 IaaS服务

4月10 日早上,我和老婆提起,“今天早上的大新闻是 Instagram被Facebook 收购了, 10亿美金,iOS 平台上最受欢迎的拍照分享服务”,我故意顿了一下,说“这家公司现在只有 13个人。”老婆立刻惊问,“他们怎么做到的?”确实难以置信,在去年年底冯大辉先生在DBANotes的《Instagram 架构笔记》(http://www.dbanotes.net/arch/instagram.html)里提到,“只有三名工程师,所以自己部署机器到 IDC是不靠谱的事情。幸好有亚马逊。” 是的,是亚马逊的IaaS服务—— AWS改变了游戏规则。

本文希望从技术角度,介绍IaaS服务商借助哪些核心技术提供了这样的能力,而创业者如果希望将来能和Instagram一样,服务上千万的用户、存储上亿张照片的话,应该如何更合理地使用IaaS云服务。

互联网创业的后AWS时代

实际上,互联网的从业者都知道,在AWS上的成功案例远不止这一家,去年QCon杭州的云计算主题的引言里,笔者就提到了Dropbox的案例,Zynga的成长也是AWS的受益者,同样的受益者还包括Foursquare, Quora… 正是AWS,或者说靠谱的IaaS服务的存在,才为这些创业公司的成长铺就了道路,以至于业界有了“后AWS时代”的提法。具体地说,后AWS时代都包含了那些特征呢:

随时可用的资源池——服务上线之前,创业者不需要租用IDC的机架位,也不需要购买服务器,更不需要去机房插网线,当服务需要上线的时候,在资源池里租用刚好够用的服务即可,没有固定资产投入,运维投入也是从服务上线部署才开始的。根据Zynga的案例(Zynga在没用AWS时,用户增加,运维加班严重,运维老大怀孕的老婆都来机房帮忙插网线,后来用了AWS,就再也无此窘境了 https://blog.khsing.net/2011/10/%E6%94%BEamazon%E7%9A%84%E6%88%90%E6%9C%AC.html),网友曾经杜撰过一条广告词——“AWS,让你的老婆在家安心待产”。

快速弹性——如果仅仅是方便的主机资源,那么也就不需要所谓“云计算”了,VPS们已经做得很好了。但是,Draw Something只用了几周就有每日1500万活跃用户和每秒3000张图片,Animoto 需要在3天之内将主机从5台增长到5000台(http://www.weibo.com/1642316384/yaS0on3xm),这样的规模和扩展速度,不仅依赖于网站的良好架构,也依赖于基础设施服务的高弹性。换一个角度考虑,如果你期望自己的服务也可以以这样梦幻速度增长,却不希望一下就准备这么多资源的话,具有快速弹性的IaaS服务无疑是你的首选。

用量计费——有了上面两项特性,相应地,成本也需要细粒度地按照用量来计算才划算,对于主机,只需要为运行的时间付费(随时可以新申请或释放掉主机资源),对于存储,只为使用的空间和流量付费,对于网络,只需要关心实际使用了多少流量。这样更能为小型的刚刚起步的服务节约成本。

按需自服务——所有上面的特征都依赖于便捷的使用,IaaS服务不仅可以通过页面点击完成资源的申请和释放,而且可以通过API,直接编程进行资源操作,配合自助的监控服务,IaaS的用户可以根据服务的负载情况,自动的增加或删除使用的资源,既保证终端用户的体验,又无需无谓付出成本。

新的互联网创业模式正式建立在这些特征之上的,他们可以更专注于应用的开发、低成本地提供服务。下面我们就来看具体提供这些特征的核心技术,以及如何使用这些技术和服务,确实获得这些期望的特征。

弹性的基础设施

IaaS的基础设施提供了从计算到存储一整套和传统计算机平台完全一致的环境,从而最大程度地方便了既有应用向云平台的迁移,但是云平台也不是“银弹”,并不是一切传统应用迁移到云上就可以无限扩展了。要想引爆云平台带来的弹性,还需要可扩展的网站架构以及合理利用云基础设施的各项实用功能。

面向扩展的服务架构

成为“合格”的云应用,服务架构自身的体质是最重要的。可扩展性,或者说弹性、可伸缩性,追求的是,当服务的节点规模增加时,服务能力也可以线性或近似线性的提升。这就需要服务请求可以被良好地、互不干扰地分配到多个节点上执行。

简单地,我们可以把一般的网站架构分成“服务”和“数据”两个大的层次,前者接纳用户的访问请求,执行各种计算任务,从数据层获取状态信息,并将可能存在的处理结果持久化到数据层;而数据层则要保证数据的正确性、一致性和可用性。

为了线性扩展,服务层就必须做到无状态,这样,任何新上线的节点都可以分担同样的负载请求。同时,要对数据和对数据的访问进行均匀的分片(sharding),在著名的eBay的分布式实践(http://www.infoq.com/cn/articles/ebay-scalability-best-practices)中,强调任何数据都要被分片,并避免分布式事务,这样,当面临海量请求的时候,才可以分而治之,而不是互相影响导致崩溃,重蹈火车订票系统的覆辙。尽管“分治”的思路很简单,但要做到均匀且可动态扩展却并不容易,一方面需要合理选择划分依据,另一方面需要数据存储层面的一些配合,后面的内容还会继续介绍多种云中的和分布式的存储技术。

虚拟化技术:弹性的基础

笔者个人并不赞同过度夸大虚拟化对云计算中的意义,显然虚拟服务器上的服务不能被称为“云服务”,但也无法否认,正是日益成熟的虚拟化技术,才让云计算的IaaS服务真正可以成功地大规模投入商业运营。

David Wheeler的有一句名言:“计算机科学中的一切问题,都可以通过再增加一个中间层来解决”(Diomidis Spinellis. Another level of indirection. In Andy Oram and Greg Wilson, editors, Beautiful Code: Leading Programmers Explain How They Think, chapter 17, pages 279–291. O’Reilly and Associates, Sebastopol, CA, 2007.),虚拟化计算技术就是这个在多任务操作系统出现之后,又在操作系统和硬件之间插入的中间层,它解决的问题包括:

  • 一台计算机的处理能力已经足够满足多个用户的需求了,但在分给多个租户的时候,他们需要的操作系统环境不尽相同,也需要彼此安全地隔离;
  • 动态的调整一台计算机(或者说操作系统)的物理资源不够容易,至少不容易自动化;
  • 安装或迁移一台服务器需要大量的时间,而且不灵活。

虚拟化技术主要是一种隔离与监视技术,让不同的虚拟机分享同一套物理机(主要指CPU/内存子系统)而彼此隔离、互不干扰,同时,为虚拟机代理访问网络、磁盘IO等共享的外部资源。由于虚拟化技术对CPU/内存子系统工作的干扰很少,因此,计算能力方面很少有开销,相比之下,IO的性能受到的影响会略大一些,但也是可以接受的。

目前的IaaS服务中,主要的虚拟化技术包括开源的Xen、KVM,以及VMWare的ESX和微软的Hyper-V。它们的工作原理都比较接近,以Xen为例,它通过一个hypervisor来监控管理多个不同的虚拟机(称为Domain),并将IO等访问特权资源的操作在专门的特权域(Dom0)中执行,其他的运行客户操作系统的虚拟机称为用户域(DomU)。某些DomU操作系统是被修改过的操作系统,它们知道自己运行在虚拟化环境中,并不直接和硬件打交道,于是,它可以将IO请求通过“XenBus”直接发送到Dom0,由Dom0代理完成,这种方法效率很高,称为半虚拟化(PV, ParaVirtualization)。对于不支持以PV方式运行的虚拟机,我们需要首先实现一个虚拟的设备(在Linux下,Xen和KVM的虚拟设备都是基于Qemu的),提供给虚拟机,它再将这些IO请求代理发出,这种方式的IO相比之下更加繁琐,效率更低,称为完全虚拟化(FV, Full Virtualization),优点是可以兼容任何操作系统,无需修改。

实际上,在VPS主机服务和各种内部的虚拟化服务方案中,还使用另一种虚拟化技术,包括Linux的OpenVZ、vServer以及Sun的Zone等技术,这些技术利用操作系统内核本身的特性,在操作系统中划分出多个强隔离分区,从而解决资源共享的问题。但是,这种方案下,多个虚拟机是共用同一个内核的,隔离性不高,也不可能支持不同虚拟机使用不同类型的操作系统,因此,IaaS服务普遍不会使用这项技术。

实现快速扩展的公有云运维技术

即使虚拟机可以快速分配、部署了,用户的服务程序的部署也不见得是一个简单的过程,尤其要在服务提供的过程,自动化地扩充服务器,更需要费一番力气。实际上,除了使用配置服务等“传统手段”之外,IaaS服务商们还提供自己的一些运维用工具,帮助用户更好地实现弹性服务。

这些技术之一就是快照/镜像服务,很多云服务商都已经提供了这项功能,它可以帮助用户保存虚拟机的一个快照性质的副本,一旦用户的虚拟机发生故障,可以用于恢复虚拟机;同时,因为用户的应用服务器一般是无状态的,这样,通过定制镜像可以直接快速复制出大量的包含用户应用的,相同配置的虚拟机。而且,对于实现良好的IaaS服务,镜像服务系统可以加速热点镜像的传播,进一步加速了用户服务的扩展。

通过API实现自动扩展

IaaS的目标之一就是帮助用户尽可能的降低运维的复杂度,即使用户需要随着服务规模的增长迅速扩展服务能力,仍然能够举重若轻。这里,不可忽视的一个方面就是云服务的API,对于一个“可编程”的IaaS服务,用户可以在业务需要时,通过RESTful API请求来直接创建新的虚拟机,而无需登陆管理页面。

更进一步,与监控程序配合,用户的扩展脚本可以根据性能监控的数据,用户可以实现在业务流量在一定范围内发生变化时,无人值守地扩展或缩小服务规模,既不浪费资源,又不影响服务质量。通过云监控、API和扩展脚本,以及上面提到的镜像服务的配合,用户可以实现高效可靠的自动化扩展能力。

善用存储服务

前面提到数据层对于网站可扩展性的重要性,这里就要展开介绍云中的各种存储服务。存储本身说来简单,但实际需求却很多样,有提供客户端访问的,也有服务自己的元数据;有需要持久化的,也有用于加速的缓存;有要求严格一致的交易数据,也有不太重要的状态更新;有结构化的,也有非结构化的。而不同的存储系统、存储服务也是为不同的用途所准备的,要真的做到高效、低成本、可扩展,就需要为服务选择合理的存储服务。

对象存储服务

对象存储服务是指可以通过HTTP RESTful接口的API,以键值访问的数据对象,典型的对象存储服务是亚马逊的S3服务以及国内相应的云服务商的云存储服务。通常对象就是一个文件,如图片或文档、音乐、压缩包等,而用于标识对象的键值可以看作是文件名。对象被组织在称为桶(bucket)的容器中,每个桶可以指定特定的访问权限等属性。与网盘或分布式文件系统不同,对象存储服务不提供全局的命名空间和复杂的目录树,只有桶-对象二级结构,这简化了系统的实现、也提高了访问效率,当然,要把直接使用既有服务迁移到对象存储服务上来,需要进行一定的调整:

对象存储服务的访问URL一般是类似下面的形式:

http://s3.amazonaws.com/ppt-download/cloud-bupt-phpapp01.pdf?

URL的路径部分就是对象的逻辑结构,而“?”之后的参数部分会包含请求的Token和其他相关参数。在页面中,将附件、图片等托管到对象存储中实际并不需要太多的调整。

对于使用IaaS云搭建的云服务,推荐使用云存储服务存放需要浏览器或是客户端直接下载的静态内容,因为这样一方面可以直接使用云服务带来的高可靠、高可用性,利用云服务商提供的网络加速功能,同时,相对于虚拟机存储空间的局限性和其他存储服务的成本来说更低廉,也不会占用虚拟机服务的带宽,是一种性价比更高的存储服务。

在网页的图片和附件之外,对象存储还胜任很多其他场合,如网盘和计算机间的数据同步,著名的同步服务Dropbox就构建在亚马逊的S3上,而苹果的iCloud也被认为可能构建在亚马逊的云上。时至今日,亚马逊的S3已经是最受欢迎的云基础设施服务了,截止到2012年1月,亚马逊S3中已经存储了7620亿个对象了(http://www.36kr.com/p/79515.html)。在国内,IaaS服务商们也提供了类似的服务,但国内的用户市场还在培育之中。

云硬盘服务

云硬盘服务或弹性快存储服务(EBS, Elastic Block Store)并不是网盘,而是一种提供给弹性计算中的虚拟机使用的,具有独立于虚拟机的永久存储能力和高可用性的存储服务。对于虚拟机来说,云硬盘使用起来就是一块硬盘。用户可以申请一块任意大小(一般是1-1000GB之间的整数GB)的云硬盘,将它挂载到自己的任意虚拟机上使用,也可以将它同一台虚拟机上卸载,并挂载到另一台虚拟机上,甚至于可以删除所有虚拟机,只保留云硬盘。

相对于虚拟机自己的存储空间,云硬盘的大小更灵活、可以由用户指定;云硬盘具有更高的可靠性,即使虚拟机发生故障,云硬盘由于有后台的类似RAID的多副本保障,仍然可以保障数据的可靠;云硬盘的生命周期与虚拟机彼此独立,弹性计算服务鼓励用户在不使用时,释放虚拟机,让出资源,同时也节约自己的开销,这样的情况下,云硬盘可以承担数据持久化的功能,不必因为释放虚拟机就丢弃数据。

尽管作为一块硬盘,云硬盘显然可以存放图片、附件等内容,但并不意味着云硬盘是比对象存储更好的存储系统。两者是面向不同用途的,如上所说,使用对象存储意味着更低的成本和往往更好的客户端访问性能,可以利用服务商的网络加速能力,并且不占用虚拟机的网络流量;作为对比,云硬盘可以从虚拟机更快的访问(读取操作平均响应时间一般是小于10毫秒的),各种程序可以像访问本地磁盘一样使用云硬盘中的数据,当然,云硬盘会比云存储贵一些,因此,相对于面向客户端请求的对象存储服务,云硬盘更倾向于存放数据库等供虚拟机直接使用的持久化数据。

云中的关系型与非关系型数据库

毫无疑问,Web 2.0时代的基石之一是一种开源的关系型数据库——MySQL,但随着移动互联网和社交网络的发展导致的数据爆炸性增长,关系型数据库的范式模型和事务性限制了它们在保持原有功能性的情况下,水平扩展到更多节点上。于是,在“大数据(BigData)”时代,很多非关系型数据库(NoSQL)开始受到越来越多的推崇。

根据Brewer的CAP原理,对于一个分布式系统,一致性(Consistency)、可用性(Availability)和分区耐受性(Partition Tolerance)三个特性,只能强化其中两个。作为面向大数据的分布式存储系统,分区耐受性是必须的选择,因此,就不得不在一致性和可用性之间抉择,选择一致性的系统不得不在有些情况下无法提供服务,而那些强化可用性的服务则允许系统在某些时刻不完全一致,也就是所谓的“最终一致性”。用户在选择一个存储系统时需要选择,自己的数据模型怎样、是否需要强一致性。当然,NoSQL和MySQL之间并非取代关系,两者各有优势,并且,笔者负责任的说,大部分的应用还没到MySQL无法承受的数据规模,只是有的需要更良好的架构设计而已。

而对于NoSQL,也有很多可以选择的,比较流行的包括面向JSON文档的、灵活的MongoDB,主要用于内存缓存的、高性能的、通过键值方式访问的Redis,基于Hadoop、提供列族模型的HBase,以及同样提供列族模型的、写入性能很高的、无中心的Cassandra等。

很多IaaS云服务商也提供了SQL与NoSQL的增值服务,用户可以选择安装、调优好的虚拟机,作为云数据库服务。

CDN服务

CDN(内容推送网)服务很难确切定位为存储还是网络服务,它是用于加速用户的网络访问的,其加速手段是通过部署在接近终端用户位置的缓存服务器,向他们提供高速内容服务的。

传统的CDN服务一般是面向访问量很大的客户的加速服务,不仅贵,而且购买、调整不方便。而IaaS云服务商面向他们的客户,提供了自助化的CDN加速服务,使得中小网站也可以享受到同样的加速服务。

 展望:从IaaS到PaaS

虽然相对于IaaS,PaaS还没有大量的改变我们生活,但并不妨碍很多业内人士将其视为公有云的未来 。与IaaS的简单直接不同,PaaS服务并不直接提供资源,而是提供运行环境和功能组件(库)以及附加的服务,如数据库、队列及其他特殊功能,更方便开发者的开发、部署,而将伸缩、扩展等复杂性进一步屏蔽。

在PaaS服务逐渐成熟的同时,一些开构建在的IaaS层之上的PaaS服务也开始出现,成为IaaS的增值服务,使得两者的界限逐步开始模糊。此外,一些可以构建在多种IaaS服务上的“开放PaaS”平台的出现,更进一步方便了IaaS服务商提供附加的PaaS服务,给用户更多的选择。这一演进将进一步降低运维开销,让创业者把精力更多专注于创新和提高用户体验上,彼此共赢。

from 我有分寸: http://wangxu.me/blog/p/731