| Subcribe via RSS

书评: Linux操作系统之奥秘

11月 13th, 2008 | 4 Comments | Posted in 读书笔记 < by Johnny Woo >

一直在买书看书
但是好久没有写书评了
可能是因为书太多.所以交叉着看都没来得及读完
Feng的网站上看到推荐了一本[Linux操作系统之奥秘](免费给amazon做下广告.免运费送书,使我这个china-pub的4星会员不得不跳槽了)
看到一条 把硬件和操作系统结合起来讲
引起我的兴趣了.赶快买来一本.
心中抱着希望是那种会从硬盘引导开始一直讲到init启动的书.而且会很细.很全的那种
拿到手之后.我满足了
不仅从硬盘引导.还是从BIOS开始.一直到把控制权交给init
以前读过一本[Linux 0.01内核分析与操作系统设计--创造你自己的操作系统]
这本书就是从最原始的bootloader开始从头分析.
不过对于没有汇编基础或者C语言基础的人来说.这本书未免太底层了一点
而且即便是有基础的人.看起来也会很累.因为我们只要知道原理.不需要知道那么细节的内容
而我一直想要的一本书就是讲一些比较底层.能说明原理和过程的书.也就是知其然也知其所以然的的书.
这本书的序也提到,市面上的linux书籍,要不就在于管理或者建站,要不就是直接kernel源码分析.而没有讨论linux本身概念的书.中间其实是个真空地带.
简直是一语中的.目前linux书籍的现状就是如此.两个极端.要不就是只讲些鸡毛蒜皮的命令.要不就是直接把kernel源码拿出来给你看.而整个系统的概念.流程.都没有书提及.也一直是我觉得linux类书籍无书好看的原因.
1.命令我自己会去man,参数我自己会help,只要有些英文水平.根本用不到买书.
2.我不是开发驱动,裁剪内核的开发人员.给我看了内存调度算法.于系统管理来说有一定助益,但是成本太高.
读过一半之后.我觉得这才是一本可以真正给广大linux用户推荐的好书
一本能让新手管理员更了解linux整个体系和概念的书.
当然对于linux老手
这些概念早已经在多年的摸爬滚打中混熟了.
但是有人能够从头一点点的打散理顺.还是很有帮助的
特别是看了之后再去看那本linux 0.01内核分析
嘿嘿.自己搞搞实验还是非常有意思的.

阅读内文

[转载]大型网站运维探讨和心得

11月 6th, 2008 | 1 Comment | Posted in 系统监控, 网站架构, 读书笔记, 集中存储 < by Michael Field >

看到一篇不错的心得体会;相信我们做技术的都会有或多或少的担忧自己的未来职业发展:

今天看到一篇心得体会,转过来和大家一起探讨一下:

一、什么是大型网站运维?
首先明确一下,全文所讲的”运维“是指:大型网站运维,与其它运维的区别还是蛮大的;然后我们再对大型网站与小型网站进行范围定义,此定义主要从运维复杂性角度考虑,如网站规范、知名度、服务器量级、pv量等考虑,其它因素不是重点;因此,我们先定义服务器规模大于1000台,pv每天至少上亿(至少国内排名前10),如sina、baidu、QQ,51.com等等;其它小型网站可能没有真正意义上的运维工程师,这与网站规范不够和成本因素有关,更多的是集合网络、系统、开发工作于一身的“复合性人才”,就如有些公司把一些合同采购都纳入了运维职责范围,还有如IDC网络规划也纳入运维职责。所以,非常重要一定需要明白:运维对其它关联工种必须非常了解熟悉:网络、系统、系统开发、存储,安全,DB等;我在这里所讲的运维工程师就是指专职运维工程师。
我们再来说说一般产品的“出生”流程:
1、首先公司管理层给出指导思想,PM定位市场需求(或copy成熟应用)进行调研、分析、最终给出详细设计。
2、架构师根据产品设计的需求,如pv大小预估、服务器规模、应用架构等因素完成网络规划,架构设计等(基本上对网络变动不大,除非大项目)
3、开发工程师将设计code实现出来、测试工程师对应用进行测试。
4、好,到运维工程师出马了,首先明确一点不是说前三步就与运维工作无关了,恰恰相反,前三步与运维关系很大:应用的前期架构设计、软/硬件资源评估申请采购、应用设计性能隐患及评估、IDC、服务性能\安全调优、服务器系统级优化(与特定应用有关)等都需运维全程参与,并主导整个应用上线项目;运维工程师负责产品服务器上架准备工作,服务器系统安装、网络、IP、通用工具集安装。运维工程师还需要对上线的应用系统架构是否合理、是否具备可扩展性、及安全隐患等因素负责,并负责最后将产品(程序)、网络、系统三者进行拼接并最优化的组合在一起,最终完成产品上线提供用户使用,并周而复使:需求->开发(升级)->测试->上线(性能、安全问题等之前预估外的问题随之慢慢就全出来了)在这里提一点:网站开发模式与传统软件开发完全不一样,网站一天开发上线1~5个升级版本是家常便饭,用户体验为王嘛,如果某个线上问题像M$ 需要1年解决,用户早跑光了;应用上线后,运维工作才刚开始,具体工作可能包括:升级版本上线工作、服务监控、应用状态统计、日常服务状态巡检、突发故障处理、服务日常变更调整、集群管理、服务性能评估优化、数据库管理优化、随着应用PV增减进行应用架构的伸缩、安全、运维开发工作:
a 、尽量将日常机械性手工工作通过工具实现(如服务监控、应用状态统计、服务上线等等),提高效率。
b、解决现实中服务存在的问题,如高可靠性、可扩展性问题等。
c、大规模集群管理工具的开发,如1万台机器如何在1分钟内完成密码修改、或运行指定任务?2000台服务器如何快速安装操作系统?各分布式IDC、存储集群中数PT级的数据如何快速的存储、共享、分析?等一系列挑战都需运维工程师的努力。
在此说明一下其它配合工种情况,在整个项目中,前端应用对于网络/系统工程师来说是黑匣子,同时开发工程师职责只是负责完成应用的功能性开发,并对应用本身性能、安全性等应用本身负责,它不负责或关心网络/系统架构方面事宜,当然软/硬件采购人员等事业部其它同事也不会关心这些问题,各司其职,但项目的核心是运维工程师~!所有其它部门的桥梁。
上面说了很多,我想大家应该对运维有一些概念了,在此打个比方吧,如果我们是一辆高速行驶在高速公路上的汽车,那运维工程师就是司机兼维修工,这个司机不简单,有时需要在高速行驶过程中换轮胎、并根据道路情况换档位、当汽车速度越来越快,汽车本身不能满足高速度时对汽车性能调优或零件升级、高速行进中解决汽车故障及性能问题、时刻关注前方安全问题,并先知先觉的采取规避手段。这就是运维工作~!
最后说一下运维工程师的职责:”确保线上稳定“,看似简单,但实属不容易,运维工程师必须在诸多不利因素中进行权衡:新产品模式对现有架构及技术的冲击、产品高频度的升级带来的线上BUG隐患、运维自动化管理承度不高导致的人为失误、IT行业追求的高效率导致流程执行上的缺失、用户增涨带来的性能及架构上的压力、IT行业宽松的技术管理文化、创新风险、互联网安全性问题等因素,都会是网站稳定的大敌,运维工程师必须把控好这最后一关,需具体高度的责任感、原则性及协调能力,如果能做到各因素的最佳平衡,那就是一名优秀的运维工程师了。
另外在此聊点题外话,我在这里看到有很多人要sina、QQ、baidu,51.com等聊自已的运维方面的经验,其实这对于它们有点免为其难:
a、各公司自已网络架构、规模、或多或少还算是公司的核心秘密,要保密,另外,对于大家所熟知的通用软件、架构,由于很多公司会根据自已实际业务需要,同时因为原版性能、安全性、已知bug、功能等原因,进行过二次开发(如apache,php,mysql),操作系统内核也会根据不同业务类型进行定制的,如某些应用属于运算型、某些是高IO型、或大存储大内存型。根据这些特点进行内核优化定制,如sina就在memcache上进行过二次开发,搞出了一个MemcacheDB,具体做得如何我们不谈,但开源了,是值得称赞的,国内公司对于开源基本上是索取,没有贡献;另外,服务器也不是大家所熟知的型号,根据业务特点,大部份都是找DELL/HP/ibm进行过定制;另外,在分布式储存方面都有自已解决方案,要不就是使用现成开源hadoop等解决方案,或自已开发。但90%都是借鉴google GFS的思想:分布式存储、计算、大表。
b、各公司业务方向不一样,会导致运维模式或方法都不一样,如51.com和baidu运维肯定区别很大,因为他们业务模式决定了其架构、服务器量级、IDC分布、网络结构、通用技术都会不一样,主打新闻门户的sina与主打sns的51.com运维模式差异就非常大,甚至职责都不大一样;但有一点,通用技术及大致架构上都大同小异,大家不要太神化,更多的公司只是玩垒积木的游戏罢了,没什么技术含量。
c、如上面所讲,目前大型网站运维还处于幼年时期理念和经验都比较零散,没有成熟的知识体系,可能具体什么是运维,大家都要先思索一番,或压根没想过,真正讨论也只是运维工作的冰山一角,局限于具体技术细节,或某某著名网站大的框架,真正运维体系化东西没有,这也许是目前网上运维相关资料比较少的原故吧。或者也是国内运维人员比较难招,比较牛的运维工程师比较少见的原因之一吧。

二、运维工作师需要什么样的技能及素质
做为一名运维工程师需要什么样的技能及素质呢,首先说说技能吧,如大家上面所看到,运维是一个集多IT工种技能与一身的岗位,对系统->网络->存储->协议->需求->开发->测试->安全等各环节都需要了解一些,但对于某些环节需熟悉甚至精通,如系统(基本操作系统的熟悉使用,*nix,windows..)、协议、系统开发(日常很重要的工作是自动运维化相关开发、大规模集群工具开发、管理)、通用应用(如lvs、ha、web server、db、中间件、存储等)、网络,IDC拓朴架构;
技能方面总结以下几点:
1、开发能力,这点非常重要,因为运维工具都需要自已开发,开发语言:c/c++(必备其中之一)、perl、python、php(其中之一)、shell(awk,sed,expect….等),需要有过实际开发经验,否则工作会非常痛苦。
2、通用应用方面需要了解:操作系统(目前国内主要是linux、bsd)、webserver相关(nginx,apahe,php,lighttpd,java。。。)、数据库(mysql,oralce)、其它杂七八拉的东东。。。系统优化,高可靠性。。。这些只是加分项,不需必备,可以边工作边慢慢学,这些东西都不难。当然在运维中,有些是有分工偏重点不一样。
3、系统、网络、安全,存储,CDN,DB等需要相当了解,知道其相关原理。
个人素质方面:
1、 沟通能力、团队协作:运维工作跨部门、跨工种工作很多,需善于沟通、并且团队协作能力要强;这应该是现代企业的基本素质要求了,不多说。
2、工作中需胆大心细:胆大才能创新、不走寻常路,特别对于运维这种新的工种,更需创新才能促进发展;心细,运维工程师是网站admin,最高线上权限者,一不小心就会遗憾终生或打入十八层地狱。
3、主动性、执行力、精力旺盛、抗压能力强:由于IT行业的特性,变化快;往往计划赶不上变化,运维工作就更突出了,比如国内各大公司服务器往往是全国各地,哪里便宜性价比高,就那往搬,进行大规模服务迁移(牵扯的服务器成百上千台),这是一个非常头痛的问题;往往时间非常紧迫,如限1周内完成,这种情况下,运维工程师的主动性及执行力就有很高的要求了:计划、方案、服务无缝迁移、机器搬迁上架、环境准备、安全评估、性能评估、基建、各关联部门扯皮,7X24小紧急事故响应等。
4、其它就是一些基本素质了:头脑要灵光、逻辑思维能力强、为人谦虚稳重、亲和力、乐于助人、有大局观。
5、最后一点,做网站运维需要有探索创新精神,通过创新型思维解决现实中的问题,因为这是一个处于幼年的职业(国外也一样,但比国内起步早点),没有成熟体系或方法论可以借鉴,只能靠大家自已摸索努力。

三、怎样才算是一个合格的运维工程师
1、保证服务达到要求的线上标准,如99.9%;保证线上稳定,这是运维工程师的基本责职所在。
2、不断的提升应用的可靠性与健壮性、性能优化、安全提升;这方面非常考验主动性、和创新思维。
3、网站各层面监控、统计的覆盖度,软件、硬件、运行状态,能监控的都需要监控统计,避免监控死角、并能实时了解应用的运转情况。
4、通过创新思维解决运维效率问题;目前各公司大部份运维主要工作还是依赖人工操作干预,需要尽可能的解放双手。
5、运维知识的积累与沉淀、文档的完备性,运维是一个经验性非常强的岗位,好的经验与陷阱都需积累下来,避免重复性范错。
6、计划性和执行力;工作有计划,计划后想法设法达到目标,不找借口。
7、自动化运维;能对日常机械化工作进行提炼、设计并开发成工具、系统,能让系统自动完成的尽量依靠系统;让大家更多的时间用于思考、创新思维、做自已喜欢的事情。
以上只是技术上的一些层面,当然个人意识也是很重要的。

四、运维职业的迷惘、现状与发展前景
运维岗位不像其它岗位,如研发工程师、测试工程师等,有非常明确的职责定位及职业规划,比较有职业认同感与成就感;而运维工作可能给人的感觉是哪方面都了解一些,但又都比上专职工程师更精通、感觉平时被关注度比较低(除非线上出现故障),慢慢的大家就会迷惘,对职业发展产生困惑,为什么会有这种现象呢? 除了职业本身特点外,主要还是因为对运维了解不深入、做得不深入导致;其实这个问题其它岗位也会出现,但我发现运维更典型,更容易出现这个问题;

针对这个问题我谈一下网站运维的现状及发展前景(也在思考中,可能不太深入全面,也请大家斧正补充)

运维现状:
1、处于刚起步的初级阶段,各大公司有此专职,但重视或重要承度不高,可替代性强;小公司更多是由其它岗位来兼顾做这一块工作,没有专职,也不可能做得深入
2、技术层次比较低;主要处于技术探索、积累阶段,没有型成体系化的理念、技术。
3、体力劳动偏大;这个问题主要与第二点有关系,很多事情还是依靠人力进行,没有完成好的提练,对于大规模集群没有成熟的自动化管理方法,在此说明一下,大规模集群与运维工作是息息相关的如果只是百十来台机器,那就没有运维太大的生存空间了。
4、优秀运维人才的极度缺乏;目前各大公司基本上都靠自已培养,这个现状导致行业内运维人才的流动性非常低,非常多好的技术都局限在各大公司内部,如google 50万台机器科学的管理,或者国内互联公司top 10 的一些运维经验,这些经验是非常有价值的东西并决定了一个公司的核心竞争力;这些问题进而导致业内先进运维技术的流通、贯通、与借签,并最终将限制了运维发展。
5、很多优秀的运维经验都掌握在大公司手中;这不在于公司的技术实力,而在于大公司的技术规模、海量PV、硬件规模足够大,如baidu可怕的流量、51.com海量数据~~~~这些因素决定了他们遇到的问题都是其它中/小公司还没有遇到的,或即将遇到。但大公司可能已有很好的解决方案或系统。
发展前景:
1、从行业角度来看,随着中国互联网的高速发展(目前中国网民已跃升为全球第一)、网站规模越来越来大、架构越来越复杂;对专职网站运维工程师、网站架构师的要求会越来越急迫,特别是对有经验的优秀运维人才需求量大,而且是越老越值钱;目前国内基本上都是选择毕业生培养(限于大公司),培养成本高,而且没有经验人才加入会导致公司技术更新缓慢、影响公司的技术发展;当然,毕业生也有好处:白纸一张,可塑性强,比较认同并容易融入企业文化。
2、从个人角度,运维工程师技术含量及要求会越来越高,同时也是对公司应用、架构最了解最熟悉的人、越来越得到重视。
3、网站运维将成为一个融合多学科(网络、系统、开发、安全、应用架构、存储等)的综合性技术岗位,给大家提供一个很好的个人能力与技术广度的发展空间。
4、运维工作的相关经验将会变得非常重要,而且也将成为个人的核心竞争力,具备很好的各层面问题的解决能力及方案提供、全局思考能力等。
5、特长发控和兴趣的培养;由于运维岗位所接触的知识面非常广阔,更容易培养或发挥出个人某些方面的特长或爱好,如内核、网络、开发、数据库等方面,可以做得非常深入精通、成为这方面的专家。
6、如果真要以后不想做运维了,转到其它岗位也比较容易,不会有太大的局限性。当然了,你得真正用心去做。
7、技术发展方向、网站/系统架构师。

五、运维关键技术点解剖
1、 大规模集群管理问题
首先我们先要明确集群的概念,集群不是泛指各功能服务器的总合,而是指为了达到某一目的或功能的服务器、硬盘资源的整合(机器数大于两台),对于应用来说它就是一个整体,目前常规集群可分为:高可用性集群(HA),负载均衡集群(如lvs),分布式储、计算存储集群(DFS,如google gfs ,yahoo hadoop),特定应用集群(某一特定功能服务器组合、如db、cache层等),目前互联网行业主要基于这四种类型;对于前两种类似,如果业务简单、应用上post操作比较少,可以简单的采用四层交换机解决(如f5),达到服务高可用/负责均衡的作用,对于资源紧张的公司也有一些开源解决办法如lvs+ha,非常灵活;对于后两种,那就考验公司技术实力及应用特点了,第三种DFS主要应用于海量数据应用上,如邮件、搜索等应用,特别是搜索要求就更高了,除了简单海量存储,还包括数据挖掘、用户行为分析;如google、yahoo就能保存分析近一年的用户记录数据,而baidu应该少于30天、soguo就更少了。。。这些对于搜索准备性、及用户体验是至关重要的。
接下来,我们再谈谈如何科学的管理集群,有以下关键几点:
I、监控
主要包括故障监控和性能、流量、负载等状态监控,这些监控关系到集群的健康运行,及潜在问题的及时发现与干预;
a、服务故障、状态监控:主要是对服务器自身、上层应用、关联服务数据交互监控;例如针对前端web server,我们就可以有很多种类型的监控,包括应用端口状态监控,便于及时发现服务器或应用本身是否crash、通过icmp包探测服务器健康状态,更上层可能还包括应用各频道业务的监控,常用方法是采用面业特征码进行判断,或对重点页面进行签名,以网站被黑篡改(报警、并自动恢复被篡改数据)等等,这些只是一部份,还有N多监控方式,依应用特点而定,还有一些问题需解决,如集群过大,如何高性能的进行监控也是一个现实问题。
b、其它就是集群状态类的监控或统计,为我们合理管理调优集群提供数据参考、包括服务瓶颈、性能问题、异常流量、攻击等问题。
II、故障管理
a、硬件故障问题;对于成百上千或上万机器的N多集群,服务器死机、硬件故障概率是非常大的,几乎每时每刻都有服务硬件问题,死机、硬盘损坏、电源、内存、交换机。针对这种情况,我们在设计网站架构时需要充分考虑到这些问题,并将其视为常态;更多的依靠应用的冗余机制来规避这种风险,但给系统工程师足够宽裕的处理时间。(如google不是号称同时死800台机器,服务不会受到任何影响吗);这就是考验运维工程师及网站架构师功能的地方了,好的设计能达到google所描述自恢复能力,如gfs,糟糕的设计那就是一台服务器的死机可能会造成大面积服务的连锁故障反映,直接对用户拒绝响应。
b、应用故障问题;可能是某一bug被触发、或某一性能阀值被超越、攻击等情况不一而定,但重要的一点,是要有对这些问题的预防性措施,不能想当然,它不会出问题,如真出问题了,如何应对? 这需要运维工程师平时做足功夫,包括应急响应速度、故障处理的科学性、备用方案的有效等。

III、自动化
自动化:简而言之,就是将我们日常手动进行的一些工作通过工具,系统自动来完成,解放我们的双手及枯燥的重复性劳动,例如:没有工具前,我们安装系统需要一台一台裸机安装,如2000台,可能需要10人/10天,搞烂N张光盘,人力成本更大。。。而现在通过自动化工具,只需几个简单命令就能搞定、还有如机器人类程序,自动完成以往每天人工干预的工作,使其自动完成、汇报结果,并具备一定的专家系统能力,能做一些简单的是/非判断、优化选择等。。。这些好处非常明显不再多说。。。应该说,自动化运维是运维工程师职业化的一个追求,利已利公,虽然这是一个异常艰巨的任务:不断变更的业务、不规范化的应用设计、开发模式、网络架构变更、IDC变更、规范变动等因素,都可能会对现有自动化系统产生影响,所以需要模块化、接口化、变因参数化等因此,自动化相关工作,是运维工程师的核心重点工作之一,也是价值的体现。
五、运维中关键技术点解剖(比较实际,现实中的案例,今天先想出这几条,如大家有其它感觉兴趣的,可以提出,一起交流~)

1 大量高并发网站的设计方案
2 高可靠、高可伸缩性网络架构设计
3 网站安全问题,如何避免被黑?
4 南北互联问题,动态CDN解决方案
5 海量数据存储架构

转自chinaunix

阅读内文

[转载]RRDTool 中文手册-简易入门(二)

8月 19th, 2008 | No Comments | Posted in Cacti, RRDTool, 系统监控, 读书笔记 < by Michael Field >

三、RRD数据库更新实例

    在简易入门(一)中已经介绍过update 命令:它使用1个或多个参数,其格式为: : . 如果你知道可以用一个 N 表示当前的时间,你一定会高兴的。或者你可以用Perl中的 time 函数来指定时间:
    perl: perl -e ‘print time, “\n” ‘
    shell: date +%s
    如何按照固定间隔运行某个程序各操作系统不同。不过可以用伪码来表示:
    - Get the value and put it in variable “$speed”
    - rrdtool update speed.rrd N:$speed

    就这些。每5分钟运行一次上面的脚本。在你想知道图像看起来是啥样时,运行上面的例子。你可以把他们放入一个脚本中。运行此脚本后,查看我们刚才创建的graph。

四、SNMP相关知识

    我可以想像到只有少数的人能够每5分钟从他们的汽车中读取一次真实的数据。其他人不得不清算其他类型的计数器。你可以测量打印机打印的页数,咖啡机做的咖啡杯数,计算使用的电流的设备,都可以。递增的计数器可以被监视,并且用你已经学会的方法被绘制成图像。稍后我们就能够监视像温度计这样的值了。
    大多数对RRDtool感兴趣的人会使用一个跟踪网络设备传输数据量的计数器。这样我们下一步就来作这个。我们会从解释如何收集数据开始。

    有些人会说有些工具可以帮助你收集数据。他们是对的!不过,我感觉理解这些工具不是必须的非常重要。在你能够确定为什么事情发生了错误,你要知道他们是如何工作的。

    本例中使用的工具在本文档前面非常简短地提到过,它就是所谓的SNMP。它是与联网设备交谈的方式。

下面用到的工具名为 snmpget ,以下是关于它是如何工作的说明:

snmpget device password OID

snmpget -v[version] -c[password] device OID
    对于device, 你要用设备的名称或者IP地址来替换。对于password, 你需要使用SNMP领域中称为 comunity read string 来替换。对于某些设备来说,缺省的 public 可以工作,但是该设置可能会被关闭,调整或者由于安全和机密的原因而被保护起来。请阅读你的设备或程序的文档。

    接下来有一个称为OID的参数,它用来表示 对象标识符 。

    刚开始学习SNMP时,它看起来有些令人困惑。在你看到MIB管理信息基时,就不会那么困难了。MIB是用来描述数据的倒状树,它有只有一个根结点,并且由根结点开始有多个分支。这些分支都以另一个结点终结,他们继续向下分支,如此继续。所以的分支都有一个名称,它们构成了一个我们能够沿着往下的路径。我们所沿着的这些分支都被命名了:iso, org, dod, internet, mgmt 和mib-2.这些名称也可以用数字方式记录,就像 1 3 6 1 2 1。
    iso.org.dod.internet.mgmt.mib-2 (1.3.6.1.2.1)

    有些程序会使用前导点 . , 令人感到许多困惑。在一个OID中并 没有前导点。为了显示OID缩记法和OID完整记法的区别,(通常约定)在使用OID的完整记法时使用前导点。通常这些程序在返回数据给你时,会省略却缺省的部分。这些程序有的有几个缺省前缀,这会让事情显得更加糟糕。
    Ok, lets continue to the start of our OID: we had 1.3.6.1.2.1 From there, we are especially interested in the branch interfaces which has number 2 (e.g., 1.3.6.1.2.1.2 or 1.3.6.1.2.1.interfaces).

    好了,我们继续OID的初步学习:我们有一个1.3.6.1.2.1的OID,我们对(其下面的) interface 分支特别感兴趣,其编号为2(例如:1.3.6.1.2.1.2 或 1.3.6.1.2.1.interface)。

    首先,我们得要有几个SNMP的程序。先看看你的OS平台上是否有已编译好的软件包。这是最便捷的方式。如果没有,你就得下载源代码、并编译。互联网上到处都是源代码、程序。你可以用你喜欢的任何方式、搜索引擎来找到相关的信息。

    假设你已经有了这些程序。先试着收集大多数系统都有的数据。记住:那些引起我们兴趣的树,它上面的部分都有一个简略名。

    在此我会给出一个在Fedora Core 3操作系统上可用的例子。如果对你的操作系统不可用,请查看snmp的手册,并作相应的调整让它能够运行。

snmpget -v2c -c public myrouter system.sysDescr.0
    该设备应当回应其自身的描述,该描述可能是一个空的。只有在你从某个设备获得响应后,你才能够继续。其中可能需要使用不同的口令、或者不同的设备。
snmpget -v2c -c public myrouter interfaces.ifNumber.0

    最好你得到的结果是一个数字。如果这样的话,你就可以继续往下,并试试另一个叫做 snmpwalk 的程序。

snmpwalk -v2c -c public myrouter interfaces.ifTable.ifEntry.ifDescr
    如果该命令返回一系列的接口,这就对了。以下是该命令运行的返回结果的例子:
[user@host /home/alex]$ snmpwalk -v2c -c public cisco 2.2.1.2
interfaces.ifTable.ifEntry.ifDescr.1 = "BRI0: B-Channel 1"
interfaces.ifTable.ifEntry.ifDescr.2 = "BRI0: B-Channel 2"
interfaces.ifTable.ifEntry.ifDescr.3 = "BRI0" Hex: 42 52 49 30
interfaces.ifTable.ifEntry.ifDescr.4 = "Ethernet0"
interfaces.ifTable.ifEntry.ifDescr.5 = "Loopback0"
    对于cisco设备,我想监视 ‘Ethernet0` 接口,从上面的输出结果能够看到该接口的编号是 4。 我试着运行如下命令:
[user@host /home/alex]$ snmpget -v2c -c public cisco 2.2.1.10.4 2.2.1.16.4

interfaces.ifTable.ifEntry.ifInOctets.4 = 2290729126
interfaces.ifTable.ifEntry.ifOutOctets.4 = 1256486519
    这样,我就有两个OID需要监视,他们是(这次使用完整记法):
    1.3.6.1.2.1.2.2.1.10

    1.3.6.1.2.1.2.2.1.16
    这两个OID都有接口编号4。
    别被糊弄了,我可不是试一次就搞定的。我花了一些数据来搞清这些数字都是什么意思。把这些编号转换成描述文字大有帮助… 至少在大家谈论MIB和OID时,你知道他们是什么东西。别忘了接口编号(如果它不是附属接口,就是0),如果用snmpget没有得到响应,试试 snmpwalk。

五、应用RRDtool的实例

    实际运用的例子
    开始有趣的东东吧。首先,创建一个新的数据库。它包含输入和输出2个计数器的数据。该数据被放入能够进行平均的归档中。他们一次使用1、6、24、或 288个样本。他们同时被存入保存最大数字的归档中。稍后会解释。样本间隔时间为300秒,也就是5分钟,这是一个好的开始。:

    1个样本 “平均” 保留5分钟的周期
    6个样本 每30分钟进行一次平均
    24个样本 每2小时进行一次平均
    288个样本 每1天进行一次平均

    我们试着与MRTG互相兼容,MRTG存储以下数据::

    600 5分钟样本数: 2天和2小时
    600 30分钟样本数: 12.5天
    600 2小时样本数: 50天
    732 1天样本数: 732天

    这些范围被补充进去,因此在数据库中保存的数据总数大约797天。RRDtool存储不同的数据,它不会在 每日 归档停止的地方开始 每周 归档。对于这两个归档,最新的数据会是在 now 附近,因此我们需要比MRTG保存更多的数据!
    我们需要::

    600个5分钟的样本 (2天和2小时)
    700个30分钟的样本 (2天和2小时,加12.5天)
    775个2小时的样本 (上述+50天)
    797个1天的样本 (上述+732天,环型回绕最大797)

rrdtool create myrouter.rrd \
DS:input:COUNTER:600:U:U \
DS:output:COUNTER:600:U:U \
RRA:AVERAGE:0.5:1:600 \
RRA:AVERAGE:0.5:6:700 \
RRA:AVERAGE:0.5:24:775 \
RRA:AVERAGE:0.5:288:797 \
RRA:MAX:0.5:1:600 \
RRA:MAX:0.5:6:700 \
RRA:MAX:0.5:24:775 \
RRA:MAX:0.5:288:797

接下来要做的就是收集数据并把它保存起来。以下是一个例子。它是用伪码写的,你得根据OS调整后让它能够运行。:

while not the end of the universe
do
get result of
snmpget router community 2.2.1.10.4
into variable $in
get result of
snmpget router community 2.2.1.16.4
into variable $out

rrdtool update myrouter.rrd N:$in:$out

wait for 5 minutes
done

在收集了1天的数据后,试着用下面的命令创建图像::

rrdtool graph myrouter-day.png --start -86400 \
DEF:inoctets=myrouter.rrd:input:AVERAGE \
DEF:outoctets=myrouter.rrd:output:AVERAGE \
AREA:inoctets#00FF00:"In traffic" \
LINE1:outoctets#0000FF:"Out traffic"

这会产生一个具有1天流量值的图像。1天有24(小时)x60(分钟)x60(秒)。我们从当前时间-86400秒开始。我们用DEF把输入和输出字节数定义成myrouter.rrd数据库中的的平均值,并且绘制输入流量区和输出流量线。

阅读内文 Tags: , , ,

[转载]RRDTool 中文手册-简易入门(一)

8月 18th, 2008 | No Comments | Posted in Cacti, RRDTool, 系统监控, 读书笔记 < by Michael Field >

一、简介

    RRDtool是由Tobias Oetiker 编写并由全球各地的许多人贡献的工具。本篇文档的作者是Alex van den Bogaerdt 主要是帮助你理解RRDtool是什么,它能够帮助你作些什么。 RRDtool的文档对于有些人来说过于技术化。本教程帮助你理解RRDtool的基本概念。它为你自学RRDtool的文档做好准备。本文档还重点介绍了网络统计方面的知识。


1、RRDtool是什么东西?

    RRDtool是指Round Robin Database 工具(环状数据库)。Round robin是一种处理定量数据、以及当前元素指针的技术。想象一个周边标有点的圆环--这些点就是时间存储的位置。从圆心画一条到圆周的某个点的箭头--这就是指针。就像我们在一个圆环上一样,没有起点和终点,你可以一直往下走下去。过来一段时间,所有可用的位置都会被用过,该循环过程会自动重用原来的位置。这样,数据集不会增大,并且不需要维护。RRDtool处理RRD数据库。它用向RRD数据库存储数据、从RRD数据库中提取数据。


2、RRD中可以存放什么样的数据?

    可以适合时间序列的数据。就是说你必须能够在时间的几个点上度量某些值,并提供这些信息给RRDtool。如果你能够做到这一点,RRDtool就能够存储它们。这些数值必须是数字,但是不一定要是整数,在与MRTG合用时。(下一节会给出更详细的介绍)。
    下面的例子是关于SNMP的,SNMP是简单网络过来协议的缩写。简单是指协议简单--并不表示管理或监视网络简单。读完本篇文档后,你应当能够对人们谈论的SNMP的东西有更多的理解。现在,只要知道SNMP可以用来查询设备中保持的计数器的值就可以了。我们要存放到RRD数据库中的正是这些计数器中的数值。


3、RRDtool可以用来干什么?

    RRDtool源自MRTG(多路由器流量绘图器)。MRTG是有一个大学连接到互联网链路的使用率的小脚本开始的。MRTG后来被当作绘制其他数据源的工具使用,包括温度、速度、电压、输出量等等。
    很可能你会从使用RRDtool来存储和处理通过SNMP收集到的数据开始。这些数据很可能是某个网络或计算机接收或发送的字节数(比特数)。它也可以用来显示潮水的波浪、阳光射线、电力消耗、展会的参观人员、机场附近的噪音等级、你喜欢的度假区的温度、电冰箱的温度、以及任何你可以想象的东西。
    你最需要一个度量数据,以及能够提供这些数据给RRDtool的感应器就可以了。RRDtool会让你创建数据库、存储数据、提取数据、创建用于在Web浏览器中显示的PNG格式的图像。这些PNG图像以来于你收集的数据,它可以是网络平均使用率、峰值。


4、问题探讨

    首先:再读一遍!你可能漏了某些地方。如果你无法编译源代码,而且你的操作系统相当普遍,很可能不是RRDtool的错误。互联网上有已经编译好的版本。如果来自可信赖的网站,就下载一个。
    另一种情况是程序能够工作,但是没有得到预期的结果,可能是配置方面的问题。检查你的配置,与后面例子的配置比较一下。
    RRDtool有一个邮件列表及其归档。读一下几周的列表并搜索归档。没有搜索过归档就提问是很粗鲁的做法:你遇到的问题可能已经由其他人解决了!尽管不是全部,大多数问题都会这样,邮件列表不是经济为了某个参与者服务的。看看RRDtool的文档了解邮件列表的位置和使用方法。
    我建议你马上就花点时间订阅邮件列表,只要发送一封主题为 subscribe 的邮件到 rrd-user-request@list.ee.ethz.ch 就可以了。如果要退定该邮件列表,只需要发送主题为 unsubscribe 到同样的地址即可。


二、学习实例
1、第一个RRD数据库

    在我看来,学习某个东西的最好办法就是实践。为什么现在不开始呢?我们会创建一个数据库,放一些数值到它里面,然后提取这些数据。你的输出应当与本文档中的输出是一样的。
    我们会从一些简单的入手,然后把汽车与路由器比较,或者将公里和比特、字节数比较。他们都是一样的:都是某些时段的某些数值。
    假设我们有一个向互联网发送数据和接收数据的设备。该设备保留一个计数器,该计数器在开启设备时设置为0,并在每传送一个字节就加1。该计数器可能会有一个最大值。如果该值达到最大时,在加一个字节的计数,该计数器就会再次从0开始。这与世界上的许多计数器都是一样的,比如车辆上的里程计数器。
    关于网络的讨论通常用每秒比特数来衡量,因此我们要习惯这种用法。把一个字节看成是8个比特,并且开始用比特而不是字节来思考问题。不过,计数器仍然用字节数为单位来计量!在SNMP世界里,大部分的计数器都是32比特的。这就意味着他们计数范围是0-4294967。我们在例子里会用到这些数值。该设备在被查询时,会返回计数器的当前值。我们知道从上次查询设备开始到现在的时间,因此我们现在就知道每秒 平均传输了多少字节数。这不难计算。首先用文字来描述,然后计算:

用当前查询到的计数器值,减去上一次查询的计数器值
把当前查询时间和上次查询时间作上述同样操作(秒)
将(1)的结果除以(2)的结果,得到的结果就是每秒的字节数。乘以8就得到每秒的比特数(bps)

  • 实例一
    • 你现在正在开车。12:05时你看了一下仪表盘上的里程计数器,它显示这俩车已经行驶了12345公里。12:10分时,你有看了一下里程计数器,它显示 12357公里。这表示你在5分钟内行驶了12公里。科技人员会把它转换成米/秒,这样可以更好的进行比较(每5分钟的字节数)和(每秒比特数)。
      我们行驶了12公里,也就是12000米。我们在5分钟内,或者说是300秒内完成。我们的速度是1200米/300秒,或者说是40米/秒。
      我们可以用公里/小时来计算速度:12乘以5分钟就是一个小时,因此我们必须把12公里乘以12得到144公里/小时。对于和我一样说英语的朋友来说,就是90英里/小时,因此不要在家里或我生活的地方尝试这个速度 :)
      记住:这些数值都仅仅是平均值。如果无法从数字中得到你是否以固定的速度在行驶。本教程后面有一个例子说明这个问题。我希望你理解在计算米/秒或者比特/秒。唯一的差别在于收集数据的方式。即使是K这个单位也是一样的,因为在网络术语中,K同样表示1000。
      我们现在要创建一个数据库,在此数据库中我们能够保存所有这些有趣的数字。启动这个程序的方法可能在各个操作系统上各不相同,但是我假设你可以搞清楚它是否与你的操作系统不同,键入下面的行作为一个长长的行(为了可读性,我得把他分成几行)并且用 \ 来分割。
    rrdtool create test.rrd \
    --start 920804400 \
    DS:speed:COUNTER:600:U:U \
    RRA:AVERAGE:0.5:1:24 \
    RRA:AVERAGE:0.5:6:10


    2、创建了什么东西?

      我们创建的rrd数据库名为test (test.rrd),它的起始时间是我写这篇文档的当天下午,也就是1999年3月7日(该日期转换成920804400秒)。我们的数据库存放一个名为 ’speed’ 的数据源(DS),它表示一个计数器。该计数器每5分钟(缺省)读取一次。在同一个数据库中,保存有2个环状归档(RRA),一个是每次读取时的平均数据(例如:没有东西进行平均)并保留24个样本(24乘以5分钟是2小时)。另一个RRA有6个平均值(半小时)并包含10个这样的平均值(例如5个小时)。

      RRDtool使用来源于UNIX世界的特殊时间戳。该时间戳是自1979年1月1日UTC时间开始到当前逝去的秒数。该时间戳的值被转换成本地时间,它在不同的时区会不一样。
      可能你不是和我在地球的同一个地方。这就是说时区不同。在所有的例子中,我所说的时间当中,小时可能对你来说是错误的。这对这些例子中的结果有一点影响,在阅读时,只需要修正时间中的小时即可。例如:我看到 12:05 的话,在英国的家伙看到的时间就是 11:05 。

    现在我们得向数据库中填入一些数字。我们希望读到以下数据:
    12:05 12345 KM
    12:10 12357 KM
    12:15 12363 KM
    12:20 12363 KM
    12:25 12363 KM
    12:30 12373 KM
    12:35 12383 KM
    12:40 12393 KM
    12:45 12399 KM
    12:50 12405 KM
    12:55 12411 KM
    13:00 12415 KM
    13:05 12420 KM
    13:10 12422 KM
    13:15 12423 KM

  • 我们用下面的命令把上述数据填入数据库:
  • rrdtool update test.rrd 920804700:12345 920805000:12357 920805300:12363
    rrdtool update test.rrd 920805600:12363 920805900:12363 920806200:12373
    rrdtool update test.rrd 920806500:12383 920806800:12393 920807100:12399
    rrdtool update test.rrd 920807400:12405 920807700:12411 920808000:12415
    rrdtool update test.rrd 920808300:12420 920808600:12422 920808900:12423

    正如你说看到的那样,可以在一个命令里向数据库中填入多个值。为了可读性,我得只用三个数据,实际一行里运行的最大数据与操作系统相关。
    我们可以使用 rrdtool fetch 命令从数据库中提取数据。

    rrdtool fetch test.rrd AVERAGE --start 920804400 --end 920809200
      该命令会返回如下输出结果:
      speed

      920804700: nan
      920805000: 4.0000000000e-02
      920805300: 2.0000000000e-02
      920805600: 0.0000000000e+00
      920805900: 0.0000000000e+00
      920806200: 3.3333333333e-02
      920806500: 3.3333333333e-02
      920806800: 3.3333333333e-02
      920807100: 2.0000000000e-02
      920807400: 2.0000000000e-02
      920807700: 2.0000000000e-02
      920808000: 1.3333333333e-02
      920808300: 1.6666666667e-02
      920808600: 6.6666666667e-03
      920808900: 3.3333333333e-03
      920809200: nan
      如果不是像上面的输出结果,可能哪里有错误。也许你的操作系统会打印出不同的格式 NaN 。 NaN 表示 非数字 。 如果你的操作系统输出 U 或 UNKN 或者其他类似东西都是正常的。如果其他地方错误,可能是因为你的过程中的那些步骤出错了(当然假设我的教程是完全正确的 :-))。这样的话,删除数据库文件然后再重新尝试。 有时事情就会变化。本例哟难道的数据像 0.04 而不是 4.0000e-02 。这些实际上是一样的数字,只是写法不同而已。如果rrdtool今后的版本显示略有不同是输出也不要大惊小怪。本文档中的例子对于RRDtool 1.2.0版本都是正确的。


    3、绘第一张图

    建几个图示的时候到了,试试下面的命令:

    rrdtool graph speed.png \
    --start 920804400 --end 920808000 \
    DEF:myspeed=test.rrd:speed:AVERAGE \
    LINE2:myspeed#FF0000

  • 如图一

    • 该命令会创建名为speed.png的图像文件,该图像从12:00开始,到13:00。有一个名为myspeed的变量定义,它使用来自 test.rrd数据库的 speed RRA中的数据。绘制的线条是2像素高,表示myspeed变量。颜色是红色的.
      你会注意到图像的起始不是12:00而是12:05。这是因为在此时间之前的数据不够计算出平均值。这只会在缺少某些样本的情况下发生,不会经常发生。
      颜色是由红、绿、蓝构成的。对每种颜色成分,你可以用16进制来表示使用多少,其中00表示不包含,FF表示完全包含。白色是由红、绿、蓝组成的:FFFFFF。黑色是全部不包含:000000。


    4、用几种数学方法来绘图

      查看图像时,你会注意到横轴下标为 12:10、12:20、12:30、12:40、12:59。有时某些下标不适合(可能是12:00和13:00)会被忽略掉。
      纵轴显示我们输入的范围。下面提供的公里数,以及除以300妙的结果,我们得到非常小的数值。为了更加精确,第一个值是12(12567-12456),除以300后得到0.04,RRDtool显示时为 40m 表示 40/1000 。 其中的 m 与米、公里、或者毫米都没有任何关系!RRDtool不知道我们的数据单位,它只处理没有单位的数据。
      如果我们用米来衡量我们的距离,就会是这样:(12′357′000-12′345′000)/300 = 12′000/300 = 40.
      因为许多人都对这样的数值范围感觉更好,我们就来修正一下。我们将重新创建数据库,并存储正确的数据。但是有更好的办法:在创建png文件时进行一些计算!
    rrdtool graph speed2.png \
    --start 920804400 --end 920808000 \
    --vertical-label m/s \
    DEF:myspeed=test.rrd:speed:AVERAGE \
    CDEF:realspeed=myspeed,1000,\* \
    LINE2:realspeed#FF0000

  • 如图二


  • 注意:不要忘记操作符 * 后面的 。这个反斜杆用来将*从操作系统可能解释的符号转义,而不是直接传递给rrdtool命令。
    在查看PNG文件后,你会注意到 m 不见了。正确的结果就是这样。同样,在图像中加入了一个标注。出了上面提到的几点外,PNG看起来应当是一样的。

      计算是在CDEF部分中指定的,使用逆波兰表达式( RPN )表示的。我们要求RRDtool所作的事情是:`取数据源myspeed, 以及数值1000;把他们相乘` 。在此不要被RPN表达式困扰了,后面会详细介绍。同时,你可能想读一读关于CDEF的教程。以及Steve Rader的RPN表达式的教程。不过哦首先看我这篇教程吧。
      如果我们用1000乘以这些数值,显示把同样的数据显示成公里/小时也是可以的。
      要修改米/秒为单位的值:
      计算米/小时: value * 3′600
      计算公里/小时: value / 1′000
      合起来: value * (3′600/1′000) 或者 value * 3.6

    下面我们来创建这个PNG文件,并加入更多的魔幻功能…

    rrdtool graph speed3.png \
    --start 920804400 --end 920808000 \
    --vertical-label km/h \
    DEF:myspeed=test.rrd:speed:AVERAGE \
    "CDEF:kmh=myspeed,3600,*" \
    CDEF:fast=kmh,100,GT,kmh,0,IF \
    CDEF:good=kmh,100,GT,0,kmh,IF \
    HRULE:100#0000FF:"Maximum allowed" \
    AREA:good#00FF00:"Good speed" \
    AREA:fast#FF0000:"Too fast"

  • 如图三


  • 这个图像看起来更好。速度用KM/H表示,有一个附加的线条表示最大允许的速度(在我行驶的道路上的最大限速)。我还修改了速度的显示颜色,把它从线条改为区块。


    5、一个更复杂的图例

      现在计算更加复杂一些。对于在限速内的速度衡量方法是:
      检查公里/小时是否大于100 ( kmh,100 ) GT
      如果是,返回0,否则返回公里/小时。 ((( kmh,100 ) GT ), 0, kmh) IF

      对于上述的限速值:
      检查公里/小时是否大于100 ( kmh,100 ) GT
      如果是,返回公里/小时,否则返回0。 ((( kmh,100) GT ), kmh, 0) IF

    我愿意相信RRDtool的绘图功能能够处理的数据没有任何虚拟的限制。我会解释他们是如何工作的,不过看看下面的PNG图像:

    rrdtool graph speed4.png \
    --start 920804400 --end 920808000 \
    --vertical-label km/h \
    DEF:myspeed=test.rrd:speed:AVERAGE \
    "CDEF:kmh=myspeed,3600,*" \
    CDEF:fast=kmh,100,GT,100,0,IF \
    CDEF:over=kmh,100,GT,kmh,100,-,0,IF \
    CDEF:good=kmh,100,GT,0,kmh,IF \
    HRULE:100#0000FF:"Maximum allowed" \
    AREA:good#00FF00:"Good speed" \
    AREA:fast#550000:"Too fast" \
    STACK:over#FF0000:"Over speed"

  • 如图四

  • 第一部分完
    本文从网上转载,本人重新整理和附图,出处未考证。

    阅读内文 Tags: , , ,

    最近的读书计划

    5月 13th, 2008 | No Comments | Posted in 读书笔记 < by Johnny Woo >

    ppk谈JavaScript
    C和指针
    编程之美
    JavaScript核心指南

    阅读内文

    好书推介

    4月 30th, 2008 | No Comments | Posted in 读书笔记 < by Johnny Woo >

    Speed Up Your Site (暂未引进)
    优化网站的技巧和方法

    Defensive Design for the Web (暂未引进)
    由37 signals编写的一本书.讲述web网站的防御式编程,也许很多设计者认为给用户看404没什么大不了
    那么这本书会告诉你,你错了.
    和37 signals的其他书一样,短小,精悍,切中要害.

    High Performance MySQL (暂未引进)
    调优MySQL性能以及优化SQL语句

    Windows Via C/C++ (暂未引进)
    windows核心编程的第五版

    Getting Real (暂未引进)
    快速开发的新思维,包括产品设计的新思维,知道Ruby On Rails么.那你应该读一下他们是如何成功的

    Don’t Make Me Think [点石成金-访客至上的网页设计秘笈]
    已经有中译本,全彩书,这本书讲述了关于WEB UI设计方面的金科玉律.
    如何使用户不用思考和寻找即可使用他想要的功能
    在国内绝大多数网站都是贪图大,全,炫的前景下
    这本书的出炉更显出它的重要性

    The Design of Everyday Things [设计心理学] (已绝版)
    工业设计心理学必读,对于设计方面的用户心理进行分析
    怎样的设计才能让用户不用思考就顺畅使用

    GUI Bloopers [GUI设计禁忌] & WEB Bloopers [WEB设计禁忌] (均已绝版)
    关于可用性设计方面的另两份力作
    如何避免用户界面设计方便的弊病
    虽然我们不能说达到哪些条件的设计是好的(这样就会扼杀创新)
    但是我们能够总结哪些设计是糟糕的和需要避免的
    如果你的开发团队里面没有专业的UI设计师
    那么可能就需要让所有开发者都去读一下这两本书的其中一本

    阅读内文

    <构建可扩展WEB站点>心得

    4月 22nd, 2008 | No Comments | Posted in 读书笔记 < by Johnny Woo >

    序言:
    基本上这本书对于一个比较熟悉系统架构的工程师来说
    后面1/2的内容(第八章开始)才是稍微有些看头的.
    这本书对于大网站架构的入门还是不错的
    但是不够深入.建议需要深入者,还是阅读例如<High Performance Mysql>等书更好.

    正文:
    扩展的三要素:
    1.系统能够容纳使用率的增加
    2.系统能够容纳数据集的增加
    3.系统可维护

    扩展的两种方法:
    1.垂直扩展
    通过直接增加单台服务器的性能来提高吞吐量
    2.水平扩展
    增加服务器数量来分摊负载,从而提高吞吐量

    MySQL复制模式解决同步流量问题方法:
    为MySQL Slave服务器建立内网
    由于数据库服务器一般位于内网
    所以一般只用到一块网卡
    另一块网卡可以单独用于binlog传输

    阅读内文

    High Performance MySQL 手稿

    4月 11th, 2008 | No Comments | Posted in 读书笔记 < by Johnny Woo >

    <2007-02-04>服务器优化的6.4节终于翻译完成.这一节对于服务器维护非常有用.

    6.4 技巧
    在所有基本理论和建议之后,是时候来处理现实世界中会遇见的问题了.当你发现你的服务器变慢,你能对它做什么?如何定位瓶颈的位置?哪些工具可用?用什么思路去处理?

    第一步是在操作系统的层面来判别瓶颈的类型.使用标准的操作系统工具,来推断哪种服务器资源负载最大.使用top, vmstat, 或者Windows任务管理器(Task Manager), 检查服务器的CPU利用率. 如果它接近100%,那就显然是CPU引起的.使用 top 来验证那个进程导致CPU负载激增.(如果你对于使用操作系统性能工没有太多的经验,考虑向有经验的系统管理员请教.)

    如果确实是MySQL占用了大量的CPU时间, 这里有几种技巧能够帮助你尝试减轻CPU 负载,阅读之后的 Section 6.4.2 章节. 如果占用CPU时间最大的进程不是 mysqld, 那很明显你需要解决的问题和 MySQL 无关. 也许那是一个失控的进程或者只是简单的某些程序应该被移到其他服务器上去运行. 不管怎样,这都不是MySQL问题,所以解决这类问题的方案超出了我们的讨论范围.

    如果CPU非常繁忙但是却没有显示任何进程或者进程组使用大量CPU时间,那查看一下系统使用和用户使用之间的差距.如果系统(内核)任务占用了以往未出现过的特别多的CPU时间,那可能是Mysql配置问题或者其他一些不相干的事情导致的. Section 6.4.4 中有例子显示了为什么MySQL可能引起内核负载异常增高.

    如果CPU相对较空那就是因为它经常在等待磁盘导致的. Section 6.4.1 有相应内容. 通过 vmstat 与/或 iostat 命令,如果显示超过一般数值很多的结果,那就是因为磁盘因素导致的.如果由于交换而导致CPU等待磁盘I/O,那么 Section 6.4.3 会有相对应的解决方案.

    6.4.1 解决I/O瓶颈
    磁盘 (I/O) 瓶颈是最常见的MYSQL性能问题. 它们经常由低效的查询引起,低效查询使得mysql必须读取太多你需要的行数据到本地. 通常这意味着你的查询没有使用索引, 或者它所使用的索引对实际请求没有产生任何作用.在讨论更多相关细节之前,确认你已经阅读过 Chapter 5 的有关内容.

    判断一个查询是否在使用索引是比较简单的. 如果你开启了慢速查询日志(slow query log) (在 Chapter 5 Section 5.3 中) 并且设置了长日志模式 log-long-format, MySQL 会自动记录任何没有使用索引的查询操作. 你所需做的就是: 使用 EXPLAIN 并且使用简单的性能测试来重写一个查询.

    在你找到和修正慢速查询之后, 下一步就是查找更多的细节问题. 在一些情况下,查询使用索引并且执行相对较快,这样MYSQL不会认为他们速度慢,但是这些查询从性能角度来看,实际上使用错误的索引. 如果选择另一个索引,则mysql可能减少所需的I/O请求.

    6.4.1.1 错误的索引
    查找使用错误索引的查询语句是件非常有挑战性的工作. 它需要对你数据的完整的理解以及查询时如何工作的.一个真实环境下的案例也许能够阐释这种问题可能有多细微.

    Jeremy 使用 mod_log_sql 这个Apache模块来记录他网站的所有点击,他们被记录到一个名为access_jeremy_zawodny_com 的MyISAM表. 这张表大概有 1.3 GB , 包含600万条记录, 表结构如下:

    +——————+———————-+——+—–+———+——-+

    | Field | Type | Null | Key | Default | Extra |

    +——————+———————-+——+—–+———+——-+

    | agent | varchar(255) | YES | MUL | NULL | |

    | bytes_sent | int(10) unsigned | YES | | NULL | |

    | child_pid | smallint(5) unsigned | YES | | NULL | |

    | cookie | varchar(255) | YES | | NULL | |

    | request_file | varchar(255) | YES | | NULL | |

    | referer | varchar(255) | YES | | NULL | |

    | remote_host | varchar(50) | YES | MUL | NULL | |

    | remote_logname | varchar(50) | YES | | NULL | |

    | remote_user | varchar(50) | YES | | NULL | |

    | request_duration | smallint(5) unsigned | YES | | NULL | |

    | request_line | varchar(255) | YES | | NULL | |

    | request_method | varchar(6) | YES | | NULL | |

    | request_protocol | varchar(10) | YES | | NULL | |

    | request_time | varchar(28) | YES | | NULL | |

    | request_uri | varchar(255) | YES | MUL | NULL | |

    | server_port | smallint(5) unsigned | YES | | NULL | |

    | ssl_cipher | varchar(25) | YES | | NULL | |

    | ssl_keysize | smallint(5) unsigned | YES | | NULL | |

    | ssl_maxkeysize | smallint(5) unsigned | YES | | NULL | |

    | status | smallint(5) unsigned | YES | | NULL | |

    | time_stamp | int(10) unsigned | YES | MUL | NULL | |

    | virtual_host | varchar(50) | YES | | NULL | |

    +——————+———————-+——+—–+———+——-+
    其中针对行: agent, time_stamp, request_uri, 和 remote_host 有独立的索引. 目的是想提高基于时间,用户代理(浏览器),申请地址(request_uri)或者客户端(remote_host) 进行统计的效率. 注意所有的索引.

    大多数的查询执行的非常迅速,但是一个特别的查询却有问题.它看起来比预期的执行时间更长.在重复执行并且查看 vmstat 的输出之后, 很明显大量的时间被用于等待磁盘. 这个查询尝试找出在特定时间范围内(一般是一天),哪些文档被传送给用户.每个客户端在请求过去时间内任意内容时这个查询都会执行一次. 查询语句如下:

    select request_uri from access_jeremy_zawodny_com

    where remote_host = ‘24.69.255.236′

    and time_stamp >= 1056782930

    and time_stamp <= 1056869330

    order by time_stamp asc
    通过 EXPLAIN 执行查询后给出的内容很有趣:

    mysql> explain select request_uri from access_jeremy_zawodny_com

    -> where remote_host = ‘24.69.255.236′

    -> and time_stamp >= 1056782930

    -> and time_stamp <= 1056869330

    -> order by time_stamp asc \G

    *************************** 1. row ***************************

    table: access_jeremy_zawodny_com

    type: ref

    possible_keys: time_stamp,remote_host

    key: remote_host

    key_len: 6

    ref: const

    rows: 4902

    Extra: Using where; Using filesort

    1 row in set (0.00 sec)
    MySQL 选择使用 remote_host 索引. 但是它并不总是这样选择.有时候MYSQL决定使用 time_stamp 索引. 例如下面:

    mysql> explain select request_uri from access_jeremy_zawodny_com

    -> where remote_host = ‘67.121.154.34′

    -> and time_stamp >= 1056782930

    -> and time_stamp <= 1056869330

    -> order by time_stamp asc \G

    *************************** 1. row ***************************

    table: access_jeremy_zawodny_com

    type: range

    possible_keys: time_stamp,remote_host

    key: time_stamp

    key_len: 5

    ref: NULL

    rows: 20631

    Extra: Using where

    1 row in set (0.01 sec)
    这两个请求的唯一不同点就在于我们查询的IP地址不同. 在每个情况下,MySQL的优化器估算它使用每个索引后所需读取的的行数.在第一个例子中,它判定当使用24.69.255.236 的 remote_host 作为索引时比制定24小时时间范围所需获取的行数更少.在第二个例子中恰恰相反, 它判定使用时间范围作为索引所需的行数更少.

    在尝试各种IP地址之后.很快查出MySQL做了错误的选择. 在使用 remote_host 作为索引所需行数更少的情况下.他选择了 ,但是实际上使用 time_stamp 更快.[4] 这怎么可能?

    [4] 使用 USE INDEX 在查询内指定条件, 你能够测试每种索引的性能.

    先假设所有的行数据在读取上的时间开销大致都是一致的.当然实际情况并不是总是这样的.想像一下在MyISAM表中的数据是如何存储的. Apache将所有的请求日志都记录在表中,并且运行了一年多.所有行都没有被删除过,所以在表以及磁盘中数据已经是按照时间戳timestamp来排序的了(架设只有很小的磁盘碎片).

    当你对于表中的数据了如指掌, 那情况可能会不一样. 我们假设给定IP的记录被分散在几百万行记录中, 那很明显,如果使用 remote_host 作为索引,很可能会引起更多的磁盘寻道. 既然磁盘寻道比从磁盘中读取连续数据更慢,那很自然当Mysql判定会作更少的操作(评估更少的行数)的时候,磁盘却需要做更多的寻道工作.这样,整个查询的速度就减慢了.

    在日志记录型的应用中,当你经常基于时间范围和其他索引字段查询的时候,这种问题常常会出现并且没有什么通用的解决方案. 但是如果你对你的数据有足够的洞察力并且能够在修改应用程序的话,这就会很有帮助了. 软件可以告诉mysql它需要用哪个索引. 例如,如果你的软件知道某个给定的IP地址最近只是偶尔登录, 那就能强制MySQL使用 time_stamp 区域作为索引:

    SELECT … USE_INDEX(time_stamp) …
    这虽然不是个理想的解决方案,但是如果使用适当的话,却是十分有效的.

    6.4.1.2 临时表
    另一个在上面没有显示出来的问题就是过多的使用基于磁盘的临时表. 在 EXPLAIN 的输出中, 你常常会看到 Using temporary. 这说明 MySQL 必须创建一个临时表来完成查询. 但是它却不会告诉你到底临时表是在内存中还是磁盘中. 临时表的大小由所需查询的表的大小以及MySQL配置文件中的 tmp_table_size 变量来确定.

    如果创建临时表所需的空间小于或者等于 tmp_table_size, MySQL 会将其保存在内存里.这样在读写时就不会有磁盘那样的开销了. 但是如果临时表的空间达到了 tmp_table_size 的大小, 那MySQL 就会在它的 tmpdir 目录下建立基于磁盘的临时表文件 (一般在UNIX系统下是 /tmp 目录.) tmp_table_size 的默认大小是 32 MB.

    为了获取mysql使用两种临时表的数量, 可以比较 Created_tmp_tables 和 Created_tmp_disk_tables 计数:

    mysql> SHOW STATUS LIKE ‘Created_tmp_%’;

    +————————-+——-+

    | Variable_name | Value |

    +————————-+——-+

    | Created_tmp_disk_tables | 18 |

    | Created_tmp_tables | 203 |

    | Created_tmp_files | 0 |

    +————————-+——-+
    如果你创建了大量基于磁盘的临时文件,你可以通过小心的增加 tmp_table_size 的大小来解决. 但是要注意如果将这个值设置的太大,那在太多进程尝试同时分配内存给临时表的时候可能引起过多的交换或者mysql 内存溢出(out of memory). 或者, 确定 tmpdir 是指向一个非常高速的磁盘,这样就不需要等待太多的I/O操作.

    作为最后的手段, 考虑使用tmpfs (或者ramdisk, mdmfs, 以及任何在你操作系统上基于内存的文件系统) 并且将 $TMPDIR 指向它,然后运行MySQL.

    6.4.1.3 缓存
    虽然的查询已经优化过并且使用了最有效率的索引,但是仍然有可能在某些时候遭遇到I/O瓶颈. 比如运行过多的查询,不论它们有多么高效,都会造成磁盘过载.如果是这样.那就是时候考虑缓存了.

    最简单的就是确认你已经在使用MySQL的查询缓存.从MySQL 4.0开始, 查询缓存在内存中保存了那些经常被执行的 SELECTs 查询的结果,这样MySQL就不用去处理任何磁盘I/O.在 Chapter 5 的 Section 5.4.4 有更详细的描述.

    更进一步, 你可以考虑应用层来做缓冲. 如果数据不是经常被修改, 那就可以在查询被执行一次之后保存至内存或者本地磁盘,以供下一次查询使用.

    6.4.1.4 分担负载
    如果针对以上情况你都按照所建议的做过修改,那看起来你需要更有效的分担I/O负载. 如同先前提到过的.安装拥有更快转速以及更少寻道时间的磁盘会有所帮助.使用RAID (特别是 RAID 0, RAID 5, 或者 RAID 10) 会将压力分摊到多个磁盘上,这样可能解决或者减轻瓶颈问题.

    另一种方法是,如果你拥有多个磁盘并且无法简单的配置RAID的话,那就尝试手动分摊磁盘I/O负载. 花一些时间用 iostat 或者 systat (视你的操作系统而定) 来发现I/O大部分发生在哪个位置. 如果你将所有的mysql数据库文件存放在一个单独的磁盘,你可以尝试着将一些存放到其他词胖上.如果大多数的操作集中在一小组表中,考虑将它们移到不同的磁盘中去.

    还有一种方法是将主要的随机I/O和主要的顺序存取分开. 存储的日志,例如二进制日志(binary logs),复制分发日志(replication relay logs)以及InnoDB事务日志(InnoDB transaction logs), 分派到和主数据文件不同位置的磁盘上. 这最后就是一个不停测试和修正的过程. 通过使用性能测试(benchmark), 注意数值的变化,还有尽量一次不要变更太多设置.

    复制模式总是最后的选择. 如果你的需求超过了单台服务器的负载能力, 它总是最少影响整个架构的解决方案. 关于复制模式的内容,在 Chapter 7 中有讲述.

    6.4.2 解决CPU瓶颈
    MySQL中的CPU瓶颈很难跟踪. 不像一些数据库软件, MySQL目前没有提供关于每个查询实际工作时间以及等待磁盘操作时间的统计.

    很幸运这不会是一个完全的猜谜游戏. 如果你看到一个查询在慢速查询日志 里面并且怀疑它引起CPU符合,简单的对它压力测试(benchmark)就可以了. 把一份MySQL的副本复制出来运行, 在一行上面运行几千次. 然后再另一个窗口上观察top, vmstat, 或者其他你喜欢的系统监控工具. 如果CPU很快达到了100%而这时候同时查询数相对较低,那么这个查询很可能就是引起CPU高负荷的元凶.

    如果你发现慢速查询有很多的话, 选择哪一个开始分析呢? 简单: 查看那些调用大量行数的 (几千,几万,或者更多行), 并且注意那些使用MySQL内建数据处理函数的. 一般来说以下一些比较可疑:

    格式化或者比较日期

    加密数据或计算哈希值

    处理复杂的比较,例如正则表达式

    你常会发现一些每小时在几百万个值上计算MD5哈希值的查询常常占用太多的CPU时间. 通过将逻辑运算转移到查询数据库的应用服务器, 你能够更有效的释放MySQL的CPU时间.

    如果你通过将逻辑运算转移到应用层也无法降低MySQL的运算量, 你就必须查看硬件问题了. 你有两种选择. 你可以简单的升级服务器的CPU或者增加更多的CPU. 或者,你也许会发现增加一台服务器更便宜些并且扩展性更好一些, 把数据复制给新服务器, 并且把流量分摊给它们.在这里利用一下摩尔定律,增加你硬件的性能.

    MyISAM表的高CPU负载并不总是坏事. 它可能意味着你正在做的查询操作已经被完全缓存到系统缓冲中去了. 这也许是,或者也许不是一件坏事. 这确实比从磁盘读取好, 但是MySQL每次都必须向操作系统所要一块数据的处理时间,原本可以被更好的分配到其他的查询进程上. 转移到 InnoDB 或者 BDB 表会让 MySQL 自己去缓冲表数据, 这样就不用去向操作系统所要数据记录了.

    6.4.3 解决内存瓶颈
    在MySQL上调整内存使用量是件很精巧细致的活儿. 和前面提到的一样, MySQL有一些全局内存缓冲还有一些额外的单进程缓冲. 主要的难度在于平衡使用大的全局缓冲所获取的性能以及服务器能够服务的同时在线用户数. 最少而言,你必须拥有足够可用内存来处理MySQL的全局缓冲加上单进程缓冲乘以最大同时连接数的综合.

    以下用算式来表示:

    最小内存需求 = 全局缓冲大小 + (单进程缓冲大小 * 最大连接数)
    单进程缓冲(thread_buffers) 包含以下内容:

    排序缓冲(sort_buffer)
    myisam表缓冲(myisam_sort_buffer)
    读缓冲(read_buffer)
    链接缓冲(join_buffer)
    随机读缓冲(read_rnd_buffer)
    全局缓冲(global_buffers) 包括:

    键值缓冲(key_buffer)
    innodb缓冲池(innodb_buffer_pool)
    innodb日志缓冲(innodb_log_buffer)
    innodb附加内存池(innodb_additional_mem_pool)
    网络缓冲(net_buffer)
    之所以说它是最小内存需求是因为理论上你还需要保留一些作为操作系统本身使用. 例如MyISAM表, “多余” 内存往往被用来缓冲MyISAM 数据文件(.MYD) 内的记录.

    在查询进程中所有线程除了其所申请的内存外, 线程本身也需要开销一点内存. thread_stack 参数控制这个值. 在绝大多数的平台上,其默认值为192 KB.[5]

    [5] 如果你在FreeBSD上使用linux线程库(LinuxThreads), 这个值将会被硬编码在linux进程库(LinuxThreads)中. 即使改变MySQL的 thread_stack 设置也不会生效. 你必须重新编译库赖改变这个堆栈大小.

    这方面的问题很常见,并且很有代表性. 想象你有一台拥有1GB内存的服务器,上面混合了MyISAM 以及 InnoDB 表. 为了满足性能, 在使用 mytop (Appendix B) 观察了key的效率之后,你配置了512MB的 key_buffer , 通过SHOW INNODB STATUS ( Appendix A)检查了缓冲池内存统计之后,配置了256-MB的 innodb_buffer_pool .这样还留下了 256 MB内存可以被操作系统用来缓冲数据文件 , 这些内存被每个线程缓冲用来分配必须的空间. MySQL服务器处理小量的同时用户数, 也许绝大多数时间在20-50个, 每个线程的缓冲大小保留为默认设置.

    所有这些都工作的很好,直到有一些新的应用也开始使用这台MySQL服务器. 这些新的应用程序需要大量的同时连接数. 服务器不再只处理大约20-50个同时连接,它现在处理大约300-400的同时连接. 现在, 在同一时刻这些连接所需要分配的每进程缓冲 (和 sort_buffer 一样) 都大大增加了.

    这会导致一系列的恶性循环. 如果大量的线程需要分分配额外内存, 很可能因为服务器在处理一个大型的查询负载. 这会引起MySQL申请大量的内存以至于操作系统开始使用交换分区, 这使得性能进一步降低, 每条查询需要更长才能完成. 由于查询运行的更慢了,更多线程会申请更多的内存,最终导致了恶性循环的发生.

    唯一的解决方案就是在系统内存和MySQL’s的内存需求之间做出一个平衡.这意味着需要做出一下改动.

    增加更多的内存

    减少max_connections

    减少每进程缓冲大小

    前提是. 监控服务器上的内存使用状况. 确保在满足最坏情况下的内存需求 (达到了 max_connections 上线并且每个进程都分配了额外内存)的条件下, 仍能有一点空闲内存.

    6.4.4 解决内核瓶颈
    虽然这并不常见, 你也许发现MySQL并没有使用大量的CPU时间,然而服务器却十分繁忙. 服务器只有只有相当少的CPU空闲. 更进一步观察之后, 你发现更多的CPU时间被开销在”system”进程而不是”user” 或者 “idle”. 这种情况可能预示着MySQL正在做一些不常见的操作使得内核进行创建或者回收线程.

    这种情况曾经在Yahoo!上发生过,当Yahoo!开放了一个新的web站点之后, 在2002年9月, 工程师开始创建九月11日的纪念性网站:remember.yahoo.com[6]. 在网站上,任何人可以通过选择一个图片以及增加一段个人留言来创建纪念物瓦片(”tile”) . 任何观看此网站的人都可以看到瓦片. 为了尽快的完成工作, 网站由一些标准的开源工具构成,包括FreeBSD, Apache, PHP, 以及 MySQL

    [6] 整个网站由一群Yahoo的工程师通过空闲时间,在两周内构想,设计并且创建发布出来.

    整个结构并不简单, 但是我们针对了主要目的简化了它. 一组前端web服务器通过一个硬件负载均衡器连接到一个从服务器. 通过使用从服务器的连接,web服务器获取用来显示瓦片的一些必要数据. 当一个浏览者创建瓦片时, web服务器必须连接到主服务器来插入一些必要记录. 主服务器是一台高端的服务器: 两颗1.2-GHz CPU, 2 GB 内存, 还有一个RAID5的SCSI阵列.

    最大情况下, 大约有25-30台web服务器需要连接master服务器. 每个服务器大约运行30-40 Apache 进程. 这意味着 master 需要支持超过 1,000 个同时连接数. 预想到这会消耗掉主服务器的所有资源后, 设计者选择了一个简单的处理方法. 很不幸, web应用(由PHP写成) 配置了持久连接. 所以,为了降低主服务器的连接数, wait_timeout 被设置成低于10秒.

    总的来说, 这个方案可以工作. 空闲连接在10秒钟之后被丢弃. 在主服务器上的连接数保持在200以下, 保留了很多空闲资源. 但是这里有个问题: 主服务器上的CPU非常的繁忙. 大多数情况下空闲都小于10%, 将近50%的CPU时间被花费在系统任务(而非用户任务)上.

    在大约一个小时的冥思苦想以及观察了系统日志和 SHOW STATUS 的输出之后, Jeremy终于突发灵感. Threads_created 的值太大,并且以令人恐怖的比率增加. 内核忙于创建和回收线程导致它占用了MySQL用来有效服务的那部分资源.

    在认识到这点之后, 解决方案就很简单了.将原来 thread_cache 默认的0增加到大约150,这个修改立竿见影.系统占用的CPU时间降低了大约10%, 这样就释放了一定的CPU供给MySQL使用. 这样的结果是, MySQL并不完全需要这部分资源, 所以服务器最终有了20%的空闲CPU时间以供调配

    阅读内文

    过誉的东西太多

    4月 11th, 2008 | No Comments | Posted in 读书笔记 < by Johnny Woo >

    刚入手市面上赞的很凶的
    号称是PHPCHINA的负责人翻译的
    但是实际拿到手之后
    感觉翻译的很一般
    与其说是一般
    不如说翻译水平很业余
    可能简先生自身PHP水平很好
    但是并非一名好的译者
    书中大量存在着从英文直译过来原句型
    包括常用的长句以及倒装句
    这种句子在中文内很少使用
    而作为一个优秀的译者
    不仅要保证原文的准确性
    更要保证对于本国的语言习惯的兼容
    如果不能让人一读就明白
    那和去读英文原文也没多大差异
    恐怕只是帮你减少了翻辞典的工作而已.

    一些意见如下

    例如P415:”另一种校验你的包的tar档案文是否像你想要的一样工作的方法是使用pear info和pear list命令”
    这种英文长句的语法,只是这样直译的话非常难以阅读.

    还有P424:”Dependency Types”翻译为”从属关系类型”
    而linux方面对于Dependency一词早有了比较统一的说法,
    那就是”依赖关系”

    还有P345将”Casting Objects”翻译为”对象的转换计算”
    而P346″Comparing Objects”翻译为”对象比较”
    从原文来说这两个是对仗的
    所以前者应该翻译为”对象转换”比较好

    阅读内文

    读书在于精而不在于多

    4月 11th, 2008 | No Comments | Posted in 读书笔记 < by Johnny Woo >

    粗略算算
    自己曾经在cnforyou买书买到3星
    又在china-pub到4星
    零零总总,已经一书橱都放不下了
    可是那么多书里面
    往往很多都是翻两页就丢在一边
    原因很多,作者写的不好,译者翻的不好,或者是又和某本书重复了
    其中重复最多的.莫过于linux类书
    基本上都是剪刀手的作品
    这边剪一些,那么抄一些,改个目录(我还见过目录都不改的)
    就又是一本新书.
    最后还是80-20定律起作用
    花费80%时间去阅读的,无非就是那20%的书
    好书,读多少遍都会发现自己有进步(当然差书也会有,你会发现自己越来越像一个合格的编辑)
    每个方面,其实也就只要1~2本书,你读精了.也就可以了.
    虽然在花费了万把块的书费之后才领悟会有些迟
    但是总好过还继续在垃圾书上花冤枉钱
    最后.一本PHP.一本CSS.一本JAVASCRIPT
    就可以结束不停买书的欲望了.
    当然.Windows Via C++是不能不买的.起码他的前身就是百读不厌的好书.

    阅读内文