作為一個軟件開發者,你一定會對網絡應用如何工作有一個完整的層次化的認知,同樣這里也包括這些應用所用到的技術:像瀏覽器,HTTP,HTML,網絡服務器,需求處理等等。
本文將更深入的研究當你輸入一個網址的時候,后臺到底發生了一件件什么樣的事~
導航的第一步是通過訪問的域名找出其IP地址。DNS查找過程如下:
DNS遞歸查找如下圖所示:
DNS有一點令人擔憂,這就是像wikipedia.org 或者 facebook.com這樣的整個域名看上去只是對應一個單獨的IP地址。還好,有幾種方法可以消除這個瓶頸:
大多數DNS服務器使用Anycast來獲得高效低延遲的DNS查找。
因為像Facebook主頁這樣的動態頁面,打開后在瀏覽器緩存中很快甚至馬上就會過期,毫無疑問他們不能從中讀取。
所以,瀏覽器將把一下請求發送到Facebook所在的服務器:
GET http://facebook.com/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, [...]
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...]
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: facebook.com
Cookie: datr=1265876274-[...]; locale=en_US; lsd=WW[...]; c_user=2101[...]
GET 這個請求定義了要讀取的URL: “http://facebook.com/”。 瀏覽器自身定義 (User-Agent 頭), 和它希望接受什么類型的響應 (Accept and Accept-Encoding 頭). Connection頭要求服務器為了后邊的請求不要關閉TCP連接。
請求中也包含瀏覽器存儲的該域名的cookies。可能你已經知道,在不同頁面請求當中,cookies是與跟蹤一個網站狀態相匹配的鍵值。這樣cookies會存儲登錄用戶名,服務器分配的密碼和一些用戶設置等。Cookies會以文本文檔形式存儲在客戶機里,每次請求時發送給服務器。
用來看原始HTTP請求及其相應的工具很多。作者比較喜歡使用fiddler,當然也有像FireBug這樣其他的工具。這些軟件在網站優化時會幫上很大忙。
圖中所示為Facebook服務器發回給瀏覽器的響應:
HTTP/1.1 301 Moved Permanently
Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,
pre-check=0
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Location: http://www.facebook.com/
P3P: CP="DSP LAW"
Pragma: no-cache
Set-Cookie: made_write_conn=deleted; expires=Thu, 12-Feb-2009 05:09:50 GMT;
path=/; domain=.facebook.com; httponly
Content-Type: text/html; charset=utf-8
X-Cnection: close
Date: Fri, 12 Feb 2010 05:09:51 GMT
Content-Length: 0
服務器給瀏覽器響應一個301永久重定向響應,這樣瀏覽器就會訪問“http://www.facebook.com/” 而非“http://facebook.com/”。
為什么服務器一定要重定向而不是直接發會用戶想看的網頁內容呢?這個問題有好多有意思的答案。
其中一個原因跟搜索引擎排名有關。你看,如果一個頁面有兩個地址,就像http://www.litfresh.com/ 和http://litfresh.com/,搜索引擎會認為它們是兩個網站,結果造成每一個的搜索鏈接都減少從而降低排名。而搜索引擎知道301永久重定向是什么意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網站排名下。
還有一個是用不同的地址會造成緩存友好性變差。當一個頁面有好幾個名字時,它可能會在緩存里出現好幾次。
現在,瀏覽器知道了“http://www.facebook.com/”才是要訪問的正確地址,所以它會發送另一個獲取請求:
GET http://www.facebook.com/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, [...]
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...]
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Cookie: lsd=XW[...]; c_user=21[...]; x-referer=[...]
Host: www.facebook.com
頭信息以之前請求中的意義相同。
服務器接收到獲取請求,然后處理并返回一個響應。
這表面上看起來是一個順向的任務,但其實這中間發生了很多有意思的東西- 就像作者博客這樣簡單的網站,何況像facebook那樣訪問量大的網站呢!
舉個最簡單的例子,需求處理可以以映射網站地址結構的文件層次存儲。像http://example.com/folder1/page1.aspx這個地址會映射/httpdocs/folder1/page1.aspx這個文件。web服務器軟件可以設置成為地址人工的對應請求處理,這樣page1.aspx的發布地址就可以是http://example.com/folder1/page1。
所有動態網站都面臨一個有意思的難點 - 如何存儲數據。小網站一半都會有一個SQL數據庫來存儲數據,存儲大量數據和/或訪問量大的網站不得不找一些辦法把數據庫分配到多臺機器上。解決方案有:sharding (基于主鍵值將數據表分散到多個數據庫中),復制,利用弱語義一致性的簡化數據庫。
委托工作給批處理是一個廉價保持數據更新的技術。舉例來講,Fackbook得及時更新新聞feed,但數據支持下的“你可能認識的人”功能只需要每晚更新(作者猜測是這樣的,改功能如何完善不得而知)。批處理作業更新會導致一些不太重要的數據陳舊,但能使數據更新工作更快更簡潔。
圖中為服務器生成并返回的響應:
HTTP/1.1 200 OK
Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,
pre-check=0
Expires: Sat, 01 Jan 2000 00:00:00 GMT
P3P: CP="DSP LAW"
Pragma: no-cache
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
X-Cnection: close
Transfer-Encoding: chunked
Date: Fri, 12 Feb 2010 09:05:55 GMT
2b3????????T?n?@????[...]
整個響應大小為35kB,其中大部分在整理后以blob類型傳輸。
內容編碼頭告訴瀏覽器整個響應體用gzip算法進行壓縮。解壓blob塊后,你可以看到如下期望的HTML:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
lang="en" id="facebook" class=" no_js">
...
關于壓縮,頭信息說明了是否緩存這個頁面,如果緩存的話如何去做,有什么cookies要去設置(前面這個響應里沒有這點)和隱私信息等等。
請注意報頭中把Content-type設置為“text/html”。報頭讓瀏覽器將該響應內容以HTML形式呈現,而不是以文件形式下載它。瀏覽器會根據報頭信息決定如何解釋該響應,不過同時也會考慮像URL擴展內容等其他因素。
在瀏覽器沒有完整接受全部HTML文檔時,它就已經開始顯示這個頁面了:
在瀏覽器顯示HTML時,它會注意到需要獲取其他地址內容的標簽。這時,瀏覽器會發送一個獲取請求來重新獲得這些文件。
下面是幾個我們訪問facebook.com時需要重獲取的幾個URL:
這些地址都要經歷一個和HTML讀取類似的過程。所以瀏覽器會在DNS中查找這些域名,發送請求,重定向等等...
但不像動態頁面那樣,靜態文件會允許瀏覽器對其進行緩存。有的文件可能會不需要與服務器通訊,而從緩存中直接讀取。服務器的響應中包含了靜態文件保存的期限信息,所以瀏覽器知道要把它們緩存多長時間。還有,每個響應都可能包含像版本號一樣工作的ETag頭(被請求變量的實體值),如果瀏覽器觀察到文件的版本ETag信息已經存在,就馬上停止這個文件的傳輸。
試著猜猜看“fbcdn.net”在地址中代表什么?聰明的答案是"Facebook內容分發網絡"。Facebook利用內容分發網絡(CDN)分發像圖片,CSS表和JavaScript文件這些靜態文件。所以,這些文件會在全球很多CDN的數據中心中留下備份。
靜態內容往往代表站點的帶寬大小,也能通過CDN輕松的復制。通常網站會使用第三方的CDN。例如,Facebook的靜態文件由最大的CDN提供商Akamai來托管。
舉例來講,當你試著ping static.ak.fbcdn.net 的時候,可能會從某個akamai.net服務器上獲得響應。有意思的是,當你同樣再ping一次的時候,響應的服務器可能就不一樣,這說明幕后的負載平衡開始起作用了。
在Web 2.0偉大精神的指引下,頁面顯示完成后客戶端仍與服務器端保持著聯系。
以Facebook聊天功能為例,它會持續與服務器保持聯系來及時更新你那些亮亮灰灰的好友狀態。為了更新這些頭像亮著的好友狀態,在瀏覽器中執行的JavaScript代碼會給服務器發送異步請求。這個異步請求發送給特定的地址,它是一個按照程式構造的獲取或發送請求。還是在Facebook這個例子中,客戶端發送給http://www.facebook.com/ajax/chat/buddy_list.php一個發布請求來獲取你好友里哪個在線的狀態信息。
提起這個模式,就必須要講講"AJAX"-- “異步JavaScript 和 XML”,雖然服務器為什么用XML格式來進行響應也沒有個一清二白的原因。再舉個例子吧,對于異步請求,Facebook會返回一些JavaScript的代碼片段。
除了其他,fiddler這個工具能夠讓你看到瀏覽器發送的異步請求。事實上,你不僅可以被動的做為這些請求的看客,還能主動出擊修改和重新發送它們。AJAX請求這么容易被蒙,可著實讓那些計分的在線游戲開發者們郁悶的了。(當然,可別那樣騙人家~)
Facebook聊天功能提供了關于AJAX一個有意思的問題案例:把數據從服務器端推送到客戶端。因為HTTP是一個請求-響應協議,所以聊天服務器不能把新消息發給客戶。取而代之的是客戶端不得不隔幾秒就輪詢下服務器端看自己有沒有新消息。
這些情況發生時長輪詢是個減輕服務器負載挺有趣的技術。如果當被輪詢時服務器沒有新消息,它就不理這個客戶端。而當尚未超時的情況下收到了該客戶的新消息,服務器就會找到未完成的請求,把新消息做為響應返回給客戶端。
希望看了本文,你能明白不同的網絡模塊是如何協同工作的。
修改了一些錯字,之前不仔細,請大家見諒~
當圖片很多的時候,減少圖片大小是提高下載速度最直接的方法。
1. 使用PNG8代替GIF(非動畫圖片),因為PNG8在效果一樣的情況,圖片大小比GIF要小。
2. 用fireworks處理PNG圖片,在我們產品中很多PNG圖片是美工直接用photoshop導出的,
后來讓美工用fireworks處理PNG(大概的方式是選擇保存為PNG8,刪除背景色)。
處理后100K的圖片大小基本減少了3/4,但圖片質量也會有少許降低,要看自己是否能接受。
3. 使用Smush.it(http://www.smushit.com/ysmush.it/)壓縮圖片,Smush.it是YUI團隊做1個在線壓縮圖片的網站,
該網站在不影響原圖片的質量下去掉圖片中一些元數據,所以可以放心使用該網站進行壓縮,
但這個壓縮比例也是比較有限的。
1. CSS Sprites合并圖片以減少請求數來提高性能大家都知道。但不要把圖片合并太多,太多太大了,
就會因為這1個圖片影響這個頁面的顯示了。
2. 有時候我們需要把1個大圖片拆分成多個小圖片,比如產品首頁圖片比較少,就1個很大的banner圖片,
因瀏覽器都可以并發下載圖片,所以如果不拆分,只使用1個大圖片的話,下載速度反而會比較慢
IE6不能顯示透明的PNG圖片,是很多開發人員特別頭疼的事,分別介紹下幾種方式的優缺點。
1.使用AlphaImageLoader,IE6支持filter,使用下面的CSS代碼,可以讓IE6支持PNG
#some-element {
background: url(image.png);
_background: none;
_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png', sizingMethod='crop');
}
優點:使用簡單
缺點:性能損耗很大,AlphaImageLoader會花費很多資源去處理透明圖片,使用AlphaImageLoader,IE使用內存會迅速上升。
而且AlphaImageLoader所有處理都在同1個線程中同步進行,所以當AlphaImageLoader多的時候,會阻塞UI的渲染。
使用_filter,IE7也可以識別,其實IE7是可以識別PNG透明圖片的,如果在IE7下使用上面代碼,IE7不會直接使用圖片,而是使用AlphaImageLoader。
注:個人建議盡量避免使用AlphaImageLoader
2. JS處理
使用DD_belatedPNG(http://www.dillerdesign.com/experiment/DD_belatedPNG/),可以很簡單的對界面上所有的透明圖片進行同一處理。
優點:使用簡單(比AlphaImageLoader還簡單)
缺點:當頁面上需要處理的圖片比較多的時候,速度也比較慢,而且不能動態改變圖片。
3. VML
IE6支持VML,VML可以使用透明圖片,代碼如下:
修改html代碼頭部
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v>
<head>
<style type="text/css">
v\:*{behavior:url(#default#VML);}
</style>
</head>
<body>
<v:image src="image.png" />
</body>
</html>優點:性能好,速度快
缺點:使用復雜,而且不支持firefox等瀏覽器,需要判斷不同的瀏覽器輸出不同的HTML代碼。
因每個瀏覽器對同1個域名同時只能發送固定的請求,比如IE6好像是2個,所以可以對圖片資源開通多個域名進行請求,
比如img1.abc.com,img2.abc.com。但域名不要開啟太多,因為解析域名和打開新的連接都需要消耗時間,域名多了,說不定反而會更慢。一般2-4個域名就夠了。
IE6背景圖片緩存是個麻煩事,很多人知道使用下面的JS來讓IE6緩存背景圖片<!--[if IE 6]>
try{
document.execCommand("BackgroundImageCache", false, true);
}catch(e){}
但是這樣做的效果并不是非常好,當出現鼠標移動改變背景圖片的時候,IE6老是會發送1個圖片請求(盡管該背景圖片已經下載),
雖然返回結果是304,但還是要花費不少時間。在這種情況下,可以使用下面1個變通的方式來處理,
在頁面上直接使用1個DIV元素來加載該圖片,這樣加載圖片就能真正被緩存,鼠標移動也不會發送請求了。
使用下面代碼可以在頁面加載完畢后預加載下1個頁面的圖片,當進入下1個頁面就不用再下載圖片了。
window.onload=function(){
var img = new Image();
img.src = "images/image.png";
img = null;
};
Description
Managing multiple webbugs is no fun. The following is an attempt to unify disparate webbugs into a single, extensible, solution.
How it works
The unified webbug snippet below replaces the need to include a separate webbug for each of analytics services you are using. Simply add the snippet below to your pages, configure your specific account settings, and you're done. This webbug will make (asynchronous) requests to each of the analytics services, without affecting page performance and simplifying the maintanance of your analytics webbug sprawl.
<script type="text/javascript"> function trackerSetup() { var tracker = new Tracker(); tracker.addTracker(new QuantcastTracker("account")); tracker.addTracker(new GoogleAnalyticsTracker("name", "UA-XXXXXXX-X")); tracker.addTracker(new ChartbeatTracker(1234, "domain")); var s_vars = { s_pageName : "pageName", s_server : "www.test.com", s_channel : "IndexPage" } tracker.addTracker(new OmnitureTracker(s_vars, "s_code.js")); tracker.trackPageview(); } (function loadJs(url, callback) { setTimeout(function() { var script = document.createElement("script") script.type = "text/javascript"; if (script.readyState){ script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; callback(); } }; } else { script.onload = function(){ callback(); }; } script.src = url; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); },0); })("http://labs.webmetrics.com/webbug/tracker.js", trackerSetup); </script>
DISPLAY=:0.0 |
export DISPLAY=:0.0 |
Xlib: connection to ":0.0" refused by server Xlib: No protocol specified Error: Can't open display: :0.0 |
xhost + |
X11Forwarding no |
ForwardX11 yes |
DISPLAY=localhost:10.0 |
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 4827/1 |
exec /usr/bin/X11/X -dpi 100 -nolisten tcp |
exec /usr/bin/X11/X -dpi 100 |
ServerArgsLocal=-nolisten tcp |
ServerArgsLocal= |
DisallowTCP=false |
用命令“echo $SHELL”可以查看當前shell是什么。
/bin/bash ------------------- Bash Shell
/bin/csh ------------------- C Shell
/bin/ksh ------------------- Kron Shell
/sbin/sh ------------------- Bourne Shell
7. 安裝后
別以為看到了install successfully 就說明沒事了,還沒到長舒一口氣的時候,還有post installation。
如果你確實已經將shell 改成 C shell 了,后面碰到的問題會少很多。假設當前已經是csh 了。
7.1
cd ~
vi .cshrc
添加一行記錄
source /var/loadrunner/env.csh #/var/loadrunner 為loadrunner安裝目錄
logoff and login。 或者開啟另一個terminal.
7.2
cd /var/loadrunner/bin
./verify_generator # 這個utility將會檢查當前的安裝及配置情況
極有可能會fail掉。常見錯誤是:
a. 找不到.rhosts file.
b. 找不到libstdc++.so.5
c. DISPLAY 沒有設
對應的:
a. 簡單說來,.rhosts 是一個安全驗證文件。遠程機器(將來測試時的controller)將remote當前Linux作為它的generator。將controllor hostname添加在.rhosts里面,這樣remote時Linux就會將其做為安全訪問而不需要password。此文件應在每個user的home下面,代表controllor以某個user 訪問Linux server. 我們暫時可以先創建一個空的文件,等確定controllor之后再添加信息進去。
cd ~
touch .rhosts
b. 這個原因是因為Loadrunner 9.0 generator 使用的是 libstdc++.so.5 但當前的版本很有可能已經是so.6了。可以這樣查看:
cd /usr.lib
ll *libstdc++*so*
如果真的沒有,那可以到 http://rpm.pbone.net里找到后下載安裝。在UI下面安裝非常方便,雙擊就可以了。
c. 這個就是DISPLAY 這個環境變量沒有設的問題。
setenv DISPLAY localhost:0.0
echo $DISPLAY
當然,這里寫的都是針對csh來說的。如果用的是K Shell 或者是 Bourne Shell, 則要麻煩一些。必須手動的將三個變量添加到.profile里面去。我沒有試過這兩種shell, 倒是試過bash,redhat 的默認shell。 但是怎么都沒法通過verify_generator的驗證,總說M_LROOT 有問題,至今不明是不是本來就不支持bash.
**********************
M_LROOT={replace w/ LR Linux installation path} ; export M_LROOT
LD_LIBRARY_PATH=${M_LROOT}/bin; export LD_LIBRARY_PATH
PATH=${M_LROOT}/bin:${PATH}; export PATH
**********************
寫到這里還沒有完。還記得之前提過的.rhosts嗎,那個實際上是給rsh (remote shell) 用的。要真正確保這個安裝在Linux上的generator 能被安裝在Windows上的controllor所調用就必須確保windows 能夠 rsh Linux 。可惜我到現在還沒能試通,不知是不是因為我的windows 和 Linux不屬于同一個domain的緣故。還得繼續研究,等有結果了之后再發上來。
http://bbs.dospy.com/viewthread.php?tid=3061548
http://www.hiapk.com/bbs/viewthread.php?action=printable&tid=10159
http://www.hiapk.com/bbs/thread-9751-1-1.html
http://www.hiapk.com/bbs/viewthread.php?tid=2834&page=1&extra=#pid11606
http://www.hiapk.com/bbs/thread-9751-1-1.html
http://www.gphone-cn.com/bbs/viewthread.php?tid=10889&extra=pageD1&page=1