• Feeds

  • Archive for the ‘Linux’ Category


    Google的系统工程师(SA)如何工作

    本文根据系统管理领域知名博客 Thomas A. LimoncelliWhat is system administration like at Google 整理而成,添加了部分笔者观点。

    Google的系统工程师(System Administrator)如何工作

    由于Google的服务已经集群化,系统工程师并不大量接触硬件比如做安装服务器等事情。另外大部分工作也已经自动化了,比如架设LDAP, 负载均衡等。对照而言,国内目前大部分互联网公司SA仍然要做大量重复的底层工作,比如拿一个业务的数据库过大需要拆分为例,从系统管理员的角度,需要做以下事情

    1. 同技术人员沟通目前业务特点,制定拆分方案并评估程序风险
    2. 搭建测试环境,技术人员测试程序兼容性
    3. 制定实施方案,保证业务的不停机平稳过渡
    4. 深夜上线
    5. 观察1-2天运行情况

    我们需要思考上面工作是否是系统管理员以及技术人员有价值的工作。像Cassandra这样解决了分布式存储自动化扩展的问题是业内一种发展方向,尽管Cassandra的稳定性还需要改进)。

    Google的系统工程师怎么做?
    他们会通常1周值班,响应各种问题,比如完成上述场景中的扩容业务。然后有大约5周左右脱离一线工作来自由思考将这1周内碰到的工作进行自动化改进,将那些会反复碰到的问题通过脚本及监控程序完成,或者进一步反馈给技术人员改进应用程序来实现自动化。1:5只是个大约比例,时段可以灵活安排。比如也可以按天来安排,1天值班/7天改进。当改进完成之后,下次遇到相同的场景,自动化程序会完成大部分工作。如果在其他公司,SA通常忙碌在一线机械重复上述工作,但是在Google, 给系统工程师预留了相当多的时间让大家思考改进。

    这就是Google的System Administrator自称SRE(Site Reliability Engineers)的原因。SRE会不断在优化所负责的系统,一些人关注运维层面,另外一些可能关注自动化工具。所有的SA都需要具备一定程序或脚本开发能力。

    因此,当遇到Google的数据规模,自动化不是是否需要,而是如何更好实现的问题。

    在Google其他一些令人兴奋的工作还包括

    • 与开发技术人员是协同的关系。
    • 只需关心技术,在技术领域也有职业生涯上升通道,不必转向技术管理岗位或其他。
    • 同事都非常聪明,通常会觉得自己是最逊的那一个。
    • 很多挑战,保守的估计领先行业2-10年,在这里工作就象给了你一个魔法水晶球,通过你的工作可以预见这个行业的未来。

    受Google方式的启发,以下想到的一些可以研究的自动化方向

    1. 程序部署

    C/C++/Java/PHP/Python/Ruby/C# 等语言如何不停机自动发布
    自动发布如何简洁的解决模块依赖性,比如1天需要同时更新10个有相互依赖的模块,并且不能停止服务
    Web容器虚拟化,同一Web容器上可以部署多个业务,业务之间互相隔离,互不影响。
    将新开发的服务程序运维自动化。一般的服务程序从数量上来说,10是一个分水岭,10台以下的服务通过人工重复操作方式来管理也问题不大,但是10台以上就需要自动化管理的方法。很多优秀的开源程序(比如Tokyo Cabinet, Redis等)在单机上表现优秀,但是大规模部署不能。大公司中很多技术人员经常提到很多开源软件不适合他们就有这方面原因。

    2. 资源部署

    MySQL
    分布式文件存储
    Cache,拿cache自动化管理举例
    端口资源管理,不同业务使用不同端口,同一应用内不同的数据使用不同的端口,相关原因可以参看以前cache相关博文。
    容量管理,不同的数据需要不同的容量
    动态扩容,应用业务规模增长,比如从10G扩容到100G
    Proxy功能,比如虚拟化端口映射,程序访问的是固定虚拟端口,这样不需要重启服务也可以随时扩充,应用也不需要一致性hash, proxy帮你做了。

    3. 系统部署

    OS
    反向代理与负载均衡
    本地分区容量,批量管理
    程序发布与停止,比如一个程序一个点击部署到100台服务器
    虚拟化,比物理服务器更容易部署,资源利用率更高,部署更可控

    大部分国内互联网公司基础技术还是比较原始的,这跟行业过分强调“好产品是运营出来的”也有关系,基础研发通常不受重视,长此以往,只能在门槛低的领域打拼,与Google的技术差异就不止10年了。
    paper tape
    (图:大型机GEORGE的纸带编程年代)

    利用Gearman来实现远程监控与管理

    Gearman是一个分发任务的程序框架,可以用在各种场合,与Hadoop相比,Gearman更偏向于任务分发功能。它的任务分布非常简单,简单得可以只需要用脚本即可完成。Gearman最初用于LiveJournal的图片resize功能,由于图片resize需要消耗大量计算资源,因此需要调度到后端多台服务器执行,完成任务之后返回前端再呈现到界面。

    gearman

    Gearman分布式任务实现原理上只用到2个字段,function name和data。function name即任务名称,由client传给job server, job server根据function name选择合适的worker节点来执行。data通常为执行任务所需的自定义的内容,比如简单的做法可以把需要执行的脚本当成data即可(当然要注意其中的安全防范)。如果有多个worker可以处理同一个function name, 则job server会自动分配一个。当用于远程监控场景时,我们可以让每个worker注册成不同的业务名称,以达到方便控制每台worker节点的目的。

    下面介绍Gearman实践中可用于多服务器管理的一些小功能,如果你的服务器有多台,重复执行命令过于繁琐,那可以借助下面一些脚本来完成一些有趣的功能。比如要实时看到所有服务器上的 netstat -nat | grep 80, 按下面步骤搭好环境之后,只需要几行脚本代码即可实现。

    1. 安装gearman
    最早的gearman是perl版的,由于国内开发人员对perl熟悉的不多,所以推荐安装C版本
    http://gearman.org/index.php?id=download
    解开后 ./configure; make; make install 即可

    2. 启动 job server
    cd sbin; ./gearmand -d

    3. 到 worker 节点启动 worker

    先按步骤1在worker机上安装 gearman, 然后创建一个执行worker的python脚本。

    #!/usr/bin/env python
    import os
    
    def main():
        cmd = raw_input()
        print os.popen(cmd).read()
    
    if __name__ == "__main__":
        main()

    cd bin; ./gearman -w -h <job_server_ip> -f server1 — ./monitor.py

    4. 通过远程 web 管理
    JSP示例:

    <%@ page language="java" import="java.util.*,java.util.concurrent.*,
    org.gearman.client.*,org.gearman.common.*"%><%!
            private static String host = "192.168.1.1";
            private static int port = 4730;
            public String testGearman(String func, String data) {
                    byte[] input = data.getBytes();
                    String uniqueId = null;
    
                    GearmanJobServerConnection conn =
                        new GearmanNIOJobServerConnection(host, port);
                    GearmanClient client = new GearmanClientImpl();
                    client.addJobServer(conn);
                    GearmanJob job = GearmanJobImpl.createJob(func, input, uniqueId);
                    Future<GearmanJobResult> f = client.submit(job);
                    GearmanJobResult jr = null;
                    String result = null;
                    try {
                            jr = f.get(3, TimeUnit.SECONDS);
                            result = new String(jr.getResults());
                    } catch (Exception e) {
                            result = e.getMessage();
                    }
    
                    client.shutdown();
                    return result;
            }
    %><%
    out.println(testGearman("test", "netstat -nat | grep 80");
    %>

    PHP示例:

    # Create our client object.
    $client= new GearmanClient();
    
    # Add default server (localhost).
    $client->addServer();
    
    echo "Sending job\n";
    
    # Send reverse job
    $result = $client->do("server1", "netstat -nat | grep 80");
    if ($result)
      echo "Success: $result\n";

    谈Linux内核定时器

    看了3个周末的Linux内核,包括前两周总结的进程与线程锁与同步。当时研究这个的原因是因为某个程序CPU context switch过高。不过到现在相关的背景知识也了解了,问题也早已经解决了,所以暂时也没有进一步的兴趣驱动去研究内核了,这里是终结篇。:)

    在应用程序运行的时候,特别是抢占式的操作系统里面,内核怎么样取得控制权?这依赖硬件支持的系统定时器来实现。内核中有非常多的功能由定时器触发。系统定时器以固定的频率触发,这个频率称为tick rate(HZ),每个触发周期的时间叫做tick, 它等于1/HZ秒。触发后系统会转到内核相应的handler去处理。

    在系统定时器中断时候内核需要做以下事情

    • 更新uptime, time of day, resource及处理器使用状态
    • 检查多处理器是否负载均衡
    • 检查当前进程是否timeslice是否用完,如果用完则重新分配下阶段计划(reschedule)
    • 运行应用程序自定义的定时器(dynamic timers)

    了解了tick rate之后才能比较好理解为什么sleep(), timer等API声称都不是提供精确的时间,因为cpu一个任务timeslice没运行完,系统是不会马上切换到这些dynamic timer的进程的。

    Linux 2.5以上将tick从100改成1000,相当于系统时钟从10ms变成每1ms要中断一次,当时也引起较大的争议。

    改成1000的优点有:

    • 系统时钟精度更高更准确。
    • 系统调用如poll(), select() 等依赖系统时钟的调用性能得到很大改善。
    • 内核实时运行指标如资源占用,uptime更准确。
    • 抢占式机制更精确。

    缺点:
    我们知道定时器频繁被触发必将会增加开销,降低throughput。这是很多人反对改成1000的理由。原理上它在CPU的时间中断上将会增加10倍的开销。但由于现代CPU硬件速度的变快。大家也逐渐认可了新的调整不会给整体性能带来大的影响。如果在意这一点的可以重新编译内核, 将<asm/param.h>中HZ的值由1000降低。目前可以接受的值有100,500和1000。

    Linux 2.6.21 又增加了一种叫dyntick的技术,dyntick就是在系统空闲的时候,彻底停止时间中断, 避免cpu空转,它会带来节能方面的好处。详情可参看Clockevents and dyntick。这是个新的技术,一般的书上都没来得及写进去。

    比较感兴趣的后续课题是virtualization系统中的timer实现。

    12