V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hepochen
V2EX  ›  程序员

国外的服务器,我们这样优化访问速度

  •  
  •   hepochen · 2012-12-03 11:14:05 +08:00 · 12879 次点击
    这是一个创建于 4385 天前的主题,其中的信息可能已经有所发展或是发生改变。
    介绍我们的海外速度优化的实践,虽然都是琐碎的事情,但或许对大家会有所帮助。

    另外,不要妄想海外线路的速度比肩国内。本文所述,也别对海外的速度太过于悲观。

    格式好一点的原文: http://ued.com.cn/post/tech/keep-the-speed-of-visiting-when-outside#content

    ## 背景介绍

    我们为什么把服务器放在国外?虽然这样做的人不少,原因也是明了的很。作为背景介绍,还是陈述几个理由。

    - 我们对国外的市场,有欲望;没有打算放弃,服务器在外面,速度能够保证。

    - 我们说的服务器,这里指的是类似Amazon的AWS或者Linode之类的;而这类服务,国内也有。在技术层面,让人没有安全感。

    - 涉及到域名、网站的备案,这会严重影响产品本身的用户体验,甚至会扼杀。

    我们选择的服务提供商是Amazon,然后,挑战就来了……


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




    ## 选择线路

    AWS上最便宜的区块自然是美国的本土,随便测试下ping值,一般是300+,500+也是正常的。距离中国大陆速度最快的是东京的节点,ping值在100左右,当然会有不算低的丢包率…… 据说Linode的日本节点要比Amazon的快一些。

    而且,我们暂时没有考虑(在国内)使用第三方的CDN服务(除了图片资源这种速度硬伤会有所影响外,其它优化后,速度会很快);但我们又测试了下美国本土到日本的速度,并不是很理想,这方面会考虑CDN,用AWS自己的FrontCloud,而且能减少费用。呃,这个自然在国内用不了,对应的DNS被墙了。

    对了,AWS日本节点上的费用,普遍比美国本土高出50%左右……

    继续,我们要做到秒开!

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



    ## Gzip & Cache

    ### 在S3上的处理

    我们把Amazon的S3存储服务,直接用为静态资源WEB服务器。这个很简单,你只要在S3上创建的bucket名字用你计划启用的域名,比如statics.yourdomain.com;然后在DNS中CNAME到<code>s3-ap-northeast-1.amazonaws.com</code>即可。

    但在上传到S3的时候,我们要对文件(css、js、html)进行GZIP压缩,并做Cache-Control。Cache-Control是文件被访问时候,可以同浏览器进行通讯,告诉浏览器自行缓存,就不会每次都去请求一次。

    *css、js还可以在gzip之前通过yui compressor进行进一步压缩; 另外,css中使用的所有图片,压缩为一张图,用background-postion来做。*


    代码片段如下:

    def gzip_content(content):
    zbuf = StringIO.StringIO()
    zfile = GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
    zfile.write(content)
    zfile.close()
    return zbuf.getvalue()

    #- - - - 下面的是上传的代码片段 - - - - -

    with open(file,'rb') as f:
    content = f.read()
    key = bucket.new_key(path)
    content_type = guess_type(path)[0]
    headers = {
    'Cache-Control':'max-age=315360000’,#这里是设置缓存的
    }
    policy = 'public-read'
    key.set_metadata('Content-Type', content_type)
    # gzip压缩
    if content_type in GZIP_CONTENT_TYPES:
    content = gzip_content(content)
    headers.update({'Content-Encoding': 'gzip'})
    key.set_contents_from_string(content, headers=headers, policy=policy)


    ### 在APP(网站)上的处理

    你也可以用上面代码片段中的思路,直接进行GZIP压缩;但还是建议在Nginx中进行处理,因为会更高效一点。

    注意输出response的时候,有些非高度动态的页面,打上Cache-Control,就算30秒也好…… 这会一定程度减少你网站的请求数。

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


    ## 数据库索引

    不管如何,你必须要一定程度上了解数据库索引优化的知识。比如常用explain去看看,数据查询的效率,比如前匹配和后匹配的效率区别,比如索引端中要避免使用NULL值, .etc

    如果你用django,则可以用debug-toolbar这类的第三方效率工具库。

    如果使用NoSQL之类的,要建立必要的索引;比如mongodb中,如果使用正则查询的时候,只要什么时候索引是有效的,何种情况会直接产生接近死循环的loop。

    如果有些数据任务因为花销比较大,如有必要驻后台跑的,就不要放在Web服务中嵌入!

    尽自己所学,让所有WEB过来的请求,都是读、读、读;快速的读、快速的读、快速的读!避开所有可能的,程序内部的阻塞!

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

    其实经过上面几步之后,东京的节点上服务器上页面访问,到完全渲染成功,估计1秒多一些。

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

    ## 但还不够!

    我们要做DNS的优化。

    你应该知道怎么去查看一个页面在渲染过程中各个时间的耗费,比如使用Chrome浏览器自带的开发者工具;或者使用 http://17ce.com http://alibench.com 这些在线的工具。

    这里需要补充的是,我们使用的DNS服务是Amazon的Route53,我们发现,国内各个网络节点,平均的解析时间在400-500毫秒之间,这个速度成了瓶颈了。虽然DNS的记录本身会缓存,其实帮助并不大,别人仍会有这种感觉的,“访问有时滞”……

    但我们不会因此就弃用Route53的,因为,它在海外的解析速度是有保证的;另外,它的费用真的是物美价廉……

    而国内最好的DNS托管服务,无疑就是 http://dnspod.cn


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




    ## DNS优化

    在优化DNS之前,先介绍下dig,通过命令行运行<code>dig google.com +trace</code>, 这个会成为你自己本机、服务器上评价国内外DNS速度的重要参考依据。

    我们的想法就是把DNSPOD和Route53合用…… 但如果只是简单地在域名设置的地方,把它们分别提供的DNS合在一起,是没有用的;当然,这第一步是你应该做的。

    在这部分开始之前,我们有必要了解下DNS,首先,它是松散的、分布式的、端口在53。

    DNS中有一项设定,叫SOA,简单的可以理解就是指定哪个解析服务是最优先的,格式如下, 中间是空格隔开。
    > [authority-domain] [domain-of-zone-admin]
    [zone-serial-number] [refresh-time] [retry-time]
    [expire-time] [minimum TTL]

    DNSPOD中没有SOA的设置,因为它已经默认设定好了,无法更改,所以,在Route53中,需要与它保持一致。

    > f1g1ns1.dnspod.net. freednsadmin.dnspod.com. 1354421554 3600 180 1209600 180

    并且在Route53中的NS记录上,把DNSPOD的服务地址补上。

    等这些记录都生效之后,可以测一下DNS是否正常了。可以到这里测试, http://www.intodns.com/

    另外非常重要的一点是,你在Route53和DNSPOD上的记录应该是完全一致的,包括TTL;另外,一般情况下,No Glue,这个可以不用考虑去优化。它的意思,比如 test.com 跑去 ns-88.awsdns-31.co.uk 解析,只会返回NS记录,而不是直接IP地址;因为 .com 和 .co.uk 的顶级解析,归属并不是一致的。


    f1g1ns1.dnspod.net. ['119.167.195.11', '122.225.217.192', '180.153.10.150', '183.60.52.217'] [TTL=172800]
    f1g1ns2.dnspod.net. ['112.90.143.29', '122.225.217.191', '180.153.10.151', '180.153.162.150'] [TTL=172800]
    ns-2.awsdns-61.com. ['205.251.93.236'] [TTL=172800]
    ns-6.awsdns-36.net. ['25.251.15.28'] [TTL=172800]
    **ns-94.awsdns-08.org. ['205.251.136.10'] (NO GLUE) [TTL=172800] **
    **ns-88.awsdns-31.co.uk. ['205.251.18.52'] (NO GLUE) [TTL=172800]**


    - - - - - - - - - -

    如此一来,一个页面从发起请求到最终渲染,国内各省市节点的时间平均值基本上控制在700ms左右;如果服务器在国内,其中的连接时间,也会被大幅降低。

    **但如论如何,让服务在墙外,会有所受损,也会有所得,各自平衡;只是漂泊在外,别对速度抱太大的恐惧就好……**
    21 条回复    1970-01-01 08:00:00 +08:00
    citydog
        1
    citydog  
       2012-12-03 11:25:05 +08:00
    远水永远解不了近渴... 除非上东亚的CDN,否则国外服务器.... ...
    hepochen
        2
    hepochen  
    OP
       2012-12-03 11:26:44 +08:00   ❤️ 1
    @citydog 日本是东亚呀……
    sivacohan
        3
    sivacohan  
       2012-12-03 11:26:55 +08:00   ❤️ 1
    相当干货了。被逼出来的解决方法。
    sdjl
        4
    sdjl  
       2012-12-03 13:03:32 +08:00
    嗯 dns部分有借鉴作用
    sdjl
        5
    sdjl  
       2012-12-03 13:08:10 +08:00   ❤️ 1
    顺便问一下, dnspod的TTL自己设置得比较低就可以更快么? TTL有什么用?
    AJ
        6
    AJ  
       2012-12-03 15:44:18 +08:00
    关注这个讨论
    sNullp
        7
    sNullp  
       2012-12-03 16:00:54 +08:00
    @sdjl 就是这个用途。TTL是DNS在非权威服务器中的过期时间。
    HowardMei
        8
    HowardMei  
       2012-12-03 16:15:44 +08:00
    好东东,DNS还可以这样优化的,长见识了。
    @sdjl 对于固定不变的绑定,TTL越大缓存越久,查询所需时间越少,在r53里面直接就是少花钱,但是考虑到万一服务器挂了,你要刷新绑定应急,TTL也不能放太大(有很多大站放一年的-_-),我一般弄个3小时。
    Livid
        9
    Livid  
    MOD
       2012-12-03 16:19:34 +08:00
    非常同意这一条:

    写尽量放入 queue,让用户访问时只需要读。
    citydog
        10
    citydog  
       2012-12-03 17:35:42 +08:00
    @hepochen 算我没说,其实我不会告诉你,我没看正文... :)
    rhwood
        11
    rhwood  
       2012-12-03 23:42:26 +08:00
    lz说的基本都是web前端的优化,试试再加varnish缓存吧
    loveminds
        12
    loveminds  
       2012-12-04 02:29:26 +08:00
    海外相对喜欢新加坡,可惜带宽太小了
    vking
        13
    vking  
       2012-12-04 09:21:29 +08:00
    接ls,海外还有韩国。
    cysnake4713
        14
    cysnake4713  
       2012-12-04 09:44:00 +08:00
    文章拉轰,纯经验贴,含金量高啊~
    remaerd
        15
    remaerd  
       2012-12-04 10:58:07 +08:00
    目测含金量很高,然后顺藤摸瓜发现博客很有意思,RSS 之了。我正在用 AppFog,还没能力碰 EC2,Linode 还有文中提到的服务,只好慢慢来了。
    moyaya
        16
    moyaya  
       2012-12-04 12:40:48 +08:00   ❤️ 1
    不错,如果早点看到,我们说不定会继续用amazon啦
    imcj
        17
    imcj  
       2012-12-04 20:41:39 +08:00
    tshwangq
        18
    tshwangq  
       2012-12-04 20:50:16 +08:00
    yahoo不是有那么一个工具么。
    运行一下,前端的优化建议就都有了
    imtoby
        19
    imtoby  
       2012-12-04 23:49:21 +08:00
    历史终究会把“伟大的墙”钉死在耻辱柱上 !!! 简直就是无耻!
    wingoo
        20
    wingoo  
       2012-12-05 00:29:43 +08:00
    国内备案,有独立服务器其实也很方便 , 可以只备出口服务器, 数据库,计算可以不备, 当然如果针对国外市场,放国外最好
    loveminds
        21
    loveminds  
       2013-06-05 14:46:08 +08:00 via iPhone
    @hepochen 亚马逊上新加坡吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5631 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 03:35 · PVG 11:35 · LAX 19:35 · JFK 22:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.