2007年8月23日

加速你的網站的13個rule

從Yahoo的經驗得知,有13的rule可以加速網站的速度, 如下(後面的註解是我的見解)
  1. Make Fewer HTTP Requests 一個image或css 就算一個Request ,yahoo首頁只有45個
  2. Use a Content Delivery Network 使用akamai(CDN),一般的國際大站(yahoo,microsoft,cnn,apple...等)都有使用此服務
  3. Add an Expires Header 一些不常更新的檔案(如banner,css...等)增加expires header,以可以cache到local
  4. Gzip Components 使用網頁壓縮的技術,必須用Http 1.1,並且配合web server設定
  5. Put CSS at the Top
  6. Move Scripts to the Bottom
  7. Avoid CSS Expressions
  8. Make JavaScript and CSS External
  9. Reduce DNS Lookups 減少domain ,盡量用同一個domain。
  10. Minify JavaScript
  11. Avoid Redirects
  12. Remove Duplicate Scripts
  13. Configure ETags
Yahoo並提供一個好用的工具Yslow
可以檢查html code及是否符合以上的13 rules,
yahoo及google得最高分是A(100分)。

瀏覽網頁的Cache原理

1.緩衝的基本原理

緩衝服務器是在瀏覽器和網頁服務器之間的一組(台)機器,主要作用有兩個:一是減少網絡流量,二是減少網絡延遲。減少網絡流量主要是減少緩衝服務和原始的網頁服務器之間的流量。減少網絡延遲是減少了應答客戶端瀏覽器的延遲。為了實現這些功能,在HTTP/1.1和HTTP/1.0協議裡面有相關的命令來控制緩衝的行為。

緩衝服務器可以靠近原始服務器端也可以靠近瀏覽器端,靠近服務器端的代理服務器一般叫做反向代理。微睦網絡的代理服務器集群就屬於這種模式。
緩衝服務器利用兩個基本的概念來管理緩存的內容,一是新鮮度,二是有效性檢查。一個被緩存的內容(比如一張圖片)在有效期內,緩衝服務器可以直接把這個內容返回給瀏覽器(客戶端)。如果一個被緩存的內容過期了,那麼緩衝服務器就會認為這個內容是"陳舊"的,就會去原始服務器驗證這個內容是否已經更新。如果已經更新了,那麼就會把更新過的內容下載到緩衝服務器,然後重新開始計算該內容的新鮮時間。

一個內容的過期時間可以由服務器端通過http頭信息來明確指定,比如通過一個名為Expires的http頭來指定,如下面的例子:

http://www.google.com/intl/zh-CN_ALL/images/logo.gif
Expires 1641 weeks 2 days from now (Sun, 17 Jan 2038 19:14:07 GMT)

這是google中國的logo圖片,它的過期時間是2038年1月17日。
那如果這個圖片在中途被修改過了怎麼辦?沒關係,假如一個瀏覽器(比如firefox)對這個圖片進行一下刷新,瀏覽器就會發送一個帶條件的請求,而緩衝就會去真實服務器檢查這個圖片是否已經更新,如果圖片更新了,那麼緩衝服務器就會把新的內容下載過來替代舊的內容。

緩衝服務器驗證內容有效,是通過一些條件來判斷的,比如最後修改時間,或者是一個叫做 ETag 的 http 頭信息。具體的細節就不用去瞭解了。

2. 如何讓你的網頁內容具有更好緩衝友好性

為什麼要對緩衝友好?因為如果有更多的內容被緩衝服務器所緩衝,那麼你的網站本身的負載就降下來了,因為很多請求都由緩衝服務器代你應答了,假如瀏覽器請求下載你的網頁裡的小圖片,如果每個這樣的請求都要你的網頁服務器來處理,必然降低你的網頁服務器的處理能力。

那麼在哪裡設置,如何設置呢?這取決於你使用的網頁服務器,現在流行的就是windows下的IIS和Unix/Linux下的Apache,下面分別講解。

Apache

在Apache裡主要是通過選擇性的模塊來設置頭信息,頭信息是 Expires 和 Cache-Control 模塊是mod_expires 和 mod_headers
利用 httpd -l 命令確認你的apache已經包含了這些模塊;然後就可以在你的配置文件裡使用命令來控制你的內容的新鮮期了。可以對一個目錄設置,也可以對文件類型進行設置。
比如下面的命令將圖片文件的新鮮期設置成1年。更詳細的配置說明請參考apache的文檔。(http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_expires.html)

ExpiresActive on
ExpiresByType image/* "access plus 1 year"

利用這些命令,你可以給你的圖片文件和靜態的文件設置一個合理的新鮮時間。而不用擔心用戶不能看到你最近的更新,正如剛才所說,如果用戶點瀏覽上的刷新按鈕,最新的內容就能被訪問到。

IIS 服務器

在iis管理器中右鍵單擊某一網站或目錄,屬性,http 頭。設置相應的過期策略,對於不經常更新的頁面可設定比較高的值。如2小時,1天等。需要經常更新的數據設定比較小的值,10分鐘,20分鐘。這個時間越長,CDN效果越好,您的真實服務器負載也越小,但有些內容又必須及時刷新,站長可以慢慢調整這個時間,找到一個最佳平衡點.

3. 在CDN後面的真實服務器端如何得到訪問者ip地址

由於真實服務器和瀏覽器之間有CDN的緩衝服務器,真實服務器得到的訪問ip是緩衝服務器的ip地址。但是緩衝服務器通常會在HTTP 頭裡包含真實客戶端的ip地址,在Squid(一種流行的緩衝服務器)裡通常增加一個X-Forwarded-For頭信息來包含原始的客戶端ip.所以要在Apache服務器的日誌裡得到這個ip,可以增加一個%{X-Forwarded-For}i 到相應LogFormat裡面。
如果想在web程序裡得到這個值,可以通過所用語言的相關函數得到這個值,比如說在php裡面,可以利用getenv函數得到。

4.可緩存的動態頁面設計

什麼樣的頁面能夠比較好的被緩衝服務器緩存呢?如果返回內容的HTTP HEADER中有"Last-Modified"和"Expires"相關聲明,比如:

Last-Modified: Wed, 14 May 2003 13:06:17 GMT
Expires: Fri, 16 Jun 2003 13:06:17 GMT

前端緩存服務器在期間會將生成的頁面緩存在本地:硬盤或者內存中,直至上述頁面過期。
因此,一個可緩存的頁面:
頁面必須包含Last-Modified: 標記
一般純靜態頁面本身都會有Last-Modified信息,動態頁面需要通過函數強制加上,比如在PHP中:
// always modified now
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");

必須有Expires或Cache-Control: max-age標記設置頁面的過期時間:
對於靜態頁面,通過apache的mod_expires根據頁面的MIME類型設置緩存週期:比如圖片缺省是1個月,HTML頁面缺省是2天等。

<IfModule mod_expires.c>
ExpiresActive on
ExpiresByType image/gif "access plus 1 month"
ExpiresByType text/css "now plus 2 day"
ExpiresDefault "now plus 1 day"
</IfModule>

對於動態頁面,則可以直接通過寫入HTTP返回的頭信息,比如對於新聞首頁index.php可以是20分鐘,而對於具體的一條新聞頁面可能是1天後過期。比如:在php中加入了1個月後過期:
// Expires one month later
header("Expires: " .gmdate ("D, d M Y H:i:s", time() + 3600 * 24 * 30). " GMT");

如果服務器端有基於HTTP的認證,必須有Cache-Control: public標記,允許前台
ASP應用的緩存改造 首先在公用的包含文件中(比如include.asp)加入以下公用函數:

<%
' Set Expires Header in minutes
Function SetExpiresHeader(ByVal minutes)
' set Page Last-Modified Header:
' Converts date (19991022 11:08:38) to http form (Fri, 22 Oct 1999 12:08:38 GMT)
Response.AddHeader "Last-Modified", DateToHTTPDate(Now())
' The Page Expires in Minutes
Response.Expires = minutes
' Set cache control to externel applications
Response.CacheControl = "public"
End Function
' Converts date (19991022 11:08:38) to http form (Fri, 22 Oct 1999 12:08:38 GMT)
Function DateToHTTPDate(ByVal OleDATE)
Const GMTdiff = #08:00:00#
OleDATE = OleDATE - GMTdiff
DateToHTTPDate = engWeekDayName(OleDATE) & _
", " &amp;amp; Right("0" & Day(OleDATE),2) & " " & engMonthName(OleDATE) & _
" " & Year(OleDATE) & " " & Right("0" & Hour(OleDATE),2) & _
":" & Right("0" & Minute(OleDATE),2) & ":" & Right("0" & Second(OleDATE),2) & " GMT"
End Function
Function engWeekDayName(dt)
Dim Out
Select Case WeekDay(dt,1)
Case 1:Out="Sun"
Case 2:Out="Mon"
Case 3:Out="Tue"
Case 4:Out="Wed"
Case 5:Out="Thu"
Case 6:Out="Fri"
Case 7:Out="Sat"
End Select
engWeekDayName = Out
End Function
Function engMonthName(dt)
Dim Out
Select Case Month(dt)
Case 1:Out="Jan"
Case 2:Out="Feb"
Case 3:Out="Mar"
Case 4:Out="Apr"
Case 5:Out="May"
Case 6:Out="Jun"
Case 7:Out="Jul"
Case 8:Out="Aug"
Case 9:Out="Sep"
Case 10:Out="Oct"
Case 11:Out="Nov"
Case 12:Out="Dec"
End Select
engMonthName = Out
End Function
%>

然後在具體的頁面中,比如index.asp和news.asp的「最上面」加入以下代碼:
HTTP Header
<!--#include file="../include.asp"-->
<%
'頁面將被設置20分鐘後過期
SetExpiresHeader(20)
%>

5. 如何檢驗緩衝服務器如何對待你的網頁內容

打開這個網址:(http://utils.vmmatrix.net/)
然後根據提示,輸入你想檢查的內容的URL(地址),就可以看到這個內容的Http頭信息,和緩衝如何處理這個URL.大多數情況有兩種,一是明確指定了新鮮時間,所以緩衝服務器在新鮮時間內認為這個內容是新鮮的。二是沒有明確指定新鮮時間,緩衝服務器就會根據這個內容的最後修改時間距離現在的時間作為一個時間段,然後把這個時間段的一個百分比來作為新鮮時間,這個百分比是在緩衝服務器哪裡設置的。
如果一個內容既沒有明確指定新鮮時間,也沒有最後修改時間,那麼緩衝服務器就會把這個內容當做是」陳舊「的內容,每次都會去原始服務器驗證。

FreeBSD ports 的使用

在我們安裝 FreeBSD 系統之時, FreeBSD 會在 /usr/ports/ 這個目錄下將各個軟體
的 PKG_NAME 目錄分門別類放在不同的子目錄下,
當我們要安裝某套軟體時, cd 到 /usr/ports/ 那個軟體的目錄下, 打入

make - 這個命令會讓 bsd 去抓 source code, patch, compile
make install - 這個命令會進行軟體的安裝

事實上在 make install 所進行的軟體安裝會採用和 packages 的 pkg_add 一
樣的方式, 在 /var/db/pkg/ 下建立一個 PKG_NAME 的目錄, 裡頭一樣會有 3 個檔案

+COMMENT 軟體的簡略說明 (only 1 line)
+DESC 軟體的簡略說明
+CONTENT 這套軟體含有哪些檔案, 分別裝到哪邊

pkg_delete PKG_NAME 移除

2006年12月9日

使用linux 的wget 指令測試proxy是否有cache到頁面

1.proxy沒cache到頁面

--20:49:37-- http://210.65.0.1/report/2006vote/chinatimes/MayorVote.xml?r=19-45
=> `MayorVote.xml?r=19-45'
Connecting to 210.65.0.1:80... connected.
HTTP request sent, awaiting response...
1 HTTP/1.0 200 OK
2 Content-Length: 19613
3 Content-Type: text/xml
4 Last-Modified: Sat, 09 Dec 2006 12:44:04 GMT
5 Accept-Ranges: bytes
6 ETag: W/"bc758bb58f1bc71:3d9"
7 Server: Microsoft-IIS/6.0
8 X-Powered-By: ASP.NET
9 Date: Sat, 09 Dec 2006 12:49:34 GMT
10 X-Cache: MISS from ac200 (沒有cache 到頁面 )
11 Connection: keep-alive
100%[====================================>] 19,613 --.--K/s
20:49:39 (36.68 MB/s) - `MayorVote.xml?r=19-45.2' saved [19613/19613]
2.proxy有cache到頁面

--20:56:50-- http://210.65.0.1/report/2006vote/chinatimes/MayorVote.xml
=> `MayorVote.xml.1'
Connecting to 210.65.0.1:80... connected.
HTTP request sent, awaiting response...
1 HTTP/1.0 200 OK
2 Content-Length: 19613
3 Content-Type: text/xml
4 Last-Modified: Sat, 09 Dec 2006 12:44:04 GMT
5 Accept-Ranges: bytes
6 ETag: W/"bc758bb58f1bc71:3d9"
7 Server: Microsoft-IIS/6.0
8 X-Powered-By: ASP.NET
9 Date: Sat, 09 Dec 2006 12:56:42 GMT
10 Age: 13
11 X-Cache: HIT from ac200 (有cache,ac200是proxy server的hostname)
12 Connection: keep-alive
100%[====================================>] 19,613 --.--K/s
20:56:51 (34.13 MB/s) - `MayorVote.xml.1' saved [19613/19613]
cache控制參數(有可能是proxy server加進去的http header):
  Cache-Control: max-age=60  (cache 60秒,如果超過 60會回304,要求確認是否更新過)
   X-Cache: HIT from ac200  (在ac200 有cache到)
 

2006年11月23日

/etc/rc.d/init.d/xxxxx 的編輯說明,& check process 是否已經在running

#!/bin/bash
#
# /etc/rc.d/init.d/<servicename>
#
# <description of the *service*>
# <any general comments about this init script>


#
# <tags -- see below for tag definitions. *Every line* from the top
# of the file to the end of the tags section must begin with a #
# character. After the tags section, there should be a blank line.
# This keeps normal comments in the rest of the file from being
# mistaken for tags, should they happen to fit the pattern.>

# Source function library.
. /etc/rc.d/init.d/functions

case "$1" in
start)
echo -n "Starting <servicename> services: "
<start daemons, perhaps with the daemon function>
touch /var/lock/subsys/<servicename>
;;
stop)
echo -n "Shutting down <servicename> services: "
<stop daemons, perhaps with the killproc function>
rm -f /var/lock/subsys/<servicename>
;;
status)
<report the status of the daemons in free-form format,
perhaps with the status function>
;;
restart)
<restart the daemons, normally with $0 stop; $0 start>
;;
reload)
<cause the service configuration to be reread, either with
kill -HUP or by restarting the daemons, possibly with
$0 stop; $0 start>
;;
probe)
<optional. If it exists, then it should determine whether
or not the service needs to be restarted or reloaded (or
whatever) in order to activate any changes in the configuration
scripts. It should print out a list of commands to give to
$0; see the description under the probe tag below.>
;;
*)
echo "Usage: <servicename> {start|stop|status|reload|restart[|probe]"
exit 1
;;
esac


Functions in /etc/rc.d/init.d/functions


daemon [+/-nicelevel] program [arguments] [&]


Starts a daemon, if it is not already running.

Does other useful things like keeping the daemon from dumping core if it terminates unexpectedly.


killproc program [signal]


Sends a signal to the program; by default it sends a SIGTERM,

and if the process doesn't die, it sends a SIGKILL a few seconds later.

It also tries to remove the pidfile, if it finds one.


pidofproc program


Tries to find the pid of a program; checking likely pidfiles,

using the pidof program, or even using ps. Used mainly from within other functions in this file, but also available to scripts.


status program


Prints status information. Assumes that the program name is the same as the servicename.


Tags.


# chkconfig: <startlevellist> <startpriority> <endpriority>


Required. <startlevellist> is a list of levels in which the service should be started by default.

<startpriority> and <endpriority> are priority numbers.

For example: # chkconfig: 2345 20 80 Read 'man chkconfig' for more information.

Unless there is a VERY GOOD, EXPLICIT reason to the contrary,

the <endpriority> should be equal to 100 - <startpriority>


# description: <multi-line description of service>


Required. Several lines of description, continued with '\' characters.

The initial comment and following whitespace on the following lines is ignored.


# description[ln]: <multi-line description of service in the language \ # ln, whatever that is>


Optional. Should be the description translated into the specified language.


# processname:


Optional, multiple entries allowed. For each process name started by the script,

there should be a processname entry. For example, the samba service starts two daemons:
# processname: smdb
# processname: nmdb


# config:


Optional, multiple entries allowed. For each static config file used by the daemon, use a single entry. For example:
# config: /etc/httpd/conf/httpd.conf
# config: /etc/httpd/conf/srm.conf

Optionally, if the server will automatically reload the config file if it is changed,

you can append the word "autoreload" to the line:
# config: /etc/foobar.conf autoreload


# pidfile:


Optional, multiple entries allowed.

Use just like the config entry, except that it points at pidfiles.

It is assumed that the pidfiles are only updated at process creation time, and not later.

The first line of this file should be the ASCII representation of the PID;

a terminating newline is optional. Any lines other than the first line are not examined.

# probe: true

# Check for postmaster already running...
pid=`pidof postmaster`
if [ $pid ]
then
echo "Postmaster already running."
else
run xxx <<<<< else 要run 的指令
fi <<<<等於endif的意思

為網路卡設置固定的速度

1) 檢查網路交換器 (或路由器),並將其設定為網路卡欲使用的速度 (它有可能被設成 100)。
2) 修改檔案: /etc/sysconfig/network-scripts/ifcfg-ethX
並且加入下面這行:
ETHTOOL_OPTS="speed 1000 duplex full"
3) 重新啟動網路卡程序,或者重新開機。