一是分步式的节点,起到负载均衡、协调跨运营商跨地域访问的作用;二是节点上的缓存,这无疑可以减少源服务器的负载,节省带宽。


  正是由于CDN如上两个特点,也给网站的管理人员带来了不少麻烦:



1. 静态文件版本管理


CDN的缓存是用户一般不可控的,且静态资源(如:js、css、图片等)的缓存时间非常长,虽然CDN提供商一般都会提供刷新缓存的方法,这种方法在少量更新时可以接受,但如果更新文件过多(如一次升级),则会非常麻烦。可以使用“ 静态资源(JS、CSS、图片)版本控制”说的,对静态资源进行管理,这样每次升级时即省事又省心。


2. 启用HTTP压缩


启用压缩对HTTP1.0、代理的支持,在IIS下配置如下:

cscript adsutil.vbs set W3SVC/Filters/Compression/Parameters/HcNoCompressionForHttp10 false
 
cscript adsutil.vbs set W3SVC/Filters/Compression/Parameters/HcNoCompressionForProxies false


做完上述配置后,通知CDN提供商,开通HTTP压缩功能即可。


在响应里增加一个HTTP Header: Vary: Accept-Encoding



3. 获取客户端真实IP


由于访客不是直接访问源服务器,跟源服务打交道的都是CDN的节点机器,所以在源服务器抓取到的IP都是节点IP。这对按ip来统计的浏览量、网站统计等模块的影响会比较大。一般来说,CDN节点会以某种方式将源客户端的IP传递给源服务器,就拿我用的网宿CDN来说,它是将源IP添加到了一个叫“Cdn-Src-Ip”的Http Header里,以C#语言为例,获得客户端真实IP的方式如下:


网宿的cdn是


String srcIp = Request.Headers["Cdn-Src-Ip"];     

 

  if(srcIp == null)    {      

 

      srcIp = Request.UserHostAddress; 

 

  } 

 
 
 
 

  //蓝汛的是  

 

  HttpContext.Current.Request.ServerVariables["HTTP_CLIENT_IP"];


以上内容,根据不同的CDN提供商可能会有所不同,操作前最好咨询自己的CDN提供商




public static string GetUserIp
        {
            get
            {
                string userIP = "未获取用户IP";
 
                try
                {
                    if (HttpContext.Current == null
                || HttpContext.Current.Request == null
                || HttpContext.Current.Request.ServerVariables == null)
                        return "";
 
                    string CustomerIP = "";
 
                    //CDN加速后取到的IP
                    CustomerIP = HttpContext.Current.Request.Headers["Cdn-Src-Ip"];
                    if (!string.IsNullOrEmpty(CustomerIP))
                    {
                        return CustomerIP;
                    }
 
                    CustomerIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
 
                    if (!String.IsNullOrEmpty(CustomerIP))
                        return CustomerIP;
 
                    if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
                    {
                        CustomerIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                        if (CustomerIP == null)
                            CustomerIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                    }
                    else
                    {
                        CustomerIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
 
                    }
 
                    if (string.Compare(CustomerIP, "unknown", true) == 0)
                        return HttpContext.Current.Request.UserHostAddress;
                    return CustomerIP;
                }
                catch { }
 
                return userIP;
            }




关键就在HTTP_X_FORWARDED_FOR

使用不同种类代理服务器,上面的信息会有所不同:
一、没有使用代理服务器的情况:
REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示
二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP
这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。
三、使用普通匿名代理服务器的情况:Anonymous Proxies
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP
隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。
四、使用欺骗性代理服务器的情况:Distorting Proxies
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP
告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。
五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示