天天看點

Varnish搭建緩存代理提高網站通路速度

簡介:

Varnish是一款高性能、開源的反向代理伺服器和緩存伺服器,官方說是squid的四倍,實際應用測試中雖然達不到四倍的性能,那也能達到1-2倍的效果。

Varnish和Squid的對比:

Squid 也是一種開源的代理緩存軟體,下面對比 Varnish 和 Squid 的不同點。

Varnish的穩定性很好。兩者在完成相同負載的工作時,Squid伺服器發生故障的幾率要高于Varnish,是以Squid需要經常重新開機。Varnish通路速度更快。Varnish采用了 Visual Page Cache技術,所有緩存的資料都直接從記憶體讀取,而Squid從硬碟讀取緩存的資料,是以Varnish在通路速度方面會更快一些。Varnish可以支援更多的并發連接配接。因為Varnish的TCP連接配接與釋放比Squid快,是以在高并發連接配接情況下可以支援更多的TCP連接配接。Varnish可以通過管理端口來管理緩存,使用正規表達式就可以批量清除部分緩存,而Squid做不到這一點。

Varnish缺點:

Varnish在高并發狀态下,CPU、I/O和記憶體等資源的開銷高于Squid。Varnish的程序一旦挂起、崩潰或者重新開機,緩存的資料都會從記憶體中釋放出來。此時的所有請求都會被發送到後端應用伺服器上,在高并發的情況下,就會給後端伺服器造成很大壓力。

一、安裝varnish

1.下載下傳:https://www.varnish-cache.org/releases/varnish-cache-3.0.3

1

2

3

4

5

<code>yum </code><code>install</code> <code>-y </code><code>make</code> <code>automake pkgconfig libtool pcre-devel </code><code>#安裝依賴包</code>

<code>tar</code> <code>zxvf varnish-3.0.3.</code><code>tar</code><code>.gz</code>

<code>.</code><code>/autogen</code><code>.sh</code>

<code>.</code><code>/configure</code> <code>--prefix=</code><code>/usr/local/varnish</code> <code>--</code><code>enable</code><code>-debugging-symbols --</code><code>enable</code><code>-developer-warnings --</code><code>enable</code><code>-dependency-tracking</code>

<code>make</code> <code>&amp;&amp; </code><code>make</code> <code>install</code>

2.建立使用者、組和日志檔案

<code>groupadd varnish</code>

<code>useradd</code> <code>-g varnish -s </code><code>/sbin/nologin</code> <code>varnish</code>

<code>touch</code> <code>/usr/local/varnish/access</code><code>.log </code><code>#建立通路日志檔案</code>

<code>chown</code> <code>-R varnish.varnish </code><code>/usr/local/varnish</code>

二、修改配置varnish

前端varnish緩存是以輪詢的方式分擔到後端web伺服器,以下vcl不對php進行緩存。

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

<code>vi</code> <code>/usr/local/varnish/etc/varnish/default</code><code>.vcl</code>

<code> </code><code>backend web1 {</code>

<code> </code><code>.host = </code><code>"192.168.0.203"</code><code>; </code><code>#後端web1伺服器ip</code>

<code> </code><code>.port = </code><code>"80"</code><code>; </code><code>#通過80端口來通路後端web</code>

<code> </code><code>.connect_timeout = 1s;  </code><code>#連接配接逾時時間</code>

<code> </code><code>.probe = {</code>

<code>        </code><code>.url = </code><code>"/"</code><code>;</code>

<code>        </code><code>.interval = 5s;</code>

<code>        </code><code>.timeout = 1 s;  </code><code>#檢測逾時時間</code>

<code>        </code><code>.window = 5;</code>

<code>        </code><code>.threshold = 3;</code>

<code>    </code><code>}</code>

<code> </code><code>}</code>

<code> </code><code>backend web2 {</code>

<code> </code><code>.host = </code><code>"192.168.0.204"</code><code>;</code>

<code> </code><code>.port = </code><code>"80"</code><code>;</code>

<code>director default round-robin { </code><code>#定義後端伺服器組,預設輪詢方式</code>

<code> </code><code>{</code>

<code> </code><code>.backend = web1;</code>

<code> </code><code>.backend = web2;</code>

<code>}</code>

<code> </code><code>sub vcl_recv {</code>

<code> </code><code>if</code> <code>(req.restarts == 0) {</code>

<code> </code><code>if</code> <code>(req.http.x-forwarded-</code><code>for</code><code>) {</code>

<code> </code><code>set</code> <code>req.http.X-Forwarded-For =</code>

<code> </code><code>req.http.X-Forwarded-For + </code><code>", "</code> <code>+ client.ip;</code>

<code> </code><code>else</code> <code>{</code>

<code> </code><code>set</code> <code>req.http.X-Forwarded-For = client.ip;</code>

<code> </code><code>if</code> <code>(req.request != </code><code>"GET"</code> <code>&amp;&amp;</code>

<code> </code><code>req.request != </code><code>"HEAD"</code> <code>&amp;&amp;</code>

<code> </code><code>req.request != </code><code>"PUT"</code> <code>&amp;&amp;</code>

<code> </code><code>req.request != </code><code>"POST"</code> <code>&amp;&amp;</code>

<code> </code><code>req.request != </code><code>"TRACE"</code> <code>&amp;&amp;</code>

<code> </code><code>req.request != </code><code>"OPTIONS"</code> <code>&amp;&amp;</code>

<code> </code><code>req.request != </code><code>"DELETE"</code><code>) {</code>

<code> </code><code>return</code> <code>(pipe);</code>

<code> </code><code>if</code> <code>(req.request != </code><code>"GET"</code> <code>&amp;&amp; req.request != </code><code>"HEAD"</code><code>) {</code>

<code> </code><code>return</code> <code>(pass);</code>

<code> </code><code>if</code> <code>(req.http.Authorization || req.http.Cookie) {</code>

<code> </code><code>return</code> <code>(lookup);</code>

<code> </code><code>sub vcl_pipe {</code>

<code> </code><code>sub vcl_pass {</code>

<code> </code><code>sub vcl_hash {</code>

<code> </code><code>hash_data(req.url);</code>

<code> </code><code>if</code> <code>(req.http.host) {</code>

<code> </code><code>hash_data(req.http.host);</code>

<code> </code><code>hash_data(server.ip);</code>

<code> </code><code>return</code> <code>(</code><code>hash</code><code>);</code>

<code> </code><code>sub vcl_hit {</code>

<code> </code><code>return</code> <code>(deliver);</code>

<code> </code><code>sub vcl_miss {</code>

<code> </code><code>return</code> <code>(fetch);</code>

<code> </code><code>sub vcl_fetch {</code>

<code> </code><code>if</code> <code>(beresp.ttl &lt;= 0s ||</code>

<code> </code><code>beresp.http.Set-Cookie ||</code>

<code> </code><code>beresp.http.Vary == </code><code>"*"</code><code>) {</code>

<code> </code><code>set</code> <code>beresp.ttl = 120 s;</code>

<code> </code><code>return</code> <code>(hit_for_pass);</code>

<code> </code><code>sub vcl_deliver {</code>

<code> </code><code>sub vcl_error {</code>

<code> </code><code>set</code> <code>obj.http.Content-Type = </code><code>"text/html; charset=utf-8"</code><code>;</code>

<code> </code><code>set</code> <code>obj.http.Retry-After = </code><code>"5"</code><code>;</code>

<code> </code><code>synthetic {"</code>

<code> </code><code>&lt;?xml version=</code><code>"1.0"</code> <code>encoding=</code><code>"utf-8"</code><code>?&gt;</code>

<code> </code><code>&lt;!DOCTYPE html PUBLIC </code><code>"-//W3C//DTD XHTML 1.0 Strict//EN"</code>

<code> </code><code>"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"</code><code>&gt;</code>

<code> </code><code>&lt;html&gt;</code>

<code> </code><code>&lt;</code><code>head</code><code>&gt;</code>

<code> </code><code>&lt;title&gt;</code><code>"} + obj.status + "</code> <code>" + obj.response + {"</code><code>&lt;</code><code>/title</code><code>&gt;</code>

<code> </code><code>&lt;</code><code>/head</code><code>&gt;</code>

<code> </code><code>&lt;body&gt;</code>

<code> </code><code>&lt;h1&gt;Error </code><code>"} + obj.status + "</code> <code>" + obj.response + {"</code><code>&lt;</code><code>/h1</code><code>&gt;</code>

<code> </code><code>&lt;p&gt;</code><code>"} + obj.response + {"</code><code>&lt;</code><code>/p</code><code>&gt;</code>

<code> </code><code>&lt;h3&gt;Guru Meditation:&lt;</code><code>/h3</code><code>&gt;</code>

<code> </code><code>&lt;p&gt;XID: </code><code>"} + req.xid + {"</code><code>&lt;</code><code>/p</code><code>&gt;</code>

<code> </code><code>&lt;hr&gt;</code>

<code> </code><code>&lt;p&gt;Varnish cache server&lt;</code><code>/p</code><code>&gt;</code>

<code> </code><code>&lt;</code><code>/body</code><code>&gt;</code>

<code> </code><code>&lt;</code><code>/html</code><code>&gt;</code>

<code> </code><code>"};</code>

<code> </code><code>sub vcl_init {</code>

<code> </code><code>return</code> <code>(ok);</code>

<code> </code><code>sub vcl_fini {</code>

語句解析:

Varnish處理請求的主要處理方法

1. vcl_recv

首先接收請求,判斷是否要進一步處理,還是直接轉發給後端(pass)等。 此過程中可以使用和請求相關的變量,例如用戶端請求的url,ip,user-agent,cookie等,此過程中可以把不需緩存的位址,通過判斷(相等、不相等、正則比對等方法)轉給後端,例如gif/png/jpg/css/js等靜态檔案;

2. vcl_fetch

當從後端伺服器擷取内容後會進入此階段,除了可以使用用戶端的請求變量,還可以使用從後端擷取的資訊(bersp),如後端傳回的頭資訊,設定此資訊的緩存時間TTL等;

3. vcl_miss

緩存未命中時中要做的處理

4. vcl_hit

緩存命中後做的處理

5. vcl_deliver

發送給用戶端前的處理

6. vcl_pass

交給後端伺服器

7. vcl_hash

設定緩存的鍵值key

Varnish處理流程

首次請求時過程如下:

recv-&gt;hash-&gt;miss-&gt;fetch-&gt;deliver

緩存後再次請求:

recv-&gt;hash-&gt;hit-&gt;deliver(fetch的過程沒了,這就是我們要做的,把要緩存的頁面儲存下來)

直接交給後端pass的情況:

recv-&gt;hash-&gt;pass-&gt;fetch-&gt;deliver(直接從後端擷取資料後發送給用戶端,此時Varnish相當于一個中轉站,隻負責轉發)

三、測試

1、啟動

<code>/usr/local/varnish/sbin/varnishd</code> <code>-f </code><code>/usr/local/varnish/etc/varnish/default</code><code>.vcl -s malloc,512M -g varnish -u varnish -T 127.0.0.1:2000 -a 0.0.0.0:80</code>

-f:選項用于指定Varnishd使用的配置檔案的路徑。

-s malloc,2G:–s選項用來确定Varnish使用的存儲類型和存儲容量,這裡使用的是malloc類型(malloc是一個C函數,用于配置設定記憶體空間),2G 定義多少記憶體被malloced。

-T:127.0.0.1:2000是Varnish基于文本方式的一個管理接口,啟動後可以在不停止Varnish的情況下來管理Varnish。管理端口2000可以指定。因為不是任何人都可以通路Varnish管理端口,是以這裡推薦隻監聽本機端口。

-a:0.0.0.0:80中-a選項表示Varnish監聽所有IP發給80端口的HTTP請求。

2、設定varnish通路日志

<code>/usr/local/</code><code>var</code><code>nish/bin/</code><code>var</code><code>nishncsa -n /usr/local/</code><code>var</code><code>nish/</code><code>var</code><code>/</code><code>var</code><code>nish/test.com -a -w /usr/local/</code><code>var</code><code>nish/access.log &amp; #将</code><code>var</code><code>nish通路日志寫入到access.log裡</code>

<code>/usr/local/</code><code>var</code><code>nish/</code><code>var</code><code>/</code><code>var</code><code>nish/test.com :預設緩存目錄</code>

<code>netstat -tuplan |grep </code><code>var</code><code>nish #檢視是否啟動</code><code>2000</code><code>和</code><code>80</code><code>端口</code>

<code>tcp </code><code>0</code> <code>0</code> <code>0.0</code><code>.</code><code>0.0</code><code>:</code><code>80</code> <code>0.0</code><code>.</code><code>0.0</code><code>:* LISTEN </code><code>28551</code><code>/</code><code>var</code><code>nishd</code>

<code>tcp </code><code>0</code> <code>0</code> <code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>2000</code> <code>0.0</code><code>.</code><code>0.0</code><code>:* LISTEN </code><code>28550</code><code>/</code><code>var</code><code>nishd</code>

<code>tcp </code><code>0</code> <code>0</code> <code>:::</code><code>80</code> <code>:::* LISTEN </code><code>28551</code><code>/</code><code>var</code><code>nishd</code>

<code>curl -I http:</code><code>//ip #使用curl指令檢視是否被緩存</code>

<code>killall -</code><code>9</code> <code>var</code><code>nishd #關閉</code><code>var</code><code>nish</code>

現在輸入varnish伺服器ip就可以通路到後端web伺服器!

3、設定開機啟動:

<code>echo</code> <code>'/usr/local/varnish/sbin/varnishd -f /usr/local/varnish/etc/varnish/default.vcl -s malloc,512M -g varnish -u varnish -T 127.0.0.1:2000 -a 0.0.0.0:80'</code> <code>&gt;&gt; </code><code>/etc/rc</code><code>.</code><code>local</code>

4、添加多個後端伺服器

如果添加多個後端網站伺服器,在default.vcl裡面添加不同網站的通路請求轉發到對應的backend去。

本文轉自 李振良OK 51CTO部落格,原文連結:http://blog.51cto.com/lizhenliang/1300036,如需轉載請自行聯系原作者

繼續閱讀