ruby gem -v yaml

gem –version

如果在使用gem的时候碰到这样的提示:

gem --version# /usr/local/lib/ruby/1.9.1/yaml.rb:84:in `<top (required)>': # It seems your ruby installation is missing psych (for YAML output). # To eliminate this warning, please install libyaml and reinstall your ruby. 

这是在编译安装 ruby 的时候没有先安装 libyaml 所致。但是,即使是你安装 libyaml 之后重新安装 ruby ,这个问题还是不能解决。

正确的方法,是安装 libyam-devel 库。下面是在 CentOS 6.3 上安装:

yum install libyaml-devel

然后,找到你先前编译 ruby 的目录,进入 ext/psych/ 文件夹,执行:

ruby extconf.rb make make install# checking for yaml.h... yes # checking for yaml_get_version() in -lyaml... yes # creating Makefile 

然后再执行一次 make install 。如果你已经 clean 了原来的编译内容,那么则需要重新编译。

make install# compiling to_ruby.c # compiling parser.c # compiling psych.c # compiling emitter.c # compiling yaml_tree.c # linking shared-object psych.so # /usr/bin/install -c -m 0755 psych.so /usr/local/lib/ruby/site_ruby/1.9.1/x86_64-linux # installing default psych libraries 

再次执行 gem -v ,发现 warning 已经消失了。

发表在 technologys | ruby gem -v yaml已关闭评论

Twitter 高并发高可用架构

解决 Twitter的“问题”就像玩玩具一样,这是一个很有趣的扩展性比喻。每个人都觉得 Twitter很简单,一个菜鸟架构师随便摆弄一下个可伸缩的 Twitter就有了,就这么简单。然而事实不是这样, Twitter的工程副总裁 Raffi Krikorian细致深入的描述了在 Twitter在可伸缩性上的演化过程,如果你想知道 Twitter的如何工作—从这里开始吧。

Twitter发展太快,一切转瞬即过,但 Twitter已经长大了。它从一开始一个在Ruby on Rails上苦苦挣扎的小网站变成一个以服务为 核心驱动的漂亮站点,服务停掉都难得一见,很大的一个转变。

Twitter现在有1.5亿全球活跃用户,300K QPS,22 MB/秒的流量,系统每天处理4亿条推特数据,用5分钟时间将Lady Gaga手尖流淌出的信息传递到她3100万个关注者。

一些需要列出来的要点:

  • Twitter不再希望成为一个Web应用程序,Twitter想要成为一套驱动全世界手机客户端的API,作为地球上最大的实时交互工具。
  • Twitter主要在分发消息,而不是生产消息,300K QPS是在读而每秒仅有6000请求在写。
  • 不对称,有数量庞大的粉丝,现在正成为一种常见情况。单个用户发送的消息有很多追随者要看到,这是一个大的扇型输出,分发可能很缓慢,Twitter试图保证在5秒以内,但并不能总是达到这个目标,尤其是当名人或名人之间发推特时,这种情况越来越常见,一个可能后果是在还未看到原始消息之前接受到了回复。Twitter做工作是在迎接高关注度用户所写推特读取的挑战。
  • 你主页的数据储存在由800多个Redis节点组成的集群上。
  • 从你关注的人及你点击的链接Twitter更了解你。可以通过隐私设置的双向以下时不存在。
  • 用户关心推特内容本身,但对Twitter而言推特的内容与其基础设施建设几乎无关。
  • 需要一个非常复杂的监控和调试系统来跟踪复杂协议栈内的性能问题。传统的遗留问题一直困扰着系统。

Twitter是如何工作的?通过Raffi精彩的演讲来发现吧…

面临的挑战

  • 可靠的实现150万在线用户及300K QPS(主页和搜索访问),响应慢怎么办?
  • 可靠的实现是一个对所有推特的select语句,响应忙死卡死。
  • 数据扇形输出的解决方案。当接收到新推特时需要弄清楚应该把它发到哪,这样可以更快速简单的读取,不要在读操作上做任何逻辑计算,性能上写要比读慢得多,能做到4000 QPS。

内部组成

  • 平台服务部门负责Twitter的核心基础设施的可扩展性。
    • 他们运行的东西为时间轴、微博、用户及社交网络提供服务,包括所有支撑Twitter平台的系统设备。
    • 统一内外部客户使用相同的API。
    • 为数百万的第三方应用注册支持
    • 支持产品团队,让他们专注产品无系统支撑方面顾虑。
    • 致力于容量规划、构建可扩展的后端系统等工作,通过不断更换设施使网站达到意想不到的效果。
  • Twitter有一个架构师部门,负责Twitter整体架构,研究技术改进路线(他们想一直走在前面)。

Push、Pull模式

  • 每时每刻都有用户在Twitter上发表内容,Twitter工作是规划如何组织内容并把它发送用户的粉丝。
  • 实时是真正的挑战,5秒内将消息呈现给粉丝是现阶段的目标。
    • 投递意味着内容、投入互联网,然后尽可能快的发送接收。
    • 投递将历时数据放入存储栈,推送通知,触发电子邮件,iOS、黑莓及Android手机都能被通知到,还有短信。
    • Twitter是世界上活跃中最大的信息发送机。
    • 推荐是内容产生并快速传播的巨大动力。
  • 两种主要的时间轴:用户的及主页的。
    • 用户的时间轴特定用户发送的内容。
    • 主页时间表是一段时间内所有你关注用户发布的内容。
    • 线上规则是这样的:@别人是若被@的人你未关注的话将被隔离出来,回复一个转发可以被过滤掉。
    • 这样在Twitter对系统是个挑战。
  • Pull模式
    • 有针对性的时间轴。像twitter.com主页和home_timeline的API。你请求它才会得到数据。拉请求的不少:通过REST API请求从Twitter获取数据。
    • 查询时间轴,搜索的API。查询并尽可能快的返回所有匹配的推特。
  • Push模式
    • Twitter运行着一个最大的实时事件系统,出口带宽22MB/秒。
      • 和Twitter建立一个连接,它将把150毫秒内的所有消息推送给你。
      • 几乎任何时候,Push服务簇上大约有一百万个连接。
      • 像搜索一样往出口发送,所有公共消息都通过这种方式发送。
      • 不,你搞不定。(实际上处理不了那么多)
    • 用户流连接。 TweetDeck 和Twitter的Mac版都经过这里。登录的时,Twitter会查看你的社交图,只会推送那些你关注的人的消息,重建主页时间轴,而不是在持久的连接过程中使用同一个时间轴 。
    • 查询API,Twitter收到持续查询时,如果有新的推特发布并且符合查询条件,系统才会将这条推特发给相应的连接。

高观点下的基于Pull(拉取方式)的时间轴:

  • 短消息(Tweet)通过一个写API传递进来。通过负载平衡以及一个TFE(短消息前段),以及一些其它的没有被提到的设施。
  • 这是一条非常直接的路径。完全预先计算主页的时间轴。所有的业务逻辑在短消息进入的时候就已经被执行了。
  • 紧接着扇出(向外发送短消息)过程开始处理。进来的短消息被放置到大量的Redis集群上面。每个短息下在三个不同的机器上被复制3份。在Twitter 每天有大量的机器故障发生。
  • 扇出查询基于Flock的社交图服务。Flock 维护着关注和被关注列表。
  • Flock 返回一个社交图给接受者,接着开始遍历所有存储在Redis 集群中的时间轴。
  • Redis 集群拥有若干T的内存。
  • 同时连接4K的目的地。
  • 在Redis 中使用原生的链表结构。
  • 假设你发出一条短消息,并且你有20K个粉丝。扇出后台进程要做的就是在Redis 集群中找出这20K用户的位置。接着它开始将短消息的ID 注入到所有这些列表中。因此对于每次写一个短消息,都有跨整个Redis集群的20K次的写入操作。
  • 存储的是短消息的ID, 最初短消息的用户ID, 以及4个字节,标识这条短消息是重发还是回复还是其它什么东东。
  • 你的主页的时间轴驻扎在Redis集群中,有800条记录长。如果你向后翻很多页,你将会达到上限。内存是限制资源决定你当前的短消息集合可以多长。
  • 每个活跃用户都存储在内存中,用于降低延迟。
  • 活跃用户是在最近30天内登陆的twitter用户,这个标准会根据twitter的缓存的使用情况而改变。
  • 只有你主页的时间轴会存储到磁盘上。
  • 如果你在Redis 集群上失败了,你将会进入一个叫做重新构建的流程。
  •      查新社交图服务。找出你关注的人。对每一个人查询磁盘,将它们放入Redis中。
  •      MySQL通过Gizzard 处理磁盘存储,Gizzard 将SQL事务抽象出来,提供了全局复制。
  • 通过复制3次,当一台机器遇到问题,不需要在每个数据中心重新构建那台机器上的时间轴。
  • 如果一条短消息是另外一条的转发,那么一个指向原始短消息的指针将会存储下来。
  • 当你查询你主页的时间轴时候,时间轴服务将会被查询。时间轴服务只会找到一台你的时间轴所在的机器。
  •      高效的运行3个不同的哈希环,因为你的时间轴存储在3个地方。
  •      它们找到最快的第一个,并且以最快速度返回。
  •      需要做的妥协就是,扇出将会花费更多的时间,但是读取流程很快。大概从冷缓存到浏览器有2秒种时间。对于一个API调用,大概400ms。
  • 因为时间轴只包含短消息ID, 它们必须”合成”这些短消息,找到这些短消息的文本。因为一组ID可以做一个多重获取,可以并行地从T-bird 中获取短消息。
  • Gizmoduck 是用户服务,Tweetypie 是短消息对象服务。每个服务都有自己的缓存。用户缓存是一个memcache集群 拥有所有用户的基础信息。Tweetypie将大概最近一个半月的短消息存储在memcache集群中。这些暴露给内部的用户。
  • 在边界将会有一些读时过滤。例如,在法国过滤掉纳粹内容,因此在发送之前,有读时内容剥离工作。

高级搜索

  • 与Pull相反,所有计算都在读时执行,这样可以使写更简单。
  • 产生一条推特时,Ingester会对其做语法分析找出新建索引的一切东西,然后将其传入一台Early Bird机器。Early Bird是Lucene的修改版本,索引储存在内存中。
  • 在推特的分发过程中可能被储存在多个由粉丝数量决定的主页时间轴中,一条推特只会存入一个Early Bird机器中(不包括备份)。
  • Blender进行时间轴的跨数据中心集散查询。为发现与查询条件匹配的内容它查询每个Early Bird。如果你搜索“纽约时报”,所有分片将被查询,结果返回后还会做分类、合并及重排序等。排序是基于社会化度量的,这些度量基于转发、收藏及评论的数量等。
  • 互动信息是在写上完成的,这里会建立一个互动时间轴。当收藏或回复一条推特时会触发对互动时间轴的修改,类似于主页时间轴,它是一系列的活跃的ID,有最受喜欢的ID,新回复ID等。
  • 所有这些都被送到Blender,在读路径上进行重计算、合并及分类,返回的结果就是搜索时间轴上看到的东西。
  • Discovery是基于你相关信息的定制搜索,Twitter通过你关注的人、打开的链接了解你的信息,这些信息被应用在Discovery搜索上,重新排序也基于这些信息。

Search和Pull是相反的

  • Search和Pull明显的看起来很相似,但是他们在某些属性上却是相反的。
  • 在home timeline时:
    • 写操作。tweet写操作引发O(n)个进程写入Redis集群,n代表你的粉丝,如果是这样,处理Lady Gaga或是Obama百万粉丝的数据就得用10s的时间,那是很难接受的。所有的Redis集群都支持硬盘处理数据,但是一般都是在RAM里操作的。
    • 读操作。通过API或是网络可用O(1)的时间来找到Redis机器。Twitter在寻找主页路径方面做了大量的优化。读操作可在10毫秒完成。所有说Twitter主导消费机制而不是生产机制。每秒可处理30万个请求和6000 RPS写操作。
  • 在搜索timeline时:
    • 写操作。一个tweet请求由Ingester收到并有一个Early Bird机器来处理。写操作时O(1).一个tweet需要5秒的处理时间,其包括排队等待和寻找路径。
    • 读操作。读操作引发O(n)个集群读操作。大多数人不用search,这样他们可以在存储tweets上面更加有效,但是他们得花时间。读需要100毫秒,search不涉及硬盘操作。全部Lucene 索引表都放入RAM,这样比放在硬盘更加有效。
  • tweet的内容和基础设施几乎没什么关系。T-bird stores负责tweet所有的东西。大多数tweet内容是放在RAM处理的。如有没再内存中,就用select query将内容抓到内存中。只有在search,Trends,或是What’s Happening pipelines中涉及到内容,hone timeline对此毫不关心。

展望:

  • 如何使通道更快更有效?
  • Fanout可以慢下来。可以调整到5秒以下,但是有时候不能工作。非常难,特别是当有名人tweet时候,这种情况越来越多。
  • Twitter 关注也是非常不对称的。Tweet只提供给定时间内被关注的信息。Twitter更注重你的信息,因为你关注了兰斯.阿姆斯特朗,但是他并没有关注你。由于不存在互相的关注关系,所以社会联系更多是暗示性隐含性。
  • 问题是巨大的基数。@ladygaga 有3100万关注者。@katyperry有2800万。@barackobama有2300万关注着。
  • 当这些人中有人发微博的时候,数据中心需要写大量微薄到各个关注者。当他们开始聊天时候,这是非常大的挑战,而这时刻都在发生着。
  • 这些高关注度的Fanout用户是Twitter最大的挑战。在名人原始微薄发出到关注用户之前,回复一直可以看到。这导致整个网站紊乱。Lady Gaga的一条微薄到关注用户需要几分钟的时间,所以关注者看到这条微薄时间是在不同时间点上。有些人可能需要大概5分钟的时间才能看到这条微薄,这远远落后于其他人。可能早期收到微薄的用户已经收到了回复的列表,而这时候回复还正在处理之中,而fanout还一直进行着所以回复被加了进来。这都发生在延迟关注者收到原始微薄之前。这会导致大量用户混乱。微薄发出之前是通过ID排序的,这导致它们主要是单调增长地,但是那种规模下这不能解决问题。对高值的fanouts队列一直在备份。
  • 试图找到解决合并读和写路径的方法。不在分发高关注度用户微薄。对诸如Taylor Swift的人不会在额外的处理,只需要在读时候,他的时间点并入即可。平衡读和写的路径。可以节约百分之10s的计算资源。

解耦

  • Tweet通过很多的方式解除关联,主要地通过彼此解耦的方式。搜索、推送、邮件兴趣组以及主页时间轴可以彼此独立的工作。
  • F由于性能的原因,系统曾经被解耦过。Twitter曾经是完全同步地方式的,由于性能的原因2年前停止了。提取一个tweet到tweet接口需要花费145微秒,接着所有客户端被断开连接。这是历史遗留的问题。写路径是通过MRI用一个Ruby驱动的程序,一个单线程的服务。每次一个独立的woker被分配的时候,处理器都会被耗尽。他们希望有能力尽可能快的去释放客户端连接。一个tweet进来了。Ruby处理了它。把它插入队列,并且断开连接。他们仅仅运行大概45-48进程/盒。所以他们只能并行处理同样多tweets/盒,所以他们希望尽可能快的断开连接。
  • Tweets 被切换到异步路径方式,我们讨论所有东西都被剔除了。

监控

  • 办公室四处的仪表盘显示了系统在任何给定时间系统的运行状态。
  • 如果你有100万的关注者,将会要花费好几分钟到分发到所有tweets。
  • Tweets 入口统计:每天400兆的tweets。日平均每秒种5000;日高峰时每秒7000;有事件时候是每秒超过12000。
  • 时间轴分发统计:30b分发/日(约21M/分钟);3.5秒@p50(50%分发率)分发到1M;300k 分发/秒;@p99 大概需要5分钟。
  • 一个名为VIZ的监控系统监控各个集群。时间轴服务检索数据集群数据的平均请求时间是5毫秒。@p99需要100毫秒。@p99.9需要请求磁盘,所以需要大概好几百毫秒。
  • Zipkin 是基于谷歌Dapper的系统。利用它可以探测一个请求,查看他点击的每一个服务,以及请求时间,所以可以获得每个请求的每一部分性能细节信息。你还还可以向下钻取,得到不同时间周期下的每单个的请求的详细信息。大部分的时间是在调试系统,查看请求时间都消耗的什么地方。它也可以展示不同纬度的聚合统计,例如,用来查看fanout和分发了多久。大概用了2年长的一个工程,来把活跃用户时间线降到2毫秒。大部分时间用来克服GC停顿,memchache查询,理解数据中心的拓扑应该是怎么样结构,最后建立这种类型集群。
  • 参与翻译(4人):Garfielt, 桔子, 李勇2, yale8848
发表在 technologys | Twitter 高并发高可用架构已关闭评论

.NET技术+25台服务器怎样支撑世界第54大网站

摘要:同时使用Linux和Windows平台产品,大量使用静态的方法和类,Stack Overflow是个重度性能控。同时,取代横向扩展,他们坚持着纵向扩展思路,因为“硬件永远比程序员便宜”。


StackOverflow是一个IT技术问答网站,用户可以在网站上提交和回答问题。当下的StackOverflow已拥有400万个用户,4000万个回答,月PV5.6亿,世界排行第54。然而值得关注的是,支撑他们网站的全部服务器只有25台,并且都保持着非常低的资源使用率,这是一场高有效性、负载均衡、缓存、数据库、搜索及高效代码上的较量。近日,High Scalability创始人Todd Hoff根据Marco Cecconi的演讲视频“ The architecture of StackOverflow”以及Nick Craver的博文“ What it takes to run Stack Overflow”总结了StackOverflow的成功原因。


点击查看原图


意料之中,也是意料之外,Stack Overflow仍然重度使用着微软的产品。他们认为既然微软的基础设施可以满足需求,又足够便宜,那么没有什么理由去做根本上的改变。而在需要的地方,他们同样使用了Linux。究其根本,一切都是为了性能。


另一个值得关注的地方是,Stack Overflow仍然使用着纵向扩展策略,没有使用云。他们使用了384GB的内存和2TB的SSD来支撑SQL Servers,如果使用AWS的话,花费可想而知。没有使用云的另一个原因是Stack Overflow认为云会一定程度上的降低性能,同时也会给优化和排查系统问题增加难度。此外,他们的架构也并不需要横向扩展。峰值期间是横向扩展的杀手级应用场景,然而他们有着丰富的系统调整经验去应对。该公司仍然坚持着Jeff Atwood的名言——硬件永远比程序员便宜。


Marco Ceccon曾提到,在谈及系统时,有一件事情必须首先弄明白——需要解决问题的类型。首先,从简单方面着手,StackExchange究竟是用来做什么的——首先是一些主题,然后围绕这些主题建立社区,最后就形成了这个令人敬佩的问答网站。


其次则是规模相关。StackExchange在飞速增长,需要处理大量的数据传输,那么这些都是如何完成的,特别是只使用了25台服务器,下面一起追根揭底:


状态


●StackExchange拥有110个站点,以每个月3到4个的速度增长。

●400万用户

●800万问题

●4000万答案

●世界排名54位

●每年增长100%

●月PV 5.6亿万

●大多数工作日期间峰值为2600到3000请求每秒,作为一个编程相关网站,一般情况下工作日的请求都会高于周末

●25台服务器

●SSD中储存了2TB的SQL数据

●每个web server都配置了2个320G的SSD,使用RAID 1

●每个ElasticSearch主机都配备了300GB的机械硬盘,同时也使用了SSD

●Stack Overflow的读写比是40:60

●DB Server的平均CPU利用率是10%

●11个web server,使用IIS

●2个负载均衡器,1个活跃,使用HAProxy

●4个活跃的数据库节点,使用MS SQL

●3台实现了tag engine的应用程序服务器,所有搜索都通过tag

●3台服务器通过ElasticSearch做搜索

●2台使用了Redis的服务器支撑分布式缓存和消息

●2台Networks(Nexus 5596 + Fabric Extenders)

●2 Cisco 5525-X ASAs

●2 Cisco 3945 Routers

●主要服务Stack Exchange API的2个只读SQL Servers

●VM用于部署、域控制器、监控、运维数据库等场合


平台


●ElasticSearch

●Redis

●HAProxy

●MS SQL

●Opserver

●TeamCity

●Jil——Fast .NET JSON Serializer,建立在Sigil之上

●Dapper——微型的ORM


UI


●UI拥有一个信息收件箱,用于新徽章获得、用户发送信息、重大事件发生时的信息收取,使用WebSockets实现,并通过Redis支撑。

●搜索箱通过 ElasticSearch 实现,使用了一个REST接口。

●因为用户提出问题的频率很高,因此很难显示最新问题,每秒都会有新的问题产生,从而这里需要开发一个关注用户行为模式的算法,只给用户显示感兴趣的问题。它使用了基于Tag的复杂查询,这也是开发独立Tag Engine的原因。

●服务器端模板用于生成页面。


服务器


●25台服务器并没有满载,CPU使用率并不高,单计算SO(Stack Overflow)只需要5台服务器。

●数据库服务器资源利用率在10%左右,除下执行备份时。

●为什么会这么低?因为数据库服务器足足拥有384GB内存,同时web server的CPU利用率也只有10%-15%。

●纵向扩展还没有遇到瓶颈。通常情况下,如此流量使用横向扩展大约需要100到300台服务器。

●简单的系统。基于.Net,只用了9个项目,其他系统可能需要100个。之所以使用这么少系统是为了追求极限的编译速度,这点需要从系统开始时就进行规划,每台服务器的编译时间大约是10秒。

●11万行代码,对比流量来说非常少。

●使用这种极简的方式主要基于几个原因。首先,不需要太多测试,因为Meta.stackoverflow本来就是一个问题和bug讨论社区。其次,Meta.stackoverflow还是一个软件的测试网站,如果用户发现问题的话,往往会提出并给予解决方案。

●纽约数据中心使用的是Windows 2012,已经向2012 R2升级(Oregon已经完成了升级),Linux系统使用的是Centos 6.4。


SSD


●默认使用的是Intel 330(Web层等)

●Intel 520用于中间层写入,比如Elastic Search

●数据层使用Intel 710和S3700

●系统同时使用了RAID 1和RAID 10(任何4+以上的磁盘都使用RAID 10)。不畏惧故障发生,即使生产环境中使用了上千块2.5英寸SSD,还没碰到过一块失败的情景。每个模型都使用了1个以上的备件,多个磁盘发生故障的情景不在考虑之中。

●ElasticSearch在SSD上表现的异常出色,因为SO writes/re-indexes的操作非常频繁。

●SSD改变了搜索的使用方式。因为锁的问题,Luncene.net并不能支撑SO的并发负载,因此他们转向了ElasticSearch。在全SSD环境下,并不需要围绕Binary Reader建立锁。


高可用性


●异地备份——主数据中心位于纽约,备份数据中心在Oregon。

●Redis有两个从节点,SQL有2个备份,Tag Engine有3个节点,elastic有3个节点,冗余一切,并在两个数据中心同时存在。

●Nginx是用于SSL,终止SSL时转换使用HAProxy。

●并不是主从所有,一些临时的数据只会放到缓存中

所有HTTP流量发送只占总流量的77%,还存在Oregon数据中心的备份及一些其他的VPN流量。这些流量主要由SQL和Redis备份产生。


数据库


●MS SQL Server

●Stack Exchange为每个网站都设置了数据库,因此Stack Overflow有一个、Server Fault有一个,以此类推。

●在纽约的主数据中心,每个集群通常都使用1主和1只读备份的配置,同时还会在Oregon数据中心也设置一个备份。如果是运行的是Oregon集群,那么两个在纽约数据中心的备份都会是只读和同步的。

●为其他内容准备的数据库。这里还存在一个“网络范围”的数据库,用于储存登陆凭证和聚合数据(大部分是stackexchange.com用户文件或者API)。

●Careers Stack Overflow、stackexchange.com和Area 51等都拥有自己独立的数据库模式。

●模式的变化需要同时提供给所有站点的数据库,它们需要向下兼容,举个例子,如果需要重命名一个列,那么将非常麻烦,这里需要进行多个操作:增加一个新列,添加作用在两个列上的代码,给新列写数据,改变代码让新列有效,移除旧列。

●并不需要分片,所有事情通过索引来解决,而且数据体积也没那么大。如果有filtered indexes需求,那么为什么不更高效的进行?常见模式只在DeletionDate = Null上做索引,其他则通过为枚举指定类型。每项votes都设置了1个表,比如一张表给post votes,1张表给comment votes。大部分的页面都可以实时渲染,只为匿名用户缓存,因此,不存在缓存更新,只有重查询。

●Scores是非规范化的,因此需要经常查询。它只包含IDs和dates,post votes表格当下大约有56454478行,使用索引,大部分的查询都可以在数毫秒内完成。

●Tag Engine是完全独立的,这就意味着核心功能并不依赖任何外部应用程序。它是一个巨大的内存结构数组结构,专为SO用例优化,并为重负载组合进行预计算。Tag Engine是个简单的windows服务,冗余的运行在多个主机上。CPU使用率基本上保持在2-5%,3个主机专门用于冗余,不负责任何负载。如果所有主机同时发生故障,网络服务器将把Tag Engine加载到内存中持续运行。

●关于Dapper无编译器校验查询与传统ORM的对比。使用编译器有很多好处,但在运行时仍然会存在fundamental disconnect问题。同时更重要的是,由于生成nasty SQL,通常情况还需要去寻找原始代码,而Query Hint和parameterization控制等能力的缺乏更让查询优化变得复杂。


编码


●流程

●大部分程序员都是远程工作,自己选择编码地点

●编译非常快

●然后运行少量的测试

●一旦编译成功,代码即转移至开发交付准备服务器

●通过功能开关隐藏新功能

●在相同硬件上作为其他站点测试运行

●然后转移至Meta.stackoverflow测试,每天有上千个程序员在使用,一个很好的测试环境

●如果通过则上线,在更广大的社区进行测试

●大量使用静态类和方法,为了更简单及更好的性能

●编码过程非常简单,因为复杂的部分被打包到库里,这些库被开源和维护。.Net 项目数量很低,因为使用了社区共享的部分代码。

●开发者同时使用2到3个显示器,多个屏幕可以显著提高生产效率。


缓存



●缓存一切

●5个等级的缓存

●1级是网络级缓存,缓存在浏览器、CDN以及代理服务器中。

●2级由.Net框架 HttpRuntime.Cache完成,在每台服务器的内存中。

●3级Redis,分布式内存键值存储,在多个支撑同一个站点的服务器上共享缓存项。

●4级SQL Server Cache,整个数据库,所有数据都被放到内存中。

●5级SSD。通常只在SQL Server预热后才生效。

●举个例子,每个帮助页面都进行了缓存,访问一个页面的代码非常简单:

●使用了静态的方法和类。从OOP角度来看确实很糟,但是非常快并有利于简洁编码。

●缓存由Redis和Dapper支撑,一个微型ORM

●为了解决垃圾收集问题,模板中1个类只使用1个副本,被建立和保存在缓存中。监测一切,包括GC操。据统计显示,间接层增加GC压力达到了某个程度时会显著的降低性能。

●CDN Hit 。鉴于查询字符串基于文件内容进行哈希,只在有新建立时才会被再次取出。每天3000万到5000万Hit,带宽大约为300GB到600GB。

●CDN不是用来应对CPU或I/O负载,而是帮助用户更快的获得答案


部署


●每天5次部署,不去建立过大的应用。主要因为

●可以直接的监视性能

●尽可能最小化建立,可以工作才是重点

●产品建立后再通过强大的脚本拷贝到各个网页层,每个服务器的步骤是:

●通过POST通知HAProxy下架某台服务器

●延迟IIS结束现有请求(大约5秒)

●停止网站(通过同一个PSSession结束所有下游)

●Robocopy文件

●开启网站

●通过另一个POST做HAProxy Re-enable

●几乎所有部署都是通过puppet或DSC,升级通常只是大幅度调整RAID阵列并通过PXE boot安装,这样做非常快速。


协作

●团队

●SRE (System Reliability Engineering):5人

●Core Dev(Q&A site)6-7人

●Core Dev Mobile:6人

●Careers团队专门负责SO Careers产品开发:7人

●Devops和开发者结合的非常紧密

●团队间变化很大

●大部分员工远程工作

●办公室主要用于销售,Denver和London除外

●一切平等,些许偏向纽约工作者,因为面对面有助于工作交流,但是在线工作影响也并不大

●对比可以在同一个办公室办公,他们更偏向热爱产品及有才华的工程师,他们可以很好的衡量利弊

●许多人因为家庭而选择远程工作,纽约是不错,但是生活并不宽松

●办公室设立在曼哈顿,那是个人才的诞生地。数据中心不能太偏,因为经常会涉及升级

●打造一个强大团队,偏爱极客。早期的微软就聚集了大量极客,因此他们征服了整个世界

●Stack Overflow社区也是个招聘的地点,他们在那寻找热爱编码、乐于助人及热爱交流的人才。


编制预算



●预算是项目的基础。钱只花在为新项目建立基础设施上,如此低利用率的 web server还是3年前数据中心建立时购入。


测试


●快速迭代和遗弃

●许多测试都是发布队伍完成的。开发拥有一个同样的SQL服务器,并且运行在相同的Web层,因此性能测试并不会糟糕。

●非常少的测试。Stack Overflow并没有进行太多的单元测试,因为他们使用了大量的静态代码,还有一个非常活跃的社区。

●基础设施改变。鉴于所有东西都有双份,所以每个旧配置都有备份,并使用了一个快速故障恢复机制。比如,keepalived可以在负载均衡器中快速回退。

●对比定期维护,他们更愿意依赖冗余系统。SQL备份用一个专门的服务器进行测试,只为了可以重存储。计划做每两个月一次的全数据中心故障恢复,或者使用完全只读的第二数据中心。

●每次新功能发布都做单元测试、集成测试盒UI测试,这就意味着可以预知输入的产品功能测试后就会推送到孵化网站,即meta.stackexchange(原meta.stackoverflow)。


监视/日志


●当下正在考虑使用http://logstash.net/做日志管理,目前使用了一个专门的服务将syslog UDP传输到SQL数据库中。网页中为计时添加header,这样就可以通过HAProxy来捕获并且融合到syslog传输中。

●Opserver和Realog用于显示测量结果。Realog是一个日志展示系统,由Kyle Brandt和Matt Jibson使用Go建立。

●日志通过HAProxy负载均衡器借助syslog完成,而不是IIS,因为其功能比IIS更丰富。


关于云


●还是老生常谈,硬件永远比开发者和有效率的代码便宜。基于木桶效应,速度肯定受限于某个短板,现有的云服务基本上都存在容量和性能限制。

●如果从开始就使用云来建设SO说不定也会达到现在的水准。但毫无疑问的是,如果达到同样的性能,使用云的成本将远远高于自建数据中心。


性能至上


●StackOverflow是个重度的性能控,主页加载的时间永远控制在50毫秒内,当下的响应时间是28毫秒。

●程序员热衷于降低页面加载时间以及提高用户体验。

●每个独立的网络提交都予以计时和记录,这种计量可以弄清楚提升性能需要修改的地方。

●如此低资源利用率的主要原因就是高效的代码。web server的CPU平均利用率在5%到15%之间,内存使用为15.5 GB,网络传输在20 Mb/s到40 Mb/s。SQL服务器的CPU使用率在5%到10%之间,内存使用是365GB,网络传输为100 Mb/s到200 Mb/s。这可以带来3个好处:给升级留下很大的空间;在严重错误发生时可以保持服务可用;在需要时可以快速回档。


学到的知识



1.为什么使用MS产品的同时还使用Redis?什么好用用什么,不要做无必要的系统之争,比如C#在Windows机器上运行最好,我们使用IIS;Redis在*nix机器上可以得到充分发挥,我们使用*nix。


2. Overkill即策略。平常的利用率并不能代表什么,当某些特定的事情发生时,比如备份、重建等完全可以将资源使用拉满。


3. 坚固的SSD。所有数据库都建立在SSD之上,这样可以获得0延时。

4. 了解你的读写负载。


5. 高效的代码意味着更少的主机。只有新项目上线时才会因为特殊需求增加硬件,通常情况下是添加内存,但在此之外,高效的代码就意味着0硬件添加。所以经常只讨论两个问题:为存储增加新的SSD;为新项目增加硬件。


6. 不要害怕定制化。SO在Tag上使用复杂查询,因此专门开发了所需的Tag Engine。


7. 只做必须做的事情。之所以不需要测试是因为有一个活跃的社区支撑,比如,开发者不用担心出现“Square Wheel”效应,如果开发者可以制作一个更更轻量级的组件,那就替代吧。


8. 注重硬件知识,比如IL。一些代码使用IL而不是C#。聚焦SQL查询计划。使用web server的内存转储究竟做了些什么。探索,比如为什么一个split会产生2GB的垃圾。


9. 切勿官僚作风。总有一些新的工具是你需要的,比如,一个编辑器,新版本的Visual Studio,降低提升过程中的一切阻力。


10. 垃圾回收驱动编程。SO在减少垃圾回收成本上做了很多努力,跳过类似TDD的实践,避免抽象层,使用静态方法。虽然极端,但是确实打造出非常高效的代码。


11. 高效代码的价值远远超出你想象,它可以让硬件跑的更快,降低资源使用,切记让代码更容易被程序员理解。


来源HighScalability,CSDN编译整理(编译/仲浩 审校/魏伟)

链接:http://www.csdn.net/article/2014-07-22/2820774-stackoverflow-update-560m-pageviews-a-month-25-servers

发表在 technologys | .NET技术+25台服务器怎样支撑世界第54大网站已关闭评论

高可用级别与宕机时间

点击查看原图

发表在 technologys | 高可用级别与宕机时间已关闭评论

微信、陌陌等著名IM软件设计架构详解

对微信、陌陌等进行了分析,发出来分享一下(时间有些久了)
电量:对于移动设备最大的瓶颈就是电量了。因为用户不可能随时携带电源,充电宝。所以必须考虑到电量问题。那就要检查我们工程是不是有后台运行,心跳包发送时间是不是合理。
流量:对于好多国内大部分屌丝用户来说可能还是包月30M,那么我们必须站在广大用户角度来考虑问题了。一个包可以解决的就一个包。
点击查看原图
网络:
这个也是IM最核心的内容了,我们要做到在任何网络下等顺畅聊天那就不容易了,好多公司都用的xmpp框架,如果在强网络环境下,xmpp完全没有问题。但是那种弱网络环境下xmpp就束手无策啦,用户体验就很垃圾了。
个人觉得xmpp 可以玩玩(参考看这个 RFC3920RFC3921   ), 但是用来真正的产品就差远了。如果遇到一个做IM 的朋友张口闭口都说xmpp 的话,那么不用沟通了,肯定不是什么好产品。微信、QQ以前也曾用过xmpp,但是最后也放弃了xmpp,就知道xmpp有很多弊端了,还有就是报文太大,好臃肿,浪费流量。为了保证稳定,微信用了长链接和短链接相结合,例如:
1 、两个域名
微信划分了http模式(short链接)和 tcp 模式(long 链接),分别应对状态协议和数据传输协议
long.weixin.qq.com  dns check 112.64.237.188 112.64.200.218
 short.weixin.qq.com  dns check  ( 112.64.237.186 112.64.200.240)
说明
 HTTP协议扩展,运行8080 端口http body为二进制(protobuf)。
 主要用途(接口)
用户登录验证;
好友关系(获取,添加);
消息sync (newsync),自有sync机制;
获取用户图像;
用户注销;
行为日志上报。
朋友圈发表刷新
 2.2  long.weixin.qq.com  
  tcp 长连接, 端口为8080,类似微软activesync的二进制协议。
 主要用途(接口)
接受/发送文本消息;
接受/发送语音;
接受/发送图片;
接受/发送视频文件等。
 
 所有上面请求都是基于tcp长连接。在发送图片和视频文件等时,分为两个请求;第一个请求是缩略图的方式,第二个请求是全数据的方式。
 
2.2.1 数据报文方面
增量上传策略:
每次8k左右大小数据上传,服务器确认;在继续传输。
 
图片上传:
先传缩略图,传文本消息,再传具体文件
 
下载:
先下载缩略图, 在下载原图
下载的时候,全部一次推送。
附录
3.1  用户登录验证
POST /cgi-bin/micromsg-bin/auth HTTP/1.1
Accept: **
User-Agent: Mozilla/4.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 174
 
3.3 消息sync (newsync)
POST /cgi-bin/micromsg-bin/newsync HTTP/1.1
User-Agent: Android QQMail HTTP Client
Cache-Control: no-cache
Connection: Keep-Alive
Content-Type: application/octet-stream
accept: **
Content-Length:  206
 
3.5 用户注销
POST /cgi-bin/micromsg-bin/iphoneunreg HTTP/1.1
Accept: */*
User-Agent: Mozilla/4.0
Cotent-Type: application/x-www-form-urlencoded
Content-Length: 271
 
3.6 行为日志上报
POST /cgi-bin/stackreport?version=240000a7&filelength=1258&sum=7eda777ee26a76a5c93b233eed504c7d&reporttype=1&username=jolestar HTTP/1.1
Content-Length: 736
Content-Type: binary/octet-stream
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
从现在互联网的发展而言,IM和视频(包括IM里面视频通话)是一个方向,这些都应该成为互联网的基础设施,就像浏览器一样。现在IM还没有一个很好的解决方案,XMPP并不能很好地做到业务逻辑独立开来。从IM的本质来看,IM其实就是将一条消息从一个地方传输到另外一个地方,这个和TCP很像,为什么不实现一个高级点的TCP协议了,只是将TCP/IP里面的IP地址换成了一个类似XMPP的唯一ID而已,其他的很多细节都可以照搬TCP协议。有了这个协议之后,将业务逻辑在现有HTTP server的基础上做,例如发送语音和图片就相当于上传一个文件,服务器在处理完这个文件后就发一条特殊的IM消息。客户端收到这个IM消息后,按照IM消息里面urlHTTP server取语音文件和图片文件。将HTTP serverIM server打通之后,可以做很多事情。但将这个两个server合并在一块并不是一个好事,不然腾讯也不会有2005年的战略转型了。从现在的情况来看,应用除了游戏,都没怎么赚钱,现在能够承载赚钱业务的还是以web为主。IM不可以赚钱,但没有却是不行的,就像一个地方要致富,不修路是不行的道理一样。

上面说到了protobuf ,就简单介绍下:

          JSON相信大家都知道是什么东西,如果不知道,那可就真的OUT了,GOOGLE一下去。这里就不介绍啥的了。

Protobuffer大家估计就很少听说了,但如果说到是GOOGLE搞的,相信大家都会有兴趣去试一下,毕竟GOOGLE出口,多属精品。

Protobuffer是一个类似JSON的一个传输协议,其实也不能说是协议,只是一个数据传输的东西罢了。

那它跟JSON有什么区别呢?

        跨语言,这是它的一个优点。它自带了一个编译器,protoc,只需要用它进行编译,可以编译成JAVApythonC++代码,暂时只有这三个,其他就暂时不要想了,然后就可以直接使用,不需要再写任何其他代码。连解析的那些都已经自带有的。JSON当然也是跨语言的,但这个跨语言是建立在编写代码的基础上。



陌陌设计:
陌陌发展刚开始由于规模小,30-40W连接数(包括Android后台长连接用户),也使用XMPP由于XMPP的缺点:流量大(基于XML),不可靠(为传统固定网络设计,没有考虑WIFI/2G/3G/地铁/电梯等复杂网络场景),交互复杂(登陆需5-6次,尤其是TLS握手);XMPP丢消息的根本原因:服务端和客户端处于半关闭状态,客户端假连接状态,服务端有收不到回执;Server端连接层和逻辑层代码没有解耦分离,常常重启导致不可用;
点击查看原图

消息中转:
点击查看原图
链接层:
点击查看原图
逻辑层:
点击查看原图
通讯协议设计:
点击查看原图
高效:弱网络快速的收发
可靠:不会丢消息
易于扩展
协议格式:
点击查看原图
Redis协议:

点击查看原图


点击查看原图点击查看原图




点击查看原图
是啊发
点击查看原图
点击查看原图
点击查看原图
阿萨德发阿发a
点击查看原图
优化
   连接层(参见通讯服务器组成):只做消息转发,允许随时重启更新,设计原则简单/异步;单台压测试连接数70W;现状:1.5亿用户,月活5000W+,连接数1200W+
   逻辑层(参见通讯服务器组成):用户会话验证即登陆、消息存取、异步队列
   采用私有通讯协议,目标:高效,弱网络快速收发;可靠:不会丢消息;易于扩展;参考协议格式:REDIS协议;参见协议格式、基于队列的消息协议、基于队列的交互、基于版本号的消息协议、基于版本号的交互等;
   核心的长连接只用于传输轻量的实时数据,图片、语音等都开新的TCPHTTP连接;
            一切就绪后,最重要的就是监控,写一个APP查看所有的运营状态,每天观察;
   如何选择最优路线,即智能路由;
二、智能路由、连接策略:
多端口、双协议支持
应对移动网关代理的端口限制
         支持TCPHTTP两种协议
         根据备选IP列表进行并发测速(IP+端口+协议)
         后端根据终端连接情况,定时更新终端的备选IP列表
         终端在连接空闲时上报测速数据,便于后端决策
         TCP协议不通,自动切换到http
         优先使用最近可用IP
        并发测速,根据终端所处的位置下发多组IPPORT,只用IP,不用域名,手机上的DNS50%不准

负载均衡器(LVS...)的问题– 单点失效

      单点性能瓶颈
      负载均衡从客户端开始做起• 域名负载的问题

      域名系统不可靠– 更新延迟大  

WNS(wireless network services)
点击查看原图
1解决移动互联网开发常见问题:
通道:数据交互、大数据上传、push
网络连接:大量长链接管理、链接不上、慢、多地分布
运营支撑:海量监控、简化问题定位
登录&安全:登录鉴权、频率控制

点击查看原图点击查看原图

移动互联网特点:
1、高延时:  信道建立耗时( 高RTT)
2、低宽带、高丢包
3、多运营商(电信,移动,联通等)
4、复杂网络  
    -2G,3G,4G,wifi。cmwap,cmnet。。
    -网关限制:协议,端口
5、用户流动性大,上网环境复杂

WNS 性能指标:
点击查看原图点击查看原图点击查看原图点击查看原图
1、开发时间:历史一年半
2、链接成功率-99.9%
3、极端网络环境下成功率-由于常见app
4、crash率 -0.02%(crash次数/登录用户数)

微信后台系统架构
背景:
A、分布式问题收敛
  后台逻辑模块专注逻辑,快速开发
可能读取到过时的数据是个痛点
需要看到一致的数据
B、内部定义
  数据拥有两个以上的副本
如果成功提交了变更,那么不会再返回旧数据
推演:
1增加一个数据
2 序列号发生器,偏序
 约束:只能有一个client操作
client有解决冲突的能力
问题转移:client如何分布?
3 修改集群中一个制定的key的value
1)覆盖他
2)根据value的内容做修改
if value = 1 then value :=2 
通用解法:
1)paxos算法
 工程难度
一切可控

分布式算法设计:
 2)quorum算法(2011)
再单个key上面运算
真是系统约束
类paxos方案,简化
为每次变更选举(by key)
算法过程
 提议/变更/同步/广播

系统架构
点击查看原图
写流程
点击查看原图
Replication & Sharding 
 权衡点
  自治,负载均衡,扩散控制
 replication->relation

容灾抵消
同城(上海)多数派存活
三园区(独立供电,独立)


Sharding

一组KV6 为一个单位

1、人工阶段
 局部扩容,影响收敛9
2均匀分布 制定分段hash32 (string)
 翻倍扩容

3一致性哈希
具体实现?
1、业务侧快速开发
 存储需要提供强一致性
丰富的数据模型支持(结构化、类SQL/KV)
条件读,条件写

2 业务增长迅速,系统要能够方便的横向扩容
3设备故障/短时节点实效便成为常态,容灾自动化,主碑可写无需人工介入
4小数据
点击查看原图
存储模型
 纯内存
Bitcask
小表系统
LSM-tree
点击查看原图
小表系统
1、解决放大问题
2、数据按变更聚集存储
3、Affected1
   ChangeTable
(1+2+。。。。+n-1+total)/n
4、分裂与合并
数据流动
1、自动化迁移
2、节点同时做代理
3、合并磁盘io

同步流量
1、数据vs 操作
2、幂等
3、保底策略

通信包量
 1、动态合并
    100K qps
    200% -10%
3、权衡与估算
设计要点
1、吞吐量
2、异步化
3、复杂度
4、libco
自动修复系统
1、不要让错误累计
2、全量扫描
bitcask 的一些变化
1、内存限制
2、全内存
发表在 technologys | 微信、陌陌等著名IM软件设计架构详解已关闭评论

IF-ERRORLEVEL

@echo off
: p
ping 61.152.XX.XX
IF ERRORLEVEL 1 goto aa
IF ERRORLEVEL 0 goto bb
:aa
echo 正在重启软件服务...
net stop MSSQLSERVER
net start MSSQLSERVER
goto p
:bb
echo 继续ping中。。。
goto p

 

 

if ERRORLEVEL nubmer commend
例:if ERRORLEVEL 1 echo 返回值等于1

那么大家就要问了,我怎么获取到前一个命令的返回值呢?
方法很简单,拿ping来说,我们先运行一个ping 127.0.0.1
运行结果是Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
这时候我们输入,echo %errorlevel%,就可以看到返回值是0,
然后我们在ping一个不存在的ip,比如192.192.192.192
ping命令显示 Request timed out.。
ok,我们在用echo %errorlevel%查一下返回值是多少。
现在变成了1。

你也可以用这个方法来查询其他命令的返回值,比如copy、dir等等。
当然if ERRORLEVEL对数值的比较方法不仅仅限于等于。在微软的帮助中我们可以看到:

IF %ERRORLEVEL% LEQ 1 goto okay

这里的LEQ表示“小于等于”,全部的比较参数如下:
EQU - 等于
NEQ - 不等于
LSS - 小于
LEQ - 小于或等于
GTR - 大于
GEQ - 大于或等于

如有错误,感谢指正。

IF-ERRORLEVEL

建立TEST4.BAT,内容如下:
@ECHO OFF 
XCOPY C:\AUTOEXEC.BAT D:\
IF ERRORLEVEL 1 ECHO 文件拷贝失败 
IF ERRORLEVEL 0 ECHO 成功拷贝文件 
然后执行文件:
C:\>TEST4
如果文件拷贝成功,屏幕就会显示“成功拷贝文件”,否则就会显示“文件拷贝失败”。 
IF ERRORLEVEL 是用来测试它的上一个DOS命令的返回值的,注意只是上一个命令的返回值,而且返回值必须依照从大到小次序顺序判断。
因此下面的批处理文件是错误的:
@ECHO OFF 
XCOPY C:\AUTOEXEC.BAT D:\ 
IF ERRORLEVEL 0 ECHO 成功拷贝文件 
IF ERRORLEVEL 1 ECHO 未找到拷贝文件 
IF ERRORLEVEL 2 ECHO 用户通过ctrl-c中止拷贝操作 
IF ERRORLEVEL 3 ECHO 预置错误阻止文件拷贝操作 
IF ERRORLEVEL 4 ECHO 拷贝过程中写盘错误 
无论拷贝是否成功,后面的: 
未找到拷贝文件 
用户通过ctrl-c中止拷贝操作 
预置错误阻止文件拷贝操作 
拷贝过程中写盘错误
都将显示出来。 
以下就是几个常用命令的返回值及其代表的意义: 
backup 
0 备份成功 
1 未找到备份文件 
2 文件共享冲突阻止备份完成 
3 用户用ctrl-c中止备份 
4 由于致命的错误使备份操作中止 
diskcomp 
0 盘比较相同 
1 盘比较不同 
2 用户通过ctrl-c中止比较操作 
3 由于致命的错误使比较操作中止 
4 预置错误中止比较 
diskcopy 
0 盘拷贝操作成功 
1 非致命盘读/写错 
2 用户通过ctrl-c结束拷贝操作 
3 因致命的处理错误使盘拷贝中止 
4 预置错误阻止拷贝操作 
format 
0 格式化成功 
3 用户通过ctrl-c中止格式化处理 
4 因致命的处理错误使格式化中止 
5 在提示“proceed with format(y/n)?”下用户键入n结束 
xcopy 
0 成功拷贝文件 
1 未找到拷贝文件 
2 用户通过ctrl-c中止拷贝操作 
4 预置错误阻止文件拷贝操作 
5 拷贝过程中写盘错误

发表在 windows | 标签为 | IF-ERRORLEVEL已关闭评论

Imagemagick resize

一些其它参考:

http://blog.sina.com.cn/s/blog_ba532aea0101bty5.html

 

将一个200x304大小的图像缩小为100x152(长宽各缩短一半)。
convert page200.png -resize 100x152 page100.png
上面的 100x152,指定了目标文件的长和宽。
 你也可以只指定目标文件宽度,这样它的高度会等比例放大:
convert page200.png -resize 100 page100.png
或者只指定高度:
convert page200.png -resize x152 page100.png
以上三句命令,其结果都是一样的。

 

一些命令:

 

1,获取图片信息

$identify image.png 
image.png PNG 559x559 559x559+0+0 8-bit sRGB 467KB 0.000u 0:00.008 
如果只需要获取宽高:

$identify -format "%wx%h" image.png 
2,放大,缩小 -resize

$convert image.png -resize 200x200 resize.png 
也可以按照比例(缩小一半):

$convert image.png -resize 50% resize.png 
还可以多次缩放(先缩小一半,再放大一倍,效果就是变模糊了):

$convert image.png -resize 50%  -resize 200%  resize.png 
3,放大,缩小 -sample

与resize的区别在于-sample只进行了采样,没有进行插值,所以用来生成缩略图最合适

$convert image.png -sample 50% sample.png 
这个处理的效果就是马赛克:

$convert image.png -sample 10% -sample 1000% sample.png 
4,裁剪 -crop

从(50,50)位置开始,裁剪一个100X100大小的图片:

$convert image.png -crop 100x100+50+50 crop.png 
如果不指定位置,则按照这个大小分隔出小图片,这个命令生成crop-0.png,crop-1.png,crop-2.png……:

$convert image.png -crop 100x100 crop.png 
可以指定裁剪位置的相对位置 -gravity:

$convert image.png -gravity northeast -crop 100x100+0+0 crop.png 
-gravity即指定坐标原点,有northwest:左上角,north:上边中间,northeast:右上角,east:右边中间……
5,旋转 -rotate

$convert image.png -rotate 45 rotate.png 
默认的背景为白色,我们可以指定背景色:

$convert image.png -backround black -rotate 45 rotate.png 
$convert image.png -background #000000 -rotate 45 rotate.png 
还可以指定为透明背景色:

$convert image.png -background rgba(0,0,0,0) -rotate 45 rotate.png 
6,合并

合并指的是将一张图片覆盖到一个背景图片上:

$convert image.png -compose over overlay.png -composite newimage.png 
-compose指定覆盖操作的类型,其中over为安全覆盖,另外还有xor、in、out、atop等等
覆盖的位置可以通过-gravity指定:

$convert image.png -gravity southeast -compose over overlay.png -composite newimage.png 
这是将图片覆盖到底图的右下角。
7,更改图片的alpha通道

分两步:

$convert image.png -define png:format=png32  image32.png 
$convert image32.png -channel alpha -fx "0.5" imagealpha.png 
这个命令首先将image.png的格式改为png32(确保有alpha通道),然后更改alpha通道置为0.5,也就是半透明,值的范围为0到1.0
可以使用将一张透明图片覆盖到原图上的方式做水印图片:

$convert image.png -gravity center -compose over overlay.png -composite newimage.png 
$convert image.png -gravity southeast -compose over overlay.png -composite newimage.png 
8,拼接

横向拼接(+append),下对齐(-gravity south):

$convert image1.png image2.png image3.png -gravity south +append result.png 
纵向拼接(-append),右对齐(-gravity east):

$convert image1.png image2.png image3.png -gravity east -append result.png 
9,格式转换

$convert image.png image.jpg 
$convert image.png -define png:format=png32 newimage.png 
10,文字注释

$convert image.png -draw "text 0,20 'some text'" newimage.png 
从文件text.txt中读取文字,指定颜色,字体,大小,位置:

$convert source.jpg -font xxx.ttf -fill red -pointsize 48 -annotate +50+50 @text.txt result.jpg 
11,去掉边框
$convert image.png -trim -fuzz 10% newimage.png

12,GIF 需要两步
用imagemagick生成gif的缩略图不能一步到位,需要两步操作

第一步 : convert sinykk.gif -coalesce sinykk_coalesce.gif

第二步 : convert  sinykk_coalesce.gif -resize "300X300>"  sinykk_end.gif

其中: "300X300>" 这个是当GIF图片没有300的长宽将不进行长宽操作

发表在 technologys | Imagemagick resize已关闭评论

pptp

1、检查服务器是否有必要的支持。如果检查结果没有这些支持的话,是不能安装pptp的。执行指令:
#modprobe ppp-compress-18 && echo ok(用模块方式支持MPPE加密模式浏览,如果内核支持检测不到。)
这条执行执行后,显示“ok”则表明通过。

2、安装ppp和iptables。默认情况下,完整的CentOS是带有这两个组件的,但是精简版的系统可能没有。我们输入下面的命令来确认,如果没有则进行安装,有的话系统不会做任何动作:
#yum install -y iptables

3、安装pptp。这个软件在yum源里是没有的,我们需要手动下载。
加入yum源:
#rpm -Uvh http://poptop.sourceforge.net/yum/stable/rhel6/pptp-release-current.noarch.rpm
#yum install  -y pptpd

4、配置pptp。首先我们要编辑/etc/pptpd.conf文件:
#vim /etc/pptpd.conf

localip 192.168.11.1
remoteip 192.168.11.2-102  (最大限制100个连接)
将前面的“#”注释符去掉,更改为你期望的IP段值。localip表示服务器的IP,remoteip表示分配给客户端的IP地址,可以设置为区间。这里我们使用pptp默认的配置:

再编辑/etc/ppp/options.pptpd文件,为VPN添加Google DNS:
#vim /etc/ppp/options.pptpd
在末尾添加下面两行:
ms-dns 8.8.8.8
ms-dns 8.8.4.4

注意:最好打开这个文件里的debug选项(去掉debug前面的“#”),以方便我们在出错的查看日志排错。错误日志在/var/log/messages里,用命令:cat /var/log/messages | grep pptpd 查看有关PPTP的错误信息。

5、设置pptp VPN账号密码。我们需要编辑/etc/ppp/chap-secrets这个文件:
#vim /etc/ppp/chap-secrets
在这个文件里面,按照“用户名 pptpd 密码 *”的形式编写,一行一个账号和密码。比如添加用户名为test,密码为1234的用户,则编辑如下内容:
test pptpd 1234 *

6、修改内核设置,使其支持转发。编辑/etc/sysctl.conf文件:
#vim /etc/sysctl.conf
将“net.ipv4.ip_forward”改为1,变成下面的形式:
net.ipv4.ip_forward=1
保存退出,并执行下面的命令来生效它:
#sysctl -p

7、添加iptables转发规则。经过前面的6个步骤,我们的VPN已经可以拨号了,但是还不能访问任何网页。最后一步就是添加iptables转发规则了,输入下面的指令:
两种修改方法:命令行或修改/etc/sysconf/iptables 文件
iptables -t nat -A POSTROUTING -o eth0 -s 192.168.11.0/24 -j MASQUERADE

iptables -L -t nat 可以看到:
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  192.168.11.0/24      anywhere
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

在/etc/sysconf/iptables 文件 允许ping
-A RH-Firewall-1-INPUT -s 192.168.11.0/255.255.255.0 -p icmp -m icmp --icmp-type 8 -j ACCEPT
service iptables save  保存
service iptables restart 重启

8.
设置开机自动运行服务。我们最后一步是将pptp和iptables设置为开机自动运行,这样就不需要每次重启服务器后手动启动服务了。当然你不需要自动启动服务的话可以忽略这一步。输入指令:
#chkconfig pptpd on
#chkconfig iptables on

 

限制pptp vpn用户单个连接的简单方法

在/etc/ppp文件夹下面建立一个名为auth-up的文件。在里面写入如下内容即可:

#!/bin/sh
# get the username/ppp line number from the parameters
REALDEVICE=$1
USER=$2
# create the directory to keep pid files per user
mkdir -p /var/run/pptpd-users
# if there is a session already for this user, terminate the old one
if [ -f /var/run/pptpd-users/$USER ]; then
kill -HUP `cat /var/run/pptpd-users/$USER`
fi
# copy the pid file of current user to /var/run/pptpd-users
cp "/var/run/$REALDEVICE.pid" /var/run/pptpd-users/$USER

来源:http://vastars.info/linux/pptp-vpn.html

 

VPN 架设中一些问题的解决方法(pptpd)

1. windows 10 下服务器推送DNS无效

控制面板 > 网络与共享 > VPN所属适配器 > 属性 > IPv4 > 高级 > 取消自动跃点并设置值为 15

IPv6 同上

Control Panel > Network and Sharing Center > Change adapter settings > Right click your Ethernet or Wifi adapter > Properties > double click IPv4 > Advanced > Uncheck Automatic Metric > Enter 15 for interface metric > OK > OK.

On that same Properties page, double click IPv6 > Advanced > Uncheck Automatic Metric > Enter 15 for interface metric > OK > OK.

2.VPN可以连接成功,但不能正常上网,messages中记录如下:

       Cannot determine ethernet address for proxy ARP

   该问题主要出在没有相关的转发规则。需要进行如下配置:

   a.打开配置文件/etc/sysctl.conf,修改配置项net.ipv4.ip_forward为1:    

# Controls IP packet forwarding

net.ipv4.ip_forward = 1

       该配置项用于允许ip转发。

   b.还需在iptables中加入NAT转换:

       iptables -t nat -A POSTROUTING -s 192.168.0.0/255.255.255.0 -j SNAT --to-source 192.168.0.88

       其中192.168.0.0/255.255.255.0为VPN的内部网络,192.168.0.88当然就是服务器的地址了。

3. 如sysctl -p

error: "net.bridge.bridge-nf-call-ip6tables" is an unknown key
error: "net.bridge.bridge-nf-call-iptables" is an unknown key

error: "net.bridge.bridge-nf-call-arptables" is an unknown key

调用并重试pptpd

modprobe bridge
lsmod|grep bridge

 

Windows7 619一些参考:

http://www.wanghailin.cn/linux-pptpd-619-internet/

GRE: read(fd=6,buffer=b77c8480,len=8196) from PTY failed:

Changing /etc/ppp/pptpd-options to the following options worked for me:

refuse-pap
refuse-chap
refuse-mschap
#require-chap
#require-mschap
#require-mschap-v2
#require-mppe-128
mppe-stateful

 

 

CentOS 7 参考:

http://www.wanghailin.cn/centos-7-vpn/

 

一些MTU参考:

Ethernet MinSize = 512bit = 64 Byte
Ethernet MaxSize = 1518 Byte
so Ethernet IP MTU = 1518 – 18 ( 6 SRCMAC+ 6 DSTMAC+ 2 TYPE+ 4 CRC) = 1500 B
so Ethernet IP TCP MSS = 1500 – 40 ( 20 IP_HEADER + 20 TCP_HEADER) = 1460 B
so Ethernet IP UDP MTU/MRU = 1500 – 28 ( 20 IP_HEADER + 8 UDP_HEADER ) = 1472 B
so PPPoE MTU/MRU = 1500 – 8 ( 6 PPPoE_SESSION + 2 PPP_HEADER ) = 1492 B
so TCP over PPPoE MSS = 1492 ( PPPoE MTU/MRU ) – 40 ( 20 IP_HEADER + 20 TCP_HEADER) = 1452
so PPTP MTU/MRU = 1500 – 56 ( 20 IP_HEADER + 20 TCP_HEADER + 12 GRE_HEADER + 4 PPP_HEADER ) = 1444 B
so TCP over PPTP MSS = 1444 ( PPTP MTU/MRU ) – 40 ( 20 IP_HEADER + 20 TCP_HEADER) = 1404
so L2TP MTU/MRU = 1500 – 40 ( 20 IP_HEADER +8 UDP_HEADER + 8 L2TP_HEADER + 4 PPP_HEADER ) = 1460 B
so TCP over L2TP MSS = 1460 ( L2TP MTU/MRU ) – 40 ( 20 IP_HEADER + 20 TCP_HEADER) = 1420 B

so
PPTP over PPPoE MTU/MRU = 1492 ( PPPoE MTU/MRU ) – 56 ( 20 IP_HEADER +
20 TCP_HEADER + 12 GRE_HEADER + 4 PPP_HEADER ) = 1436 B
so PPTP over PPTP MTU/MRU = 1444 ( PPTP MTU/MRU ) – 56 ( 20 IP_HEADER + 20 TCP_HEADER + 12 GRE_HEADER + 4 PPP_HEADER ) = 1388 B
so PPTP over L2TP MTU/MRU = 1460 ( L2TP MTU/MRU ) – 56 ( 20 IP_HEADER + 20 TCP_HEADER + 12 GRE_HEADER + 4 PPP_HEADER ) = 1404 B
so L2TP over PPPoE MTU/MRU = 1492 ( PPPoE MTU/MRU ) – 40 ( 20 IP_HEADER +8 UDP_HEADER + 8 L2TP_HEADER + 4 PPP_HEADER ) = 1452 B
so L2TP over PPTP MTU/MRU = 1444 ( PPTP MTU/MRU ) – 40 ( 20 IP_HEADER +8 UDP_HEADER + 8 L2TP_HEADER + 4 PPP_HEADER ) = 1404 B
so L2TP over L2TP MTU/MRU = 1460 ( L2TP MTU/MRU ) – 40 ( 20 IP_HEADER +8 UDP_HEADER + 8 L2TP_HEADER + 4 PPP_HEADER ) = 1420 B

发表在 linux | 标签为 , | pptp已关闭评论

vmware的后台启动

摘自网络:

 

vmware界面启动呢,消耗很大的资源,相信后台启动是大家喜欢的方式,简单介绍以下几种常用的命令如下:

 

打开dos窗口,执行以下命令:

进入虚拟机安装目录:cd C:\Program Files (x86)\VMware\VMware Workstation
启动:vmrun -T ws start "C:\ubuntu/Ubuntu.vmx" nogui

[说明:C:\ubuntu/Ubuntu.vmx 就是你在虚拟机中创建好的ubuntu系统,以下同样]
查看是否启动成功:tasklist|findstr vmware
[说明:这个就是 unix系统的中ps -ef|grep "vmware"]

正常关机:vmrun stop "C:\ubuntu/Ubuntu.vmx" soft
强制关机:vmrun stop "C:\ubuntu/Ubuntu.vmx" hard
挂起休眠:vmrun suspend "C:\ubuntu/Ubuntu.vmx" hard | soft

列出正在运行的虚拟机:vmrun list

以上是使我们常用到的操作,但是每次都输入肯定比较麻烦,写一个bat脚本,方便很多,贴出来如下:

 

::start vmware    
@echo s:start vmware p:stop vmware 
@set /p select=输入: 
@if "%select%" == "s" goto start
@if "%select%" == "p" goto stop

:stop
     cd C:\Program Files (x86)\VMware\VMware Workstation
     vmrun stop "C:\ubuntu/Ubuntu.vmx" hard
     @echo stop succeed!
     pause
     exit
:start
     cd C:\Program Files (x86)\VMware\VMware Workstation
     vmrun list
     vmrun -T ws start "C:\ubuntu/Ubuntu.vmx" nogui
     tasklist|findstr vmware
     @echo start succeed!
     pause
     exit
发表在 virtual machine | 标签为 | vmware的后台启动已关闭评论

CentOS6.4系统下安装和创建KVM虚拟机

一、安装kvm 

1 在安装CentOS6.3时可以选择安装好kvm



2 如果未安装好kvm,请按照下列方式安装

[创建本地yum源]

挂载iso文件

mount -o loop -t iso9660 CentOS-6.3-x86_64-bin-DVD1.iso /mnt

设置本地yum源

在/etc/yum.repos.d/创建   “任意文件名.repo"    文件  

vi 刚才新建的文件名编辑

【localyum】任意名称 ,不能有空格。

name= local yum  任意名称

baseurl=file:////mnt/Packages      这个路径是自定的。Server为光盘中的Server目录 ,Packages与Server放在同一目录下。即/software目录下

enabled=1   代表   生效     0为不生效

gpgcheck=1   检查gpgkey  1 生效   0不生效

gpgkey=file:///software    安装光盘里有这个文件        不指定  安装时,可能提示没有注册

保存退出

执行命令 yum clean all



(1) kvm需要有 CPU 的支持(Intel VT 或 AMD SVM)

[root@moniter ~]#egrep '^flags.*(vmx|svm)' /proc/cpuinfo

(2) 安装kvm libvirted

yum install kvm kmod-kvm qemu kvm-qemu-img virt-viewer virt-manager libvirt libvirt-python python-virtinst

yum groupinstall KVM

(3) 启动libvirted

service messagebus start

service haldaemon start

service libvirtd start

chkconfig messagebus on

chkconfig haldaemon on

chkconfig libvirtd on

(4)检查kvm是否安装成功

[root@moniter ~]#virsh -c qemu:///system list

Id Name                 State

----------------------------------

(5)kvm模块

/sbin/lsmod | grep kvm



二、配置网桥

vi /etc/sysconfig/network-scripts/ifcfg-br0

DEVICE=br0

TYPE=Bridge

BOOTPROTO=static

BROADCAST=10.207.20.255

IPADDR=10.207.20.200

NETMASK=255.255.255.0

NETWORK=10.207.20.0

ONBOOT=yes

b、

vi /etc/sysconfig/network-scripts/ifcfg-eth0

# Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet

DEVICE=eth0

BOOTPROTO=none

ONBOOT=yes

BRIDGE=br0

c、

重起网络服务生效

service network restart

d、

echo 1 > /proc/sys/net/ipv4/ip_forward  #虚拟机上网

e、

检查桥接网络

[root@moniter ~]# brctl show

bridge name     bridge id               STP enabled     interfaces

br0             8000.842b2b74e1b6       no              eth0

virbr0          8000.000000000000       yes

br0是我们配置的桥接网卡,virbr0是系统脚本自动配置的NAT网卡



三、安装vnc

注意:CentOS6.3 VNC的命名rpm为tiggervnc-server

(1)

yum install tigervnc-server

(2)

vi /etc/sysconfig/vncservers

#加一行

VNCSERVERS="1:root"

(3)

vncpasswd

创建密码

(4)

/etc/init.d/vncserver start

(5)

# netstat -nulpt | grep vnc

tcp        0      0 0.0.0.0:5901                0.0.0.0:*                   LISTEN      29167/Xvnc

tcp        0      0 0.0.0.0:6001                0.0.0.0:*                   LISTEN      29167/Xvnc

tcp        0      0 :::6001                     :::*                        LISTEN      29167/Xvnc

表示vnc可以使用了



四、创建kvm虚拟机

virsh-install

    1、输入虚拟机名称

    2、分配多少内存

    3、处理器的个数

    4、此步可以直接输入iso的位置或是url

    5、虚拟机类型KVM

    6、定义虚拟机磁盘映像的位置

    7、磁盘的大小

    6、指定哪个桥或者可以指定多个桥

    7、额外的控制台和KS文件

    8、连接到系统参数

    参数说明注意每行都要空格

    -n 虚拟机名称

    -r 分配虚拟机内存大小

    --vcpus 分配虚拟cpu个数

    -c 镜像文件位置

    --vnc --vncport=5901 --vnclisten=0.0.0.0 启动图形安装界面

    --virt-type 虚拟机模式

    -f 虚拟机系统文件存储目录

    -s 分配磁盘大小(GB)

    -w 联网方式(birdge bridge:br0/nat bridge:virbr0)

    --os-type='windows' --os-variant=win2k3 安装windows最好加上这个否则会报错

    virt-install工具安装虚拟机后,在目录/etc/libvirt/qemu/下生成xml配置文件

    -s 用来指定虚拟磁盘的大小单位为GB

    -m 指定虚拟网卡的硬件地址默认virt-install自动产生

    -p 以半虚拟化方式建立虚拟机

    -l 指定安装来源

    -x EXTRA, --extra-args=EXTRA当执行从"--location"选项指定位置的客户机安装时,附加内核命令行参数到安装程序。

    -v, --hvm 设置全虚拟化

virt-install --name=centos6.3  --ram 1024 --vcpus=2 --disk path=/data0/centos-6.3.x86_64.img.img,size=20  --accelerate --cdrom /data0/CentOS-6.3-x86_64-bin-DVD1.iso  --graphics vnc,listen=0.0.0.0,port=5920,  --network bridge=br0  --force  --autostart

执行后,netstat -nulpt | grep 5920 看端口启用否



五、用vnc连接5920完成安装

IP:5920



六、管理kvm虚拟机

virsh --connect qemu:///system

a、如果你修改了一个客户机的xml文件(位于/etc/libvirt/qemu/ 目录),你必须重新定义客户机:

define /etc/libvirt/qemu/vm10.xml

b、启动和停止客户机,运行:

start vm10

c、停止一个客户机,运行

shutdown vm10

d、立即中断一个客户机(类似直接关电源),运行

destroy vm10

e、挂起一个客户机:

suspend vm10

f、恢复客户机:

resume vm10



七、克隆

virt-clone  --connect=qemu:///system \

-o 原虚拟机 -n 新虚拟机 -f /data0/centos5.4/新虚拟机镜像

新虚拟机配置文件需要注意:虚拟机克隆完毕后,需修改vnc端口;MAC地址也是需要注意的。



八、加载磁盘空间

#qemu-img create -f qcow2 disk1.img 50G

#vi /etc/libvirt/qemu/centos1.xml

增加的部分为:



    <disk type='file' device='disk'>

      <source file='/data0/disk1.img'/>

      <target dev='hdb' bus='ide'/>

    </disk>

使配置文件生效

virsh --connect qemu:///system

virsh #define /etc/libvirt/qemu/centos1.xml

重起虚拟机生效

virsh # shutdown centos1

virsh # start centos1

进入虚拟机:

mkfs.ext3 /dev/hdb

mkdir /data

mount /dev/hdb /data

发表在 linux | 标签为 | CentOS6.4系统下安装和创建KVM虚拟机已关闭评论

whois

由于Internet的历史原因,apin负责整个网络IP的整体规划以及北美区 还有部分非洲地区的IP分配管理,与此相应的是,whois.apin.net是IP whois的root server,标准的IP whois查询方法是,首先向whois.apin.net查询某个IP属于哪个大区,然后再向该区的whois 服务器查询此IP的whois详细信息。 
目前负责IPV4的大区 
whois.arin.net 美洲区 北美,包含非洲地区的查询 
whois.apnic.net 亚太区 包括亚洲和澳大利亚 
whois.ripe.net 欧洲区 欧洲/中东(西亚)/北非 
whois.lacnic.net 拉美区 拉丁美洲和加勒比海区域向某个whois服务器提交whois查询的过程 
打开一个到whois服务器的43端口的连接,然后发送要查询的域名 和一个回车换行。如果要查询多个域名,请用空格分开然后从sokect中读取结果。最后服务器将自动断开连接。 
用PHP实现 
验证IP(用 ip2long代替 ereg) 
向whois.arin.net查询,如果数据库中没有相关信息,会给出一个Referral Server的URL,格式如下 
ReferralServer:xxxx然后根据此信息,继续查询。 
whoisip.php 
可以根据ip地址或域名查询whois信息。 

发表在 technologys | whois已关闭评论

zookeeper原理

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等。Zookeeper是hadoop的一个子项目,其发展历程无需赘述。在分布式应用中,由于工程师不能很好地使用锁机制,以及基于消息的协调机制不适合在某些应用中使用,因此需要有一种可靠的、可扩展的、分布式的、可配置的协调机制来统一系统的状态。Zookeeper的目的就在于此。本文简单分析zookeeper的工作原理,对于如何使用zookeeper不是本文讨论的重点。

1 Zookeeper的基本概念

1.1 角色

Zookeeper中的角色主要有以下三类,如下表所示:

点击查看原图

系统模型如图所示:

点击查看原图

1.2 设计目的

1.最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。

2 .可靠性:具有简单、健壮、良好的性能,如果消息m被到一台服务器接受,那么它将被所有的服务器接受。

3 .实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。

4 .等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。

5.原子性:更新只能成功或者失败,没有中间状态。

6 .顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。

2 ZooKeeper的工作原理

Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。

为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。

每个Server在工作过程中有三种状态:

  • LOOKING:当前Server不知道leader是谁,正在搜寻

  • LEADING:当前Server即为选举出来的leader

  • FOLLOWING:leader已经选举出来,当前Server与之同步

2.1 选主流程

当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic paxos流程:

  1. 1 .选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;

  2. 2 .选举线程首先向所有Server发起一次询问(包括自己);

  3. 3 .选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;

  4. 4.  收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;

  5. 5.  线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。

通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1.

每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图如下所示:

点击查看原图

fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。其流程图如下所示:

 点击查看原图

2.2 同步流程

选完leader以后,zk就进入状态同步过程。

  1. 1. leader等待server连接;

  2. 2 .Follower连接leader,将最大的zxid发送给leader;

  3. 3 .Leader根据follower的zxid确定同步点;

  4. 4 .完成同步后通知follower 已经成为uptodate状态;

  5. 5 .Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。

流程图如下所示:

点击查看原图

2.3 工作流程

2.3.1 Leader工作流程

Leader主要有三个功能:

  1. 1 .恢复数据;

  2. 2 .维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型;

  3. 3 .Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。

PING消息是指Learner的心跳信息;REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;ACK消息是Follower的对提议的回复,超过半数的Follower通过,则commit该提议;REVALIDATE消息是用来延长SESSION有效时间。

Leader的工作流程简图如下所示,在实际实现中,流程要比下图复杂得多,启动了三个线程来实现功能。点击查看原图

2.3.2 Follower工作流程

Follower主要有四个功能:

  1. 1. 向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);

  2. 2 .接收Leader消息并进行处理;

  3. 3 .接收Client的请求,如果为写请求,发送给Leader进行投票;

  4. 4 .返回Client结果。

Follower的消息循环处理如下几种来自Leader的消息:

  1. 1 .PING消息: 心跳消息;

  2. 2 .PROPOSAL消息:Leader发起的提案,要求Follower投票;

  3. 3 .COMMIT消息:服务器端最新一次提案的信息;

  4. 4 .UPTODATE消息:表明同步完成;

  5. 5 .REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;

  6. 6 .SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。

Follower的工作流程简图如下所示,在实际实现中,Follower是通过5个线程来实现功能的。

点击查看原图

对于observer的流程不再叙述,observer流程和Follower的唯一不同的地方就是observer不会参加leader发起的投票。



主流应用场景:

Zookeeper的主流应用场景实现思路(除去官方示例) 



(1)
配置管理

集中式的配置管理在应用集群中是非常常见的,一般商业公司内部都会实现一套集中的配置管理中心,应对不同的应用集群对于共享各自配置的需求,并且在配置变更时能够通知到集群中的每一个机器。



Zookeeper
很容易实现这种集中式的配置管理,比如将APP1的所有配置配置到/APP1 znode下,APP1所有机器一启动就对/APP1这个节点进行监控(zk.exist("/APP1",true)),并且实现回调方法Watcher,那么在zookeeper/APP1 znode节点下数据发生变化的时候,每个机器都会收到通知,Watcher方法将会被执行,那么应用再取下数据即可(zk.getData("/APP1",false,null));



以上这个例子只是简单的粗颗粒度配置监控,细颗粒度的数据可以进行分层级监控,这一切都是可以设计和控制的。
     点击查看原图

(2)集群管理 

应用集群中,我们常常需要让每一个机器知道集群中(或依赖的其他某一个集群)哪些机器是活着的,并且在集群机器因为宕机,网络断链等原因能够不在人工介入的情况下迅速通知到每一个机器。



Zookeeper
同样很容易实现这个功能,比如我在zookeeper服务器端有一个znode/APP1SERVERS,那么集群中每一个机器启动的时候都去这个节点下创建一个EPHEMERAL类型的节点,比如server1创建/APP1SERVERS/SERVER1(可以使用ip,保证不重复)server2创建/APP1SERVERS/SERVER2,然后SERVER1SERVER2watch /APP1SERVERS这个父节点,那么也就是这个父节点下数据或者子节点变化都会通知对该节点进行watch的客户端。因为EPHEMERAL类型节点有一个很重要的特性,就是客户端和服务器端连接断掉或者session过期就会使节点消失,那么在某一个机器挂掉或者断链的时候,其对应的节点就会消失,然后集群中所有对/APP1SERVERS进行watch的客户端都会收到通知,然后取得最新列表即可。



另外有一个应用场景就是集群选
master,一旦master挂掉能够马上能从slave中选出一个master,实现步骤和前者一样,只是机器在启动的时候在APP1SERVERS创建的节点类型变为EPHEMERAL_SEQUENTIAL类型,这样每个节点会自动被编号



我们默认规定编号最小的为
master,所以当我们对/APP1SERVERS节点做监控的时候,得到服务器列表,只要所有集群机器逻辑认为最小编号节点为master,那么master就被选出,而这个master宕机的时候,相应的znode会消失,然后新的服务器列表就被推送到客户端,然后每个节点逻辑认为最小编号节点为master,这样就做到动态master选举。

点击查看原图

Zookeeper 监视(Watches) 简介

Zookeeper C API 的声明和描述在 include/zookeeper.h 中可以找到,另外大部分的 Zookeeper C API 常量、结构体声明也在 zookeeper.h 中,如果如果你在使用 C API 是遇到不明白的地方,最好看看 zookeeper.h,或者自己使用 doxygen 生成 Zookeeper C API 的帮助文档。

Zookeeper 中最有特色且最不容易理解的是监视(Watches)。Zookeeper 所有的读操作——getData()getChildren(), 和 exists() 都 可以设置监视(watch),监视事件可以理解为一次性的触发器, 官方定义如下: a watch event is one-time trigger, sent to the client that set the watch, which occurs when the data for which the watch was set changes。对此需要作出如下理解:

  • (一次性触发)One-time trigger

    当设置监视的数据发生改变时,该监视事件会被发送到客户端,例如,如果客户端调用了 getData("/znode1", true) 并且稍后 /znode1 节点上的数据发生了改变或者被删除了,客户端将会获取到 /znode1 发生变化的监视事件,而如果 /znode1 再一次发生了变化,除非客户端再次对 /znode1 设置监视,否则客户端不会收到事件通知。

  • (发送至客户端)Sent to the client

    Zookeeper 客户端和服务端是通过 socket 进行通信的,由于网络存在故障,所以监视事件很有可能不会成功地到达客户端,监视事件是异步发送至监视者的,Zookeeper 本身提供了保序性(ordering guarantee):即客户端只有首先看到了监视事件后,才会感知到它所设置监视的 znode 发生了变化(a client will never see a change for which it has set a watch until it first sees the watch event). 网络延迟或者其他因素可能导致不同的客户端在不同的时刻感知某一监视事件,但是不同的客户端所看到的一切具有一致的顺序。

  • (被设置 watch 的数据)The data for which the watch was set

    这意味着 znode 节点本身具有不同的改变方式。你也可以想象 Zookeeper 维护了两条监视链表:数据监视和子节点监视(data watches and child watches) getData() and exists() 设置数据监视,getChildren() 设置子节点监视。 或者,你也可以想象 Zookeeper 设置的不同监视返回不同的数据,getData() 和 exists() 返回 znode 节点的相关信息,而 getChildren() 返回子节点列表。因此, setData() 会触发设置在某一节点上所设置的数据监视(假定数据设置成功),而一次成功的 create() 操作则会出发当前节点上所设置的数据监视以及父节点的子节点监视。一次成功的 delete() 操作将会触发当前节点的数据监视和子节点监视事件,同时也会触发该节点父节点的child watch。

Zookeeper 中的监视是轻量级的,因此容易设置、维护和分发。当客户端与 Zookeeper 服务器端失去联系时,客户端并不会收到监视事件的通知,只有当客户端重新连接后,若在必要的情况下,以前注册的监视会重新被注册并触发,对于开发人员来说 这通常是透明的。只有一种情况会导致监视事件的丢失,即:通过 exists() 设置了某个 znode 节点的监视,但是如果某个客户端在此 znode 节点被创建和删除的时间间隔内与 zookeeper 服务器失去了联系,该客户端即使稍后重新连接 zookeeper服务器后也得不到事件通知。

Zookeeper C API 常量与部分结构(struct)介绍

与 ACL 相关的结构与常量:

struct Id 结构为:

struct Id {     char * scheme;     char * id; };

 

struct ACL 结构为:

struct ACL {     int32_t perms;     struct Id id; };

 

struct ACL_vector 结构为:

struct ACL_vector {     int32_t count;     struct ACL *data; };

 

与 znode 访问权限有关的常量

  • const int ZOO_PERM_READ; //允许客户端读取 znode 节点的值以及子节点列表。

  • const int ZOO_PERM_WRITE;// 允许客户端设置 znode 节点的值。

  • const int ZOO_PERM_CREATE; //允许客户端在该 znode 节点下创建子节点。

  • const int ZOO_PERM_DELETE;//允许客户端删除子节点。

  • const int ZOO_PERM_ADMIN; //允许客户端执行 set_acl()。

  • const int ZOO_PERM_ALL;//允许客户端执行所有操作,等价与上述所有标志的或(OR) 。

与 ACL IDs 相关的常量

  • struct Id ZOO_ANYONE_ID_UNSAFE; //(‘world’,’anyone’)

  • struct Id ZOO_AUTH_IDS;// (‘auth’,’’)

三种标准的 ACL

  • struct ACL_vector ZOO_OPEN_ACL_UNSAFE; //(ZOO_PERM_ALL,ZOO_ANYONE_ID_UNSAFE)

  • struct ACL_vector ZOO_READ_ACL_UNSAFE;// (ZOO_PERM_READ, ZOO_ANYONE_ID_UNSAFE)

  • struct ACL_vector ZOO_CREATOR_ALL_ACL; //(ZOO_PERM_ALL,ZOO_AUTH_IDS)

与 Interest 相关的常量:ZOOKEEPER_WRITEZOOKEEPER_READ

这 两个常量用于标识感兴趣的事件并通知 zookeeper 发生了哪些事件。Interest 常量可以进行组合或(OR)来标识多种兴趣(multiple interests: write, read),这两个常量一般用于 zookeeper_interest() 和 zookeeper_process()两个函数中。

与节点创建相关的常量:ZOO_EPHEMERALZOO_SEQUENCE

zoo_create 函数标志,ZOO_EPHEMERAL 用来标识创建临时节点,ZOO_SEQUENCE 用来标识节点命名具有递增的后缀序号(一般是节点名称后填充 10 位字符的序号,如 /xyz0000000000, /xyz0000000001, /xyz0000000002, ...),同样地,ZOO_EPHEMERALZOO_SEQUENCE 可以组合。

与连接状态 Stat 相关的常量

以下常量均与 Zookeeper 连接状态有关,他们通常用作监视器回调函数的参数。

ZOOAPI const int  ZOO_EXPIRED_SESSION_STATE
ZOOAPI const int  ZOO_AUTH_FAILED_STATE
ZOOAPI const int  ZOO_CONNECTING_STATE
ZOOAPI const int  ZOO_ASSOCIATING_STATE
ZOOAPI const int  ZOO_CONNECTED_STATE

与监视类型(Watch Types)相关的常量

以下常量标识监视事件的类型,他们通常用作监视器回调函数的第一个参数。

Zookeeper C API 错误码介绍 ZOO_ERRORS

ZOK 

正常返回

ZSYSTEMERROR 

系统或服务器端错误(System and server-side errors),服务器不会抛出该错误,该错误也只是用来标识错误范围的,即大于该错误值,且小于 ZAPIERROR 都是系统错误。

ZRUNTIMEINCONSISTENCY 

运行时非一致性错误。

ZDATAINCONSISTENCY 

数据非一致性错误。

ZCONNECTIONLOSS 

Zookeeper 客户端与服务器端失去连接

ZMARSHALLINGERROR 

在 marshalling 和 unmarshalling 数据时出现错误(Error while marshalling or unmarshalling data)

ZUNIMPLEMENTED 

该操作未实现(Operation is unimplemented)

ZOPERATIONTIMEOUT 

该操作超时(Operation timeout)

ZBADARGUMENTS 

非法参数错误(Invalid arguments)

ZINVALIDSTATE 

非法句柄状态(Invliad zhandle state)

ZAPIERROR 

API 错误(API errors),服务器不会抛出该错误,该错误也只是用来标识错误范围的,错误值大于该值的标识 API 错误,而小于该值的标识 ZSYSTEMERROR。

ZNONODE 

节点不存在(Node does not exist)

ZNOAUTH 

没有经过授权(Not authenticated)

ZBADVERSION 

版本冲突(Version conflict)

ZNOCHILDRENFOREPHEMERALS 

临时节点不能拥有子节点(Ephemeral nodes may not have children)

ZNODEEXISTS 

节点已经存在(The node already exists)

ZNOTEMPTY 

该节点具有自身的子节点(The node has children)

ZSESSIONEXPIRED 

会话过期(The session has been expired by the server)

ZINVALIDCALLBACK 

非法的回调函数(Invalid callback specified)

ZINVALIDACL 

非法的ACL(Invalid ACL specified)

ZAUTHFAILED 

客户端授权失败(Client authentication failed)

ZCLOSING 

Zookeeper 连接关闭(ZooKeeper is closing)

ZNOTHING 

并非错误,客户端不需要处理服务器的响应(not error, no server responses to process)

ZSESSIONMOVED 

会话转移至其他服务器,所以操作被忽略(session moved to another server, so operation is ignored)

 

Watch事件类型:

 

ZOO_CREATED_EVENT:节点创建事件,需要watch一个不存在的节点,当节点被创建时触发,此watch通过zoo_exists()设置

ZOO_DELETED_EVENT:节点删除事件,此watch通过zoo_exists()或zoo_get()设置

ZOO_CHANGED_EVENT:节点数据改变事件,此watch通过zoo_exists()或zoo_get()设置

ZOO_CHILD_EVENT:子节点列表改变事件,此watch通过zoo_get_children()或zoo_get_children2()设置

ZOO_SESSION_EVENT:会话失效事件,客户端与服务端断开或重连时触发

ZOO_NOTWATCHING_EVENT:watch移除事件,服务端出于某些原因不再为客户端watch节点时触发

发表在 technologys | 标签为 | zookeeper原理已关闭评论

KVM的B/S架构虚拟化管理系统

云计算的提出为信息技术学术界和产业界的发展提供了一个全新的思路。虚拟化作为云计算Iaas层的关键技术,近年来也得到了迅速发展。20世纪60年代,IBM就开始研究虚拟化技术,使得大型机的资源能得被多用户使用。经过几十年的发展,虚拟化技术已经日渐成熟,诞生了如VMware,virtual PC,Xen和KVM(kernel based virtualmachine)等一批成熟的虚拟化产品。与其他虚拟化产品相比,KvM的最大优势是完全开源。KVM是基于内核的完全虚拟化,在与其他虚拟化产品效率对比中表现出色,但是其管理系统仍然只有C/S架构的,C/S架构本身的缺点造成了系统资源的浪费。而且用户进行管理工作之前,需要预先安装管理软件;而且不同的管理软件对操作系统和硬件资源还有不同的要求。相比起来,B/S模式的管理系统就灵活很多,只要有浏览器的终端都可以用来进行管理工作,提高了管理效率,节省了客户端资源占用。

  本文实现了一个基于KVM虚拟化产品的B/S架构的虚拟化管理系统。通过调用KVM的libvirt开发接口,利用J2EE技术,系统管理员可在任何地方通过浏览器登陆系统,进行虚拟机和虚拟存储的管理工作。最后通过实际测试表明B/S架构的优越性。

  1.系统组成部分

  基于KVM的虚拟化管理系统,主要包括客户端、web服务器、虚拟化服务器集群和共享存储服务器4个模块。其中客户端是具有浏览器的上网设备,操作系统可以是Linux、windows甚至嵌入式操作系统;web服务器上安装web容器tomcat,操作系统采用“nux或windows,将完成管理工作的J2EE工程放在web容器里;虚拟化服务器集群上统一安装Linux操作系统,KVlⅥ虚拟化软件和lib—virt接口,并与web服务器建立ssh无密码连接;共享存储服务器是一个磁盘阵列,安装freenas后通过IP网络向虚拟化集群提供数据存储服务。

  用户通过jsp页面登陆后进行相关操作,操作参数传递给web服务器,web服务器与管理目标服务器建立ssh连接,通过调用libvirt接口进行虚拟化集群的管理工作,并将操作结果通过jsp页面呈现给用户。用户还可以通过调用spice插件,用图形界面的方式查看虚拟机的工作情况。整个系统结构如图1所示。

点击查看原图

图1 系统架构

  1.1 KVM(Kernel based virtual machine)

  KVM即基于内核的虚拟化,依赖于“Linux内核,其性能优越,接近单机操作系统。由于其优越的性能和开源性,得到业界的一致认可并在近年来取得很大的发展。KVM使用软件模拟的方式实现完全虚拟化,通过将客户操作系统的I/0指令提交给宿主操作系统(即Linux操作系统)上的QEMU,QEMU将操作指令转换为对宿主机的I/0操作这种方式来实现虚拟化,然后宿主操作系统调用驱动程序访问硬件。通过这种方式对硬件进行了模拟,实现起来比较简洁,而且效率较高|。

  1.2 SPICE(simple procotol for independent computing environment)

  spice是一个开源的远程桌面协议,可以用于在服务器、远程计算机和瘦客户端等设备上部署虚拟桌面,与微软的Remote Desktop Protocol相似,支持windows和Linux操作系统。

  spice包括两部分:spice server和spice client。通过在虚拟机里安装spice Server进行相应的配置后,就可以在客户端通过spice client插件远程链接该虚拟机,以图形界面形式进行操作。

  1.3 Libvirt接口

  Libvirt是一套开源的、用C语言开发的支持虚拟化函数库编程接口,用一种单一方式管理不同的虚拟化提供方式和管理工具,适用于主流虚拟化工具包括Xen、KVM和vmware等,支持与Java、python、C/C++等开发语言的绑定。Linux下常用的虚拟化管理工具Virt-manager和virt—install都是基于libvirt开发。

  1.4 Freenas

  Freenas是一款免费的NAS(网络附加存储)服务器软件,它能将普通PC或服务器的硬盘资源变成网络存储服务器。该软件基于FreeBSD,Samba及PHP,支持FTP/NFS/RSYNC/CIFS/AFP/UNISON/SSH协议及web界面的设定工具。Freems还可以被安装在移动存储设备中,使用方便灵活,在组建网络存储服务器方面应用广泛。

  2.J2EE工程架构

  系统实现的核心是完成管理工作并和用户交互的J2EE工程。J2EE工程架构如图2所示。

点击查看原图

图2 J2EE工程架构

  客户层实现用户和系统的交互,用户通过Web浏览器登录系统,并通过页面提交操作参数。浏览器负责用户请求接收和服务器返回信息的显示。

  struts控制器负责接收和处理用户请求,并将相应请求转发到业务逻辑层,然后从业务逻辑层接收结果并返回给客户层进行显示。

  业务逻辑层是J2EE工程的核心,负责接收stmts传递的用户请求,调用底层libvirt API完成相应的操作,并将处理结果经Web层展现给用户。

  将管理虚拟化的J2EE工程放在中心服务器(即web服务器)的tomcat容器里,这台web服务器应该与虚拟化集群在同一局域网中以保证连接速度。用户通过前台jsp页面登陆管理系统,web服务器接收到用户的请求参数后,与管理目标服务器通过ssh建立连接,用户即可进行相关的管理操作。在web服务器接收到用户管理操作参数后,将参数转换为libvirt接口认可的xml格式文件的参数,然后发送给管理目标服务器,目标服务器接收到参数后调用Libvirt接口,执行相关操作。具体实现过程如下:

  用户提交请求参数:用户登录成功后,可以进行如下四方面管理:用户管理、存储磁盘、虚拟机管理和集群管理。通过用户管理可以修改用户登录密码,定期修改密码可以增强安全性;通过存储管理可以添加或删除资源池,查看、删除或者新建虚拟磁盘;通过虚拟机管理,可以查

看和修改虚拟机信息,并通过spice查看虚拟机图形界面;集群管理可以查看集群中的物理机信息,并可以将虚拟机迁移到另一台物理机上。用户操作通过表单形式提交给Web服务器。

  Web服务器转换请求参数并发送给目标服务器:web服务器通过servIet接收到用户请求参数,转换为字符串,然后将参数组合为ml格式的libvirt配置文件,然后与目标服务器建立ssh连接,通过配置文件将需要进行的操作传递给目标服务器。

  目标服务器进行相关管理操作并向web服务器返回结果:目标服务器收到配置文件参数后,调用libvirt接口将操作参数传人,进行相应的操作。然后将操作结果返回给Web服务器。

  Web服务器将操作结果返回给用户:web服务器接收到返回结果后,进行相应的封装后传递给前台页面,显示给用户。如果用户的请求是图形界面查看虚拟机,则Web服务器将虚拟机的参数传递给客户端后,客户端与目标服务器直接建立连接。

  3.系统设计功能

  用户登录后可以进行如下四方面管理工作:用户管理、存储管理、虚拟机管理和集群管理。系统功能框图如图3所示。

   点击查看原图

图3 系统功能结构   

  3.1用户管理

  用户名和密码通过加密后写在配置文件里,用户提交登录请求后web服务器读取配置文件并进行登录验证,验证通过即可进行权限内的相关管理操作。用户可以定期修改密码,以增强安全性。超级用户可以对用户进行管理,包括添加、删除用户,为用户分配权限等,但是超级用户本身不能对虚拟化集群直接进行管理。通过这种权限分离的方式提高系统的安全性。

  3.2虚拟存储管理

  创建虚拟磁盘之前需要先创建资源池,然后在资源池中创建虚拟磁盘。虚拟磁盘就是提供给虚拟机用的存储空间,是位于共享存储之上的虚拟逻辑磁盘空间。用户登录之后,存储管理界面提供的管理操作包括:新建和删除资源池,新建和删除虚拟磁盘。新建和删除虚拟磁盘的时候,将虚拟磁盘名作为参数传递给web服务器,创建虚拟磁盘时提交表单包括磁盘名称和磁盘大小。表单提交给servlet进行处理。

  3.3虚拟机管理

  创建虚拟机之后,KVM会给每个虚拟机分配一个UUD(universally unique identifier),用于唯一标识该虚拟机。KVM每次启动的时候,都会为每个虚拟机分配一个ID。通过UUID或者ID都可以唯一找到该虚拟机。虚拟机管理进行的操作包括:新建和删除虚拟机,查看和修改虚拟机配置信息,启动、挂起和关闭虚拟机,导出虚拟机模板,从模板创建虚拟机,显示虚拟机界面(spice)。本系统将虚拟机的ID作为参数进行传递。首先用户将操作指令和虚拟机ID传递给web服务器,web服务器封装后传递给目标服务器,然后接受目标服务器执行后的返回结果,再传递给用户显示。

  在调用spice通过图形界面方式查看虚拟机中,首先检测spice插件是否正确安装,如果没有正确安装,提示用户下载并安装。如果正确安装,在拦截到查看指令后,从网页启动spice插件。并将虚拟机参数传递给spice,输入密码即可查看虚拟机的界面。

  3.4 集嚣管理

  集群管理包括物理主机管理和集群调度。物理机管理包括向虚拟化集群添加和删除物理机,通过SNMP(simplenetwork management protocol)协议收集物理机信息,维护活动物理机列表;集群调度采用虚拟机迁移来实现,采用中心任务调度算法,根据管理节点服务器(即Web服务器)通过SNⅧ协议收集到的主机状态信息,在物理机负载过高时,将其上的部分虚拟机迁移到其他物理机上,也可以将负载量很小的物理机上的虚拟机迁移到其他主机上,然后关闭该物理机以节省电能。 


    4.关键技术

    4.1 封装ssh连接类

    系统中用到建立ssh连接的地方比较多,因此通过对连接类进行封装可以有效减少代码量,提高可读性。

    封装ssh连接类需要用到两个类:org. libvirt包下的Connect和LibvirtException类。实现封装的类如下:

  public class SSHConnect{

    private static final String SSHURLl=“

qemu+ssh://”;

   private static final String SSHURL2=“/system”;

   public static Connect getSSHConnect(String userIp,

boolean flag){

   Connect conn=null;

   try{

   conn = new Connect (SSHURL1+userIp+

SSHURL2,fIag);

   }catch(LibvirtException e){

   e.printstackTrace();

   System.out.println(e.getError());

   return:

   }

   return conn:

   }

   public static void close(Connect conn){

   if(conn!=null){

   try{

   conn.close();

   }catch(LibvirtException e){

   e.printStackTrace();

   Systern.out.println(e_getError());

   }

   }

   }

  }

  4.2 Ajax(Asynchronous JavaScript and XML)技术



    考虑到不同的用户同时对一台服务器进行管理的可能性,本系统在向服务器读取数据的时候都是实时读取的,这就要用到Ajax技术。

  Ajax即异步JavaScript和XML,是一种创建交互式网页应用的网页开发技术。其工作原理是,在用户和服务器之间增加了了一个中间层——Ajax引擎.使用户操作与服务器响应异步化,部分操作由Ajax直接完成,无需向服务器提交数据。在用户需要从服务器读取新数据时由Ajax引擎代为向服务器提交请求,然后将读取结果发送给用户。在使用Ajax擎后,用户从感觉上几乎所有的操作都会很快响应没有页面重载的等待,也没有页面跳转。其工作原理如图5所示。

 

  点击查看原图

图4 Ajax工作原理  

  4.3用spice查看虚拟机

  在创建虚拟机的时候,将图形设备选择为spice,添加spice server并设置端口号,将显卡设备选择为视频卡QXL设备。Web服务器在接收到查看图形界面请求后,首先进行客户操作系统的判断,并检测用户是否正确安装spice,如果没有安装则根据用户操作系统提示用户下载安装spice包。

  如果spice正确安装,则通过网页启动spice,并将相应参数传人,即可打开虚拟机的图形界面。

  4.4 提供类应用软件试图

  为了使管理的步骤更加清晰和兼顾用户使用习惯,本系统设计类似应用软件的用户交互界面。首先将操作拆分成各个步骤,并为每一步骤设计一个jsp页面,然后使用Css+div建立一个可拖动的层,然后采用ifr锄e技术将操作步骤对应的jsp页面加载到层中显示,用Javascript控制层中内容的切换和数据的缓存,需要与服务器及时交互的数据则采用Ajax技术实时获取。在一个操作完成后将表单数据整合并提交。

  5.系统性能测试

  以VMware的vCenter server/vClient为例,与本系统性能做一个比较,测试环境为包含6台服务器的集群。用pc做客户端进行测试,CPU为双核2.9GHz,内存为2G,Windows Xp系统使用内存约350M。使用的系统资源情况分别如图6和图7所示。

 

点击查看原图   

图5 VMware 客户端资源使用   

点击查看原图

图6 B/S架构客户端资源使用

  由图可见,C/S架构客户端CPU利用率约为50%,内存使用为350M左右,而使用B/S架构系统的客户端CPU平均使用率约为20%,内存使用为190M左右。管理节点采用的是2个64位CPU,主频2.5GHz,内存8G,硬盘100G。安装hyper_V和作web服务器时系统资源使用情况见表1。

 

表1 管理节点消耗的系统资源对比

点击查看原图

  由此可见,B/S架构管理系统能极大降低系统资源的消耗。这一特点在集群规模增大时会体现的更加明显,因此对大规模虚拟化集群部署有重要的参考价值。

  6.结束语

  基于KVM的B/S架构虚拟化管理系统,将虚拟化管理工作由C/S模式转向了B/S模式,用户在管理虚拟化集群之前不用先安装客户端,直接通过浏览器登陆即可进行管理,管理工作不用限定在特定的客户机上,也不用限定在特定的网络环境中。由于web服务器取代了管理中心服务器,使系统的资源消耗更少,管理方式更加灵活。本系统在WindowS和Linux下经过测试,运行良好

发表在 virtual machine | 标签为 | KVM的B/S架构虚拟化管理系统已关闭评论

MooseFS-管理优化

一、高级功能

1、副本

       副本,在MFS中也被称为目标(Goal),它是指文件被复制的份数,设定目标值后可以通过mfsgetgoal命令来证实,也可以通过mfssetgoal命令来改变设定。

[root@mfs-client ~]# cd /mfsdata/
[root@mfs-client mfsdata]# dd if=/dev/zero of=/mfsdata/test.file bs=1M count=200 
200+0 records in 
200+0 records out 
209715200 bytes (210 MB) copied, 9.1094 s, 23.0 MB/s 
[root@mfs-client mfsdata]# mfsgetgoal test.file 
test.file: 1 
[root@mfs-client mfsdata]# mfssetgoal 3 test.file 
test.file: 3 
[root@mfs-client mfsdata]# mfsgetgoal test.file 
test.file: 3 

补充:

用mfsgetgoal –r和mfssetgoal –r同样的操作可以对整个树形目录递归操作

[root@mfs-client mfsdata]# mkdir dir/dir1/dir2/dir3 -p 
[root@mfs-client mfsdata]# touch dir/file1 
[root@mfs-client mfsdata]# touch dir/dir1/file2 
[root@mfs-client mfsdata]# touch dir/dir1/dir2/file3
[root@mfs-client mfsdata]# mfsgetgoal -r dir 
dir: 
files with goal 1 : 3 
directories with goal 1 : 4
[root@mfs-client mfsdata]# mfssetgoal -r 3 dir 
dir: 
inodes with goal changed: 7 
inodes with goal not changed: 0 
inodes with permission denied: 0 

       实际的拷贝份数可以通过mfscheckfile 和 mfsfileinfo 命令来证实,例如:

[root@mfs-client mfsdata]# mfscheckfile test.file 
test.file: 
chunks with 1 copy: 4 
[root@mfs-client mfsdata]# mfsfileinfo test.file 
test.file: 
chunk 0: 00000000000000D2_00000001 / (id:210 ver:1) 
copy 1: 172.16.100.6:9422 
chunk 1: 00000000000000D3_00000001 / (id:211 ver:1) 
copy 1: 172.16.100.7:9422 
chunk 2: 00000000000000D4_00000001 / (id:212 ver:1) 
copy 1: 172.16.100.6:9422 
chunk 3: 00000000000000D5_00000001 / (id:213 ver:1) 
copy 1: 172.16.100.7:9422 

       需要注意的是,一个包含数据的零长度的文件,尽管没有设置为非零的目标(the non-zero goal),但是在使用命令查询时将返回一个空值

[root@mfs-client mfsdata]# touch a 
[root@mfs-client mfsdata]# mfscheckfile a 
a: 
[root@mfs-client mfsdata]# mfsfileinfo a 
a: 



2、回收

       一个删除文件能够存放在一个“垃圾箱”的时间就是一个隔离时间,这个时间可以用 mfsgettrashtime 命令来验证,也可以用 mfssettrashtime 命令来设置。例如:

[root@mfs-client mfsdata]# mfsgettrashtime test.file 
test.file: 86400
[root@mfs-client mfsdata]# mfssettrashtime 0 test.file 
test.file: 0
$ mfsgettrashtime /mnt/mfs-test/test1
/mnt/mfs-test/test1: 0 

这些工具也有个递归选项-r,可以对整个目录树操作,例如:


[root@mfs-client mfsdata]# mfsgettrashtime -r dir 
dir: 
files with trashtime 86400 : 3 
directories with trashtime 86400 : 4 
[root@mfs-client mfsdata]# mfssettrashtime -r 0 dir 
dir: 
inodes with trashtime changed: 7 
inodes with trashtime not changed: 0 
inodes with permission denied: 0 
[root@mfs-client mfsdata]# mfsgettrashtime -r dir 
dir: 
files with trashtime 0 : 3 
directories with trashtime 0 : 4 

       时间的单位是秒(有用的值有:1小时是3600秒,24 – 86400秒,1 – 604800秒)。就像文件被存储的份数一样, 为一个目录 设定存放时间是要被新创建的文件和目录所继承的。数字0意味着一个文件被删除后, 将立即被彻底删除,在想回收是不可能的

       删除文件可以通过一个单独安装 MFSMETA 文件系统。特别是它包含目录 / trash (包含任然可以被还原的被删除文件的信息)和 / trash/undel (用于获取文件)。只有管理员有权限访问MFSMETA(用户的uid 0,通常是root)。

       在开始mfsmount进程时,用一个-m或-o mfsmeta的选项,这样可以挂接一个辅助的文件系统MFSMETA,这么做的目的是对于意外的从MooseFS卷上删除文件或者是为了释放磁盘空间而移动的文件而又此文件又过去了垃圾文件存放期的恢复,例如:

mfsmount -m /mnt/mfsmeta 

需要注意的是,如果要决定挂载mfsmeta,那么一定要在 mfsmaster 的 mfsexports.cfg 文件中加入如下条目:

 *                       .       rw 

原文件中有此条目,只要将其前的#去掉就可以了。

否则,你再进行挂载mfsmeta的时候,会报如下错误:

mfsmaster register error: Permission denied 

下面将演示此操作:

$ mfssettrashtime 3600 /mnt/mfs-test/test1
/mnt/mfs-test/test1: 3600 

       从“垃圾箱”中删除文件结果是释放之前被它站用的空间(删除有延迟,数据被异步删除)。在这种被从“垃圾箱”删除的情况下,该文件是不可能恢复了。

       可以通过mfssetgoal工具来改变文件的拷贝数,也可以通过mfssettrashtime工具来改变存储在“垃圾箱”中的时间。

       在 MFSMETA 的目录里,除了trash和trash/undel两个目录外,还有第三个目录reserved,该目录内有已经删除的文件,但却有一直打开着。在用户关闭了这些被打开的文件后,reserved目录中的文件将被删除,文件的数据也将被立即删除。在reserved目录中文件的命名方法同trash目录中的一样,但是不能有其他功能的操作。



3、快照

       MooseFS系统的另一个特征是利用mfsmakesnapshot工具给文件或者是目录树做快照,例如:

$ mfsmakesnapshot source ... destination 

       Mfsmakesnapshot 是在一次执行中整合了一个或是一组文件的拷贝,而且任何修改这些文件的源文件都不会影响到源文件的快照, 就是说任何对源文件的操作,例如写入源文件,将不会修改副本(或反之亦然)。

       文件快照可以用mfsappendchunks,就像MooseFS1.5中的mfssnapshot一样,,作为选择,二者都可以用。例如:

$ mfsappendchunks destination-file source-file ... 

       当有多个源文件时,它们的快照被加入到同一个目标文件中(每个chunk的最大量是chunk)。五、额外的属性文件或目录的额外的属性(noowner, noattrcache, noentrycache),可以被mfsgeteattr,mfsseteattr,mfsdeleattr工具检查,设置,删除,其行为类似mfsgetgoal/mfssetgoal or或者是mfsgettrashtime/mfssettrashtime,详细可见命令手册。


二、综合测试

1、破坏性测试

 a、模拟MFS各角色宕机测试

 b、mfs 灾难与恢复各种场景测试


2、性能测试

       针对 MooseFS 的性能测试,我这边也没有详细去做。通过伟大的互联网,我找到了几位前辈,针对 MooseFS 所做的详细性能测试,这里我就贴出来展示一下。

1、基准测试情况:

随机读

点击查看原图

随机写

点击查看原图

顺序读

点击查看原图

顺序写

点击查看原图



小文件性能测试情况

点击查看原图

点击查看原图

点击查看原图

点击查看原图

点击查看原图

点击查看原图

        如果想看更多有关 MooseFS 性能方面的测试报告,可以去参考如下链接:

        http://blog.liuts.com/post/203/          MooseFS性能图表[原创]




三、监控

1、mfs内置的监控工具mfscgiserv

       针对 Moosefs 每个组件的监控,Moosefs自带了一个监控工具 mfscgiserv,它是一个 python 编写的 web 监控页面,监听端口为9425。该监控页面为我们提供了 Master Server、Metalogger Server、Chunk Servers以及所有Client挂载的状态信息及相关性能指标图示。

       在我们安装好 Master Server 时,它就已经默认安装上了,我们可以在/usr/local/mfs/share/mfscgi/  目录下看到这个监控页面的文件。

[root@mfs-master-1 mfs]# ll /usr/local/mfs/share/mfscgi/         # 这个 mfscgi 目录里面存放的是master图形监控界面的程序
total 136 
-rwxr-xr-x. 1 root root 1881 Dec 29 00:10 chart.cgi 
-rw-r--r--. 1 root root 270 Dec 29 00:10 err.gif 
-rw-r--r--. 1 root root 562 Dec 29 00:10 favicon.ico 
-rw-r--r--. 1 root root 510 Dec 29 00:10 index.html 
-rw-r--r--. 1 root root 3555 Dec 29 00:10 logomini.png 
-rwxr-xr-x. 1 root root 107456 Dec 29 00:10 mfs.cgi 
-rw-r--r--. 1 root root 5845 Dec 29 00:10 mfs.css 

       我们可以通过执行如下命令启动该监控程序。

/moosefs_install_path/sbin/mfscgiserv start 

       启动完毕之后,我们可以通过访问http://IP:9425来访问该监控页面。

       下面,我列出启动 mfscgiserv 监控工具的操作:

[root@mfs-master-1 mfs]# /usr/local/mfs/sbin/mfscgiserv start   # 启动mfs图形控制台 
lockfile created and locked 
starting simple cgi server (host: any , port: 9425 , rootpath: /usr/local/mfs-1.6.27/share/mfscgi)
[root@mfs-master-1 mfs]# netstat -lantup|grep 9425 
tcp 0 0 0.0.0.0:9425 0.0.0.0:* LISTEN 7940/python 
tcp 0 0 172.16.100.1:9425 172.16.100.100:50693 ESTABLISHED 7940/python 
tcp 0 0 172.16.100.1:9425 172.16.100.100:50692 ESTABLISHED 7940/python 
[root@mfs-master-1 mfs]# lsof -i tcp:9425 
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME 
python 7940 root 3u IPv4 27066 0t0 TCP *:9425 (LISTEN) 
python 7940 root 7u IPv4 27136 0t0 TCP 172.16.100.1:9425->172.16.100.100:50693 (ESTABLISHED) 
python 7940 root 8u IPv4 27124 0t0 TCP 172.16.100.1:9425->172.16.100.100:50692 (ESTABLISHED) 

下面是访问的页面:

spacer.gif点击查看原图


2、使用zabbix监控mfs

1、监控要点

        根据 MooseFS 中各个组件的特点,我们所需要监控的要点主要有如下几点:

        a、Master Server的9420、9421端口,Chunk Server 的9422端口

        b、Chunk Server 的磁盘空间

2、实施步骤

        通过在各个组件的对应服务器上部署好zabbix监控的代理端,然后分别添加端口监控和磁盘监控即可!


        操作过程略!



八、维护

1、常用管理命令

mfsgetgoal              # 获取mfs目录、文件的副本数
mfssetgoal              # 设置mfs目录、文件的副本数
mfscheckfile            # 查看副本数简单
mfsfileinfo             # 查看详细的副本数,chunks/分片
mfsdirinfo              # 以数量的方法显示mfsfileinfo
mfsgettrashtime         # 获取垃圾箱的定隔时间
mfssettrashtime         # 设置垃圾箱的定隔时间(和memcached类)
mfsmakesnapshot         # 快照 



2、可能存在的问题

A、mfscgiserv的访问安全问题

       mfscgiserv只是一个非常简单的HTTP服务器,只用来编写运行MooseFS CGI脚本。它不支持任何的附加功能,比如HTTP认证。如果公司出于对监控界面的安全访问需求,我们可以使用功能丰富的HTTP服务器,比如apache、nginx等。在使用这些更强大的HTTP服务器时,我们只需要将CGI和其它数据文件(index.html、mfs.cgi、chart.cgi、mfs.css、logomini.png、err.gif)存放到选择的站点根目录下。我们可以创建一个新的虚拟机,来设定特定的主机名和端口来进行访问。


B、Master Server 的单点问题

       Master server的单点问题,在前面介绍 MooseFS 的优缺点时已经提到过了。由于官方提供的解决方案,在恢复的时候还是需要一定时间的,因此我们建议使用第三方的高可用方案(heartbeat+drbd+moosefs)来解决 Master Server 的单点问题。


3、性能瓶颈的解决办法

       由于 MooseFS 的高可扩展性,因此我们可以很轻松的通过增加 Chunk Server 的磁盘容量或增加 Chunk Server 的数量来动态扩展整个文件系统的存储量和吞吐量,这些操作丝毫不会影响到在线业务。


4、安全开启/停止MFS集群

1、启动 MooseFS 集群

安全的启动 MooseFS 集群(避免任何读或写的错误数据或类似的问题)的步骤如下:

       1、启动 mfsmaster 进程

       2、启动所有的 mfschunkserver 进程

       3、启动 mfsmetalogger 进程(如果配置了mfsmetalogger)

       4、当所有的 chunkservers 连接到 MooseFS master 后,任何数目的客户端可以利用 mfsmount 去挂载被 export 的文件系统。(可以通过检查 master 的日志或是 CGI 监控页面来查看是否所有的chunkserver 被连接)。



2、停止 MooseFS 集群

安全的停止 MooseFS 集群的步骤如下:

       1、在所有的客户端卸载MooseFS 文件系统(用umount命令或者是其它等效的命令)

       2、用 mfschunkserver –s命令停止chunkserver进程

       3、用 mfsmetalogger –s命令停止metalogger进程

       4、用 mfsmaster –s命令停止master进程


5、增加块设备(会自动平均)

        针对增加块设备的情况,其实就是说针对chunk server 有变化(增加或减少)的情况。

        为了增加一个案例说明,这里就以 UC 在使用 MooseFS 中遇到的一个问题为案例,讲解新增加 chunk server 时,MooseFS集群发生的变化,其实也就是 Master Server 发生的变化。


        UC在使用 MooseFS 集群的过程中,有次一台 Chunk Server 挂了,于是就涉及到了后期的恢复问题。在问题Chunk Server修复之后,就从新加入到了集群当中。此时,新增加的 chunk server 启动之后会向 Master 汇报 Chunk 的信息,Master接收到 Chunk 信息之后会逐个检查 Chunk_id是否存在。如果不存在,就表示该chunk_id其实已经删除了(chunk_id过期),然后会调用chunk_new()创建该chunk,并设置lockedio属性为7天后。这些操作都是属于内存操作,并且Master是单线程的进程,并不存在全局锁,因此不会导致 Master 阻塞无响应。因此,针对增加chunk server的情况,是不会对MooseFS集群产生什么大的影响的。

        以上就是新增加 Chunk Server 后的,MooseFS 集群中 Master Server 的变化。而针对各个Chunk Server,Master Server会重新去调整块文件的磁盘空间,然后全部重新动态分配块文件。如果遇到空间不够的磁盘,Master Server会自动调整块文件的分布,从不够的磁盘里动态的把块服务移动到有大的磁盘块服务器里

        当然,如果按照上面的情况这次就不会是故障了,因此并不会对 MooseFS 集群产生什么大的影响。由于他们当时因为资源紧张,就把 Master Server 放到了虚拟机上,而虚拟机的磁盘是挂载的iscsi磁盘。并且他们的MooseFS使用的版本并不是最新的1.6.27,而是1.6.19。在1.6.19版本中,会把chunk的汇报过程写入磁盘,这样就导致了几十万条的磁盘写入,由于磁盘是前面提到的网络盘,就最终酿成了 Master Server 恢复时无响应几十分钟。

         因此,我们在生产环境中,针对Master Server的选型一定不能使用虚拟机,而是使用大内存量的物理机

 

允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://nolinux.blog.51cto.com/4824967/1602616

发表在 storage | 标签为 | MooseFS-管理优化已关闭评论

MooseFS-介绍

一、简述

1、介绍

       MooseFS是一个具备冗余容错功能的分布式网络文件系统,它将数据分别存放在多个物理服务器或单独磁盘或分区上,确保一份数据有多个备份副本。对于访问的客户端或者用户来说,整个分布式网络文件系统集群看起来就像一个资源一样。从其对文件操作的情况看,MooseFS就相当于一个类UNIX文件系统:

       1、mfs是一个分层的目录树结构

       2、存储支持POSIX标准的文件属性(权限,最后访问和修改时间)

       3、支持特殊的文件,如:块设备,字符设备,管道和套接字,链接文件(符号链接和硬链接)

       4、支持基于IP地址和密码的方式访问文件系统


2、特性

       1、高可靠性,每一份数据可以设置多个副本(多份数据),并可以存储在不同的主机上

       2、高可扩展性,可以很轻松的通过增加主机磁盘容量或增加主机数量来动态扩展整个文件系统的存储量

       3、高可容错性,我们可以通过对mfs进行系统设置,实现当数据文件被删除后的一段时间内,依然存放于主机的回收站中,以备误删恢复数据

       4、高数据一致性,即便文件被写入/访问时,我们依然可以完成对文件的一致性快照



3、优缺点

优点:

       1、由于MFS是基于GPL发布的,因此完全免费,并且开发和社区都很活跃,资料也非常丰富

       2、轻量、易部署、易配置、易维护

       3、通用文件系统,不需要修改上层应用就可以使用(那些需要专门 API 的DFS确实有点麻烦)

       4、扩容成本低、支持在线扩容,不影响业务,体系架构可伸缩性极强(官方的case可以扩到70台了!)

       5、体系架构高可用,所有组件无单点故障

       6、文件对象高可用,可设置任意的文件冗余程度(提供比 Raid 10 更高的冗余级别)

       7、提供系统负载,将数据读写分配到所有的服务器上,加速读写性能

       8、提供诸多高级特性,比如类似Windows的回收站功能、类似JAVA语言的GC(垃圾回收)、快照功能等

       9、MooseFS 是 Google Filesystem 的一个 c 实现

       10、自带 Web Gui 的监控接口

       11、提高随机读或写效率和海量小文件的读写效率(有待进一步证明)

缺点:

       1、Master Server 本身的性能瓶颈。MFS的主备架构情况类似于MySQL的主从复制,从可以扩展,主却不容易扩展。短期的对策就是按照业务来做切分。

       2、随着MFS体系架构中存储文件的总数上升,Master Server对内存的需求量会不断增大(MFS把文件系统的结构缓存到 Maset Server 的内存中)。根据官方提供的数据,8g对应2500kw的文件数,2亿文件就得64GB内存。短期的对策也是按照业务来做切分。

       3、Master server的单点解决方案的健壮性。目前官方自带的是把数据信息从Master Server同步到Metalogger Server上,Master Server一旦出问题Metalogger Server可以恢复升级为Master Server,但是需要恢复时间。目前,也可以通过第三方的高可用方案(heartbeat+drbd+moosefs)来解决 Master Server 的单点问题。

       4、Metalogger Server 复制元数据的间隔时间较长(可调整)


4、应用场景

      谈及MooseFS的应用场景,其实就是去谈分布式文件系统的应用场景。

      1、大规模高并发的数据存储及访问(小文件、大文件),TFS适合小文件(<1M)

      2、大规模的数据处理,如日志分析


5、使用现状

       针对 MooseFS 在全球的使用情况,我在国内的一篇论文上挖了一张图。图片如下,在该图中标记为驯鹿的就是 Moosefs 的使用者所在区域。从图中可以看出,它在中国、欧洲以及北美都拥有了大量的用户,正是有了广泛的用户基础,才能使得mfs特性能够快速的迭代和进步。

点击查看原图

MooseFS官方的使用情况链接:http://www.moosefs.org/who-is-using-moosefs.html


二、组成

1、架构图


点击查看原图

       整个架构中,主要有四个组件,分别是管理服务器 Master Server、备份服务器Metalogger Server、数据存储服务器 Chunk Server 和 客户端 Client。其中,管理服务器 Master Server 负责所有数据存储服务器的数据存储管理,响应客户端文件的读写请求,收回文件空间以及恢复文件,多存储节点之间的文件复制;元数据日志服务器 Metalogger Server,对 Master Server  服务器的变化日志文件进行备份,changelog_ml.*.mfs 是备份文件的类型,当 Master Server 出现故障时替换其继续工作,避免 Master Server 的单点故障导致分布式文件系统的不能正常运行;数据存储服务器chunkserver,服从 Master Server 的安排,定期向 Master Server 发送自己的状态信息,除此之外,还能向客户提供数据存储空间,能够向客户传输数据;客户端 Client,通过 FUSE 内核接口挂载到数据存储服务器上,在客户端看来使用数据存储服务器上的文件系统和使用本地Unix文件系统是一样的。

       下面再针对这4个组件进行更详细的介绍!


2、四个组件

组件名称 组件作用

管理服务器

Managing Server

简称Master Server 

这个组件的角色是管理整个mfs文件系统的主服务器,除了分发用户请求外,还用来存储整个文件系统中的每个数据文件的metadata信息,metadata(元数据)信息包括文件(也可以是目录、socket、管道、设备等)的大小、属性、文件位置路径等,以及文件空间的回收和恢复,控制多chunk server节点的数据拷贝。很类似lvs负载均衡主服务器,不同的是lvs仅仅根据算法分发请求,而master根据内存里的metadata信息来分发请求。这个master只能有一台处于激活工作的状态。

元数据备份服务器

Metadata backup servers

简称metalogger Server

这个组件的作用是备份管理服务器master的变化的metadata信息日志文件,文件类型为changelog_ml.*.mfs,以便于在主服务器出现问题的时候,可以经过简单的操作即可让新主服务器进行工作。这很类似Mysql的主从同步,只不过他不像mysql从库那样在本地应用数据,而只是接收主服务器上文件写入时记录的文件相关的metadata信息。这个backup可以有一台或多台,它很类似于lvs从负载均衡器。

数据存储服务器组

Data Servers

简称Chunk Servers

这个组件就是真正存放数据文件实体的服务器了,这个角色可以有多台不同的物理服务器或不同的磁盘及分区来充当,当配置数据的副本多于一份时,剧写入到一个数据服务器后,会根据算法在其他数据服务器上进行同步备份。这个很像lvs集群的rs节点。

客户机服务器组

Client

这个组件就是挂载并使用mfs文件系统的客户端,当读写文件时,客户端首先连接主管理服务器获取数据的metadata信息,然后根据得到的metadata信息,访问数据服务器读取或写入文件实体。mfs客户端通过FUSE mechanism实现挂载MFS文件系统的。因此,只要系统支持FUSE,就可以作为客户端访问MFS整个文件系统。所谓的客户端并不是网站用户,而是前端访问文件系统的应用服务器,如web


三、原理

    MooseFS是一个文件系统,因此其最主要的工作就是文件的读写流程,即 MooseFS的主要的两大工作过程。

1、MooseFS的读文件流程:

       首先要了解的是它的读过程。如下图所示:

点击查看原图

       图中 Master Server用三角形表示,Chunk Server用圆形表示,Client 用方形表示。整个读过程有以下四个步骤:

        1、首先client客户端访问主服务器master,获取文件实体的位置等相关信息

        2、主服务器master查询缓存记录,把文件实体的位置等相关信息发给client客户端

        3、Client客户端根据拿到的信息去访问对应的存储实体数据的服务器(data servers或者 chunk servers)

        4、存储实体数据的服务器(data servers或者 chunk servers)把对应的数据返回给Client客户端

        从上图,我们还可以看出,当多个MFS客户端读数据的时候,master服务器充当路由为这些客户端分发指路的作用,而数据的返回时由不同的数据服务器直接返回给请求的客户端,这样的模式可以极大的减轻主服务器的系统及网络瓶颈,增加了整个系统的吞吐,很像LVS的DR模式的负载均衡的分发和数据传输的情况。



2、MooseFS的写文件流程:

           相对于读文件,MooseFS的写文件流程较为复杂,如图所示:

点击查看原图

         图中 Master Server用三角形表示,Chunk Server用圆形表示,Client 用方形表示。

         整个写过程要分为下面八个步骤:

        1、Client客户端访问主服务器master,请求写入数据

        2、主服务器master查询缓存记录,如果是新文件,则会联系后面的数据服务器创建对应的chunk对象准备存放文件。

        3、数据服务器返回创建对应的chunk对象成功给主服务器

        4、主服务器master把文件实体的位置等相关信息发给client客户端。

        5、Client客户端访问对应的数据服务器写数据

        6、数据服务器之间进行数据同步,互相确认成功

        7、数据服务器返回成功写入信息给Client客户端

        8、Client客户端回报给主服务器master写入结束

转载作品,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://nolinux.blog.51cto.com/4824967/1600890
发表在 storage | 标签为 | MooseFS-介绍已关闭评论