varnish 的windows 版本下載地址:
http://sourceforge.net/projects/cygvarnish/files/windows-zip-bundle/
啟動:varnish:
C:\varnish\bin>varnishd -a :80 -T :3500 -f c:/varnish/etc/default.vcl -s file,c:/varnish/var/cache,1000M
-a:80表示,讓varnish監聽在80端口。
-T是為varnish指定一個管理端口;
-f指定所要使用的配置文件;
后面的參數只是讓varnish使用文件緩存,大小為1000M,當然,應該根據實際情況指定大小;
啟動varnish后,如果我們請求http://地址:端口/,就可以等到200OK狀態碼,那表示varnish已經在正確滴接受請求。
黃海的配置文件:
backend default {
.host = "192.168.88.177";
.port = "80";
}
#定義可以清空緩存的IP段
acl purge {
"localhost";
"192.168.88.0"/24;
}
sub vcl_recv {
#開啟壓縮模式,圖片格式取消壓縮
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|jpeg|flv)" ) {
remove req.http.Accept-Encoding;
remove req.http.Cookie;
} else if (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} else if (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
remove req.http.Accept-Encoding;
}
}
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
#配置varnish批量刷新緩存
if (req.request == "BAN") {
if (!client.ip ~purge){
error 405 "Not allowed";
}
ban("req.http.host == " +req.http.host+" && req.url ~ "+req.url);
error 200 "Ban added";
}
#把除了以下這些類型請求以外的訪問請求全部直接管道發送到后端的服務器
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
#只有GET與HEAD方法才會使用Lookup,使用緩存。
if (req.request != "GET" && req.request != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
#如果請求的是jsp頁面直接轉發到后端服務器
if (req.url ~ "\.(jsp|action)($|\?)") {
return (pass);
}
return (lookup);
}
sub vcl_pipe {
return (pipe);
}
sub vcl_pass {
return (pass);
}
#使用url+host hash算法查找數據
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
return (hash);
}
# 如果請求為purge 將清除緩存
sub vcl_hit {
#強制刷新后,忽略緩存,直接到后台請求
if(req.http.Cache-Control~"no-cache"||req.http.Cache-Control~"max-age=0"||req.http.Pragma~"no-cache")
{
set obj.ttl=0s;
return (restart);
}
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged";
}
return (deliver);
}
sub vcl_miss {
return (fetch);
}
sub vcl_fetch {
if (beresp.ttl <= 0s ||
beresp.http.Set-Cookie ||
beresp.http.Vary == "*") {
/*
* Mark as "Hit-For-Pass" for the next 2 minutes
*/
set beresp.ttl = 120 s;
return (hit_for_pass);
}
if (beresp.http.Pragma ~"no-cache" ||
beresp.http.Cache-Control ~"no-cache" ||
beresp.http.Cache-Control ~"private") {
return (deliver);
}
#當url中包含servlet時,不進行緩存
if (req.url ~ "^/servlet/")
{
return (hit_for_pass);
}
#當url中包含services時,不進行緩存
if (req.url ~ "^/services/")
{
return (hit_for_pass);
}
if (req.request == "GET" &&
req.url ~ "\.(png|xsl|xml|pdf|ppt|doc|docx|chm|rar|zip|bmp|jpeg|swf|ico|mp3|mp4|rmvb|ogg|mov|avi|wmv|swf|txt|png|gif|jpg|css|js|html|htm)$")
{
unset beresp.http.set-cookie;
set beresp.ttl = 1h;
}
#設置圖片的緩存TTL為一小時
return (deliver);
}
sub vcl_deliver {
#下面是添加一個Header標識,以判斷緩存是否命中。
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT from dsideal.com";
} else {
set resp.http.X-Cache = "MISS from dsideal.com";
}
return (deliver);
}
sub vcl_error {
set obj.http.Content-Type = "text/html; charset=utf-8";
set obj.http.Retry-After = "5";
synthetic {"
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>"} + obj.status + " " + obj.response + {"</title>
</head>
<body>
<h1>Error "} + obj.status + " " + obj.response + {"</h1>
<p>"} + obj.response + {"</p>
<h3>Guru Meditation:</h3>
<p>XID: "} + req.xid + {"</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
"};
return (deliver);
}
sub vcl_init {
return (ok);
}
sub vcl_fini {
return (ok);
}
#
********************************************************************************************************
網上3.0版本的配置說明文字太少了,這篇文章是3.0版本,不錯,有時間做個實驗。
http://wdj01.blog.51cto.com/1059856/660571
ASP.NET性能優化之反向代理緩存
2011-10-17 08:50 by 陸敏技, 2598 visits, 收藏, 編輯到目前為止,我們討論了把緩存存放在ASP.NET的輸出緩存中(內存和硬盤),以及瀏覽器緩存中,而大型站點的另一種常用做法是將緩存部署在反向代理服務器上,這類緩存我們通常稱之為反向代理緩存,比如Squid和Varnish。這兩款軟件通常都部署在非WINDOWS平台上,對於Windows平台上的Asp.net來說,其實一樣能使用,我們完全可以把反向代理軟件部署在LINUX上,然后代理會路由到后台的WINDOWS WEB(IIS)服務器。總之,非WINDOWS的世界很精彩。
當然,無論是squid還是varnish都有Windows的擴展版本。本文為了簡便起見,基於varnish的Windows版本來描述的。
varnish的官方站點:https://www.varnish-cache.org/,
varnish的Windows版本:http://www.cygwin.com/,如果要編譯過的直接可用的版本,在這里:http://www.software112.com/products/cygwin-varnish-cache.html。
1:將varnish配置為IIS的代理
首先需要為varnish准備配置文件,比如,可以為default.vcl,內容如下:
backend
default
{
.host =
"192.168.0.77"
;
.port =
"80"
;
}
sub vcl_fetch
{
remove beresp.http.Set-Cookie;
}
sub vcl_recv
{
remove req.http.Cookie;
}
|
在我們要示范的這個實例中,這3個配置都不能少,如下,
backend default:指定我們的IIS站點的地址和端口;
sub vcl_fetch:這是一個varnish函數,它varnish從后端服務器,也就是IIS中獲得數據后被調用;
sub vcl_recv:varnish函數,表示客戶端請求杠杠到達反向代理服務器時被調用;
由於varnish默認在碰到http頭中含有Cookie相關標識時直接忽略緩存,所以我們需要上面的兩個函數針對Cookie做特殊處理。當然,目前這兩個函數只是簡單而野蠻的刪除標識,實際的應用中我們可能需要根據實際情況為它們加上一些判斷條件。
2:啟動varnish
下面的命令為我啟動varnish:
C:\varnish\bin>varnishd -a :8011 -T :8088 -f c:/varnish/etc/default.vcl -s file,c:/varnish/var/cache,100M
-a:8011表示,讓varnish監聽在8011端口。由於我測試環境下varnish和iis是在同一台機器上,所以IIS已經占用了80,我這里只有使用其它端口。
-T是為varnish指定一個管理端口;
-f指定所要使用的配置文件;
后面的參數只是讓varnish使用文件緩存,大小為100M,當然,應該根據實際情況指定大小;
啟動varnish后,如果我們請求http://地址:端口/,就可以等到200OK狀態碼,那表示varnish已經在正確滴接受請求。
3:一個實例
創建asp.net頁面,內容如下:
protected
void
Page_Load(
object
sender, EventArgs e)
{
this
.Response.AddHeader(
"Cache-Control"
,
"max-age=60"
);
this
.Response.AddHeader(
"Last-Modified"
, DateTime.Now.ToString(
"U"
, DateTimeFormatInfo.InvariantInfo));
DateTime IfModifiedSince;
if
(DateTime.TryParse(
this
.Request.Headers.Get(
"If-Modified-Since"
),
out
IfModifiedSince))
{
if
((DateTime.Now - IfModifiedSince.AddHours(8)).Seconds < 60)
{
Response.Status =
"304 Not Modified"
;
Response.StatusCode = 304;
return
;
}
}
string
conn =
"Data Source=192.168.0.77;Initial Catalog=luminjidb;User Id=sa;Password=sa;"
;
using
(DataSet ds = Common.SqlHelper.ExecuteDataset(conn, CommandType.Text,
"select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"
))
{
var result = ds.Tables[0].Rows[0][
"name"
].ToString();
Response.Write(result);
}
}
|
對該頁面進行壓力測試,100個用戶,1000個請求,得到的結果如下:
如果沒有緩存,則結果如下:
可以看到吞吐率有非常大的提升。
4:監控varnish
可以使用varnishstat命令,對varnish進行監控,在上面的壓力測試中,如果我們使用監控,得到的結果如下:
在本例中,我們可以看到共請求了1000次,其中999次命中緩存,那是因為第一次顯然肯定是要從IIS中拿輸出滴。
5:管理varnish
可以通過多種途徑來進行varnish的管理,包括更改配置、停止服務、啟動服務、清理緩存等。可以通過varnishadm命令進行管理,如果你是在遠程的話,可以使用telnet來進行管理:
telnet 192.168.0.77 8088
其中8088就是我們剛在啟動varnish的時候指定的管理端口。連接上之后,stop停止服務、start啟動服務,可以敲入help查看所有命令。下面的命令,清除所有緩存:
purge.url *$
6:謹慎引入varnish后帶來的緩存變化
引入varnish后,可以發現使用強制刷新(ctrl+R5)后,動態行為發生了改變,即客戶端瀏覽器會去VARNISH上請求數據,但是此時的緩存中已經存在靜態的緩存內容,varnish會首先根據請求的HTTP頭去和這個緩存內容判斷得出需要是否更新,即由於緩存內容的存在,請求不會去IIS上進行緩存協商。這個時候,緩存中的靜態內容會直接返回給客戶端瀏覽器,這樣一來的話,我們在Page_Load中的代碼就根本不會執行,因為它是在IIS中的。
要避免這種情況的發生,我們必須更改VARNISH配置文件,讓VARNISH碰到強制更新的時候,忽略緩存,直接去IIS上請求,為配置文件增加如下函數:
sub vcl_hit {
if
(req.http.Cache-Control~
"no-cache"
||req.http.Cache-Control~
"max-age=0"
||req.http.Pragma~
"no-cache"
){
set
obj.ttl=0s;
return
(restart);
}
return
(deliver);
}
|
經過上面的修改后,再次使用強制更新varnish將會忽略緩存,到IIS上去拿正文。
參考:
https://www.varnish-cache.org/docs/trunk/reference/varnishlog.html
https://www.varnish-cache.org/trac/wiki/Introduction#TheVarnishConfigurationLanguage
http://www.docunext.com/wiki/Varnish
http://cd34.com/blog/infrastructure/no-esi-processing-first-char-not/
本系列之前篇: