定義大型網站php
pv值(page views)
頁面瀏覽量:一個網站全部頁面在24小時內,被瀏覽的總的次數。達到千萬級別/百萬級別。uv值(unique visitor)
獨立訪客:一個網站在24小時內,有多少個用戶來訪問網站。達到10w左右。uv值約等於獨立IP值。考慮局域網,或者校內網,則獨立IP小於uv值。css
產生的問題html
常規解決方案前端
併發對應方案:對網站的架構重整,使用分層的結構,同時使用負載均衡/讀寫分離+集羣。mysql
負載均衡器(器,軟件/硬件):
硬件:BIG-IP
,F5
,Net-Scaler
。硬件的特色:效率高,價格貴。
軟件:LVS(Linux virtual server)
linux虛擬服務,Nginx
Web服務器+反向代理linux
讀(select)寫(update,insert,delete)分離:
寫,通常把請求發送到master服務器上。
讀,根據實際狀況均衡到其它多個服務器上。(網站的程序80%都是讀操做)nginx
讀寫分離原理:
主服務器上操做完以後,會造成bin文件
,操做的行爲會記錄在bin文件
中。在從服務器中讀取該文件,取在主服務器的行爲,完成主從數據同步。(經過一個線程,不停的去讀取bin文件)
經過配置完成讀寫分離。git
集羣github
解決單點故障的恢復(冗餘技術)web
備用`apache`,`nginx`(處於休眠狀態),經過心跳檢測來檢測`apache`,`nginx`(被檢測的服務器屬於激活狀態)是否宕機。(備用服務器+服務器稱之爲集羣)
負載均衡的實現方案:
大流量的解決方案:
gzip
,deflate
大存儲對應方案:
使用緩存:經過緩存來儘可能減小或者不查詢數據庫。
常見的有:頁面靜態化(磁盤緩存),把動態頁面轉換成靜態頁面。 內存緩存`redis,memcached,mysql數據庫的memory存儲引擎`。
my.ini
的配置,nginx的nginx.conf
的配置,好比配置最大併發,調整一些緩存大小。頁面靜態化分爲:
僞靜態:所謂僞靜態是從url地址上看是一個靜態頁面的,可是實際上仍是對應一個動態頁面。
僞靜態的原理:
第一次訪問的時候去查詢數據庫,而且生成靜態頁面。
第二次訪問返回靜態頁面。
linxingzhang.com/index.html
-> 請求靜態頁面 <-- 首頁對應的靜態頁面
僞靜態的局部配置:
RewriteRule ^index\.html$ index\.php [L]
概念
動態網址:
通常來講去查詢數據庫,linxingzhang.com/news.php?id=1
特色:
只要有數據的接收,則要求對在客戶端使用正則驗證,同時當數據接收後,對數據再次經過正則驗證。
SQL注入
SQL注入:利用現有應用程序,攻擊者將精心構造的SQL語句注入到後臺數據庫,並使得數據庫引擎成功執行。
SQL注入特色:
SQL注入攻擊的危害性
SQL注入工具:
掃描檢測
AWVS,web掃描器,APPScan Web掃描器等,抓包代理工具burpsuite
驗證測試
sqlmap
手工探測SQL漏洞:
經過拼接SQL語句來判斷和驗證漏洞
// 測試語句 id=1' and 1=1 and 1=2 order by num union 聯合查詢 and 1=2 union select 1,2,3,4 user() database() group_coucat(table_name) from information_schema.tables where table_schema=tableName // table名十六進制 select * from downloads where id=1 and 1=2 union select 1,2,3,4,5,6,group_concat(username) from members;
?id=1 and 1=2 union select 1,2,3,4,5,6,load_file('/etc/passwd') ?id=1 and 1=2 union select 1,2,3,4,5,6,@@version ?id=1 and 1=2 union select 1,2,3,4,5,6,@@version_compile_os ?id=1 and 1=2 union select 1,2,3,4,5,6,@@basedir ?id=1 and 1=2 union select 1,2,3,4,5,6,@@datadir
SQL防護:
代碼層防護
編碼階段:
測試階段:
產品化階段:
第三方安全程序
軟件產品
mod_security 互聯網安全防禦產品(阿里雲盾,安全寶等同類產品)
硬件
web應用防火牆
SQL語句驗證
function CheckSql($db_string, $querytype = 'select') { global $cfg_cookie_encode; $clean = ''; $error = ''; $old_pos = 0; $pos = -1; $log_file = DEDEINC.'/../data/'.md5($cfg_cookie_encode).'_safe.txt'; $userIP = GetIP(); $getUrl = GetCurUrl(); // 若是是普通查詢語句,直接過濾一些特殊語法 if ($querytype=='select') { $notallow1 = "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}"; // $notallow2 = "--|/\*"; if (eregi($notallow1,$db_string)) { fputs(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||SelectBreak\r\n"); exit("<font size='5' color='red'>Safe Alert: Request Error step 1 !</font>"); } } // 完整的SQL檢查 while (true) { $pos = strpos($db_string, '\'', $pos + 1); if ($pos === false) { break; } $clean .= substr($db_string, $old_pos, $pos - $old_pos); while (true) { $pos1 = strpos($db_string, '\'', $pos + 1); $pos2 = strpos($db_string, '\\', $pos + 1); if ($pos1 === false) { break; } elseif ($pos2 == false || $pos2 > $pos1) { $pos = $pos1; break; } $pos = $pos2 + 1; } $clean .= '$s$'; $old_pos = $pos + 1; } $clean .= substr($db_string, $old_pos); $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean))); // 老版本的Mysql並不支持union,經常使用的程序裏也不使用union,可是一些黑客使用它,因此檢查它 if (strpos($clean, 'union') !== false && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="union detect"; } // 發佈版本的程序可能比較少包括--,#這樣的註釋,可是黑客常用它們 elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== false || strpos($clean, '#') !== false) { $fail = true; $error="comment detect"; } // 這些函數不會被使用,可是黑客會用它來操做文件,down掉數據庫 elseif (strpos($clean, 'sleep') !== false && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="slown down detect"; } elseif (strpos($clean, 'benchmark') !== false && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="slown down detect"; } elseif (strpos($clean, 'load_file') !== false && preg_match('~(^|[^a-z])load_file($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="file fun detect"; } elseif (strpos($clean, 'into outfile') !== false && preg_match('~(^|[^a-z])into\s+outfile($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="file fun detect"; } // 老版本的MYSQL不支持子查詢,程序裏可能也用得少,可是黑客可使用它來查詢數據庫敏感信息 elseif (preg_match('~\([^)]*?select~s', $clean) != 0) { $fail = true; $error="sub select detect"; } }
靜態網址:linxingzhang.com/a.html
靜態的網址
特色:
僞靜態網址:
從形式上看是一個靜態的頁面,可是實際上對應一個動態的頁面。
特色:
局部動態的方式:
直接嵌入JS
<script scr="xx.php"></script>
如何實現頁面靜態化
實現頁面靜態化(真靜態),有兩種方法:
OB就是output_buffering
,輸出緩存,在請求一個PHP的過程當中,實際上過三個緩存:1.程序緩存,2.OB緩存,3:瀏覽器緩存。
<?php echo 1; header('Content-Type: text/html; charset=utf-8'); echo 2; // 報警告
<?php ob_start(); // 開啓 echo 1; header('Content-Type: text/html; charset=utf-8'); echo 2; // 正常輸出 // OB緩存打開以後,輸出的語句,不會放到程序緩存中,而是放到OB緩存中,當程序執行完畢以後,OB緩存的東西強制放到程序緩存後邊,而後再二次加工成ht響應報,返回。
程序緩存,該緩存是PHP固有的,不能關閉。
每行代碼,每一個函數在程序緩存中,處理結果以後,拼接在一塊兒經過HTTP響應返回給瀏覽器。
開啓OB緩存:
php.ini
中開啓:output_buffering = 4096
4096 緩存大小。做用於全部的php後綴文件.ob_start()
,只能做用於該頁面若是沒有OB緩存,全部的緩存都放在程序緩存中。
header信息無論你是否開啓ob,老是放入到程序緩存中。
ob_get_contents(); // 獲取OB中的內容 ob_clean(); // 清除ob緩存,但不關閉ob緩存 ob_end_clean(); // 清除ob緩存,同時關閉ob緩存 ob_end_flush(); // 強制把ob緩存刷新到程序緩存,並關閉ob緩存 ob_flush(); // 強制把ob緩存刷新到程序緩存 flush(); // 把程序緩存刷新到瀏覽器緩存中
ob緩存細節
ob緩存
究竟能夠存放什麼樣的數據?
靜態數據:html,css,js,動態語言輸出的結果.
ob放入的數據,從ob_start()
開始到ob_get_contents()
之間的返回給瀏覽器的靜態頁面
經常使用工具
ab.exe
,winrunner
,loadrunner
ab.exe
基本用法:
切換到apache-bin
目錄底下,而後運行ab.exe
命令
// ab.exe -n 總的請求次數 -c 併發量 請求頁面地址 ab.exe -n 10000 -c 100 http://127.0.0.1 // 100我的完成10000次
測試結果:
> ab.exe -n 10000 -c 100 http://www.ting.com/index.html This is ApacheBench, Version 2.3 <$Revision: 1554214 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking www.ting.com (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Server Software: Apache/2.4.9 Server Hostname: www.ting.com Server Port: 80 Document Path: /index.html Document Length: 6847 bytes Concurrency Level: 100 // 併發數 Time taken for tests: 9.118 seconds // 完成的時間,值越小,服務器越好,越強悍。 Complete requests: 10000 Failed requests: 0 Total transferred: 71060000 bytes HTML transferred: 68470000 bytes Requests per second: 1096.69 [#/sec] (mean) // 一秒鐘完成多少次請求 Time per request: 91.184 [ms] (mean) // 100我的併發一次花費的時間 Time per request: 0.912 [ms] (mean, across all concurrent requests) // 一我的併發花費的時間 Transfer rate: 7610.41 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 1.2 0 11 Processing: 26 90 23.8 84 424 Waiting: 26 76 24.4 72 410 Total: 27 90 23.9 85 425 Percentage of the requests served within a certain time (ms) 50% 85 66% 91 75% 96 80% 101 90% 109 95% 117 98% 128 99% 188 100% 425 (longest request) Finished 10000 requests
調整apache的最大併發數
在默認狀況下,apache的最大併發數爲150
配置文件:httpd-mpm.conf
MPM(多路處理模塊),就是apache處理併發的方式:
肯定mpm的指令
> httpd.exe -l Compiled in modules: core.c mod_win32.c mpm_winnt.c // MPM模式 http_core.c mod_so.c
須要在httpd.conf
文件的打開mpm
從配置文件(Include conf/extra/httpd-mpm.conf
),而後在httpd-mpm.conf
文件中修改最大配置數
配置最大併發數,須要在合適數值之間,須要考慮服務器自己的性能問題
spider
不抓取DNS預解析
DNS預解析與業務相關,
DNS缺點:
<meta htt-equiv="x-dns-prefetch-control" content="on" /> <link rel="dns-prefetch" href="" />
域名收斂
域名收斂:將靜態資源只放在一個域名下面,而非發散狀況下的多個域名下
做用:減小DNS解析的開銷
performance對象
performance對象做用:查看網頁性能數據
// 獲取 performance 數據 var performance = { // memory 是非標準屬性,只在 Chrome 有 // 財富問題:我有多少內存 memory: { usedJSHeapSize: 16100000, // JS 對象(包括V8引擎內部對象)佔用的內存,必定小於 totalJSHeapSize totalJSHeapSize: 35100000, // 可以使用的內存 jsHeapSizeLimit: 793000000 // 內存大小限制 }, // 哲學問題:我從哪裏來? navigation: { redirectCount: 0, // 若是有重定向的話,頁面經過幾回重定向跳轉而來 type: 0 // 0 即 TYPE_NAVIGATENEXT 正常進入的頁面(非刷新、非重定向等) // 1 即 TYPE_RELOAD 經過 window.location.reload() 刷新的頁面 // 2 即 TYPE_BACK_FORWARD 經過瀏覽器的前進後退按鈕進入的頁面(歷史記錄) // 255 即 TYPE_UNDEFINED 非以上方式進入的頁面 }, timing: { // 在同一個瀏覽器上下文中,前一個網頁(與當前頁面不必定同域)unload 的時間戳,若是無前一個網頁 unload ,則與 fetchStart 值相等 navigationStart: 1441112691935, // 前一個網頁(與當前頁面同域)unload 的時間戳,若是無前一個網頁 unload 或者前一個網頁與當前頁面不一樣域,則值爲 0 unloadEventStart: 0, // 和 unloadEventStart 相對應,返回前一個網頁 unload 事件綁定的回調函數執行完畢的時間戳 unloadEventEnd: 0, // 第一個 HTTP 重定向發生時的時間。有跳轉且是同域名內的重定向纔算,不然值爲 0 redirectStart: 0, // 最後一個 HTTP 重定向完成時的時間。有跳轉且是同域名內部的重定向纔算,不然值爲 0 redirectEnd: 0, // 瀏覽器準備好使用 HTTP 請求抓取文檔的時間,這發生在檢查本地緩存以前 fetchStart: 1441112692155, // DNS 域名查詢開始的時間,若是使用了本地緩存(即無 DNS 查詢)或持久鏈接,則與 fetchStart 值相等 domainLookupStart: 1441112692155, // DNS 域名查詢完成的時間,若是使用了本地緩存(即無 DNS 查詢)或持久鏈接,則與 fetchStart 值相等 domainLookupEnd: 1441112692155, // HTTP(TCP) 開始創建鏈接的時間,若是是持久鏈接,則與 fetchStart 值相等 // 注意若是在傳輸層發生了錯誤且從新創建鏈接,則這裏顯示的是新創建的鏈接開始的時間 connectStart: 1441112692155, // HTTP(TCP) 完成創建鏈接的時間(完成握手),若是是持久鏈接,則與 fetchStart 值相等 // 注意若是在傳輸層發生了錯誤且從新創建鏈接,則這裏顯示的是新創建的鏈接完成的時間 // 注意這裏握手結束,包括安全鏈接創建完成、SOCKS 受權經過 connectEnd: 1441112692155, // HTTPS 鏈接開始的時間,若是不是安全鏈接,則值爲 0 secureConnectionStart: 0, // HTTP 請求讀取真實文檔開始的時間(完成創建鏈接),包括從本地讀取緩存 // 鏈接錯誤重連時,這裏顯示的也是新創建鏈接的時間 requestStart: 1441112692158, // HTTP 開始接收響應的時間(獲取到第一個字節),包括從本地讀取緩存 responseStart: 1441112692686, // HTTP 響應所有接收完成的時間(獲取到最後一個字節),包括從本地讀取緩存 responseEnd: 1441112692687, // 開始解析渲染 DOM 樹的時間,此時 Document.readyState 變爲 loading,並將拋出 readystatechange 相關事件 domLoading: 1441112692690, // 完成解析 DOM 樹的時間,Document.readyState 變爲 interactive,並將拋出 readystatechange 相關事件 // 注意只是 DOM 樹解析完成,這時候並無開始加載網頁內的資源 domInteractive: 1441112693093, // DOM 解析完成後,網頁內資源加載開始的時間 // 在 DOMContentLoaded 事件拋出前發生 domContentLoadedEventStart: 1441112693093, // DOM 解析完成後,網頁內資源加載完成的時間(如 JS 腳本加載執行完畢) domContentLoadedEventEnd: 1441112693101, // DOM 樹解析完成,且資源也準備就緒的時間,Document.readyState 變爲 complete,並將拋出 readystatechange 相關事件 domComplete: 1441112693214, // load 事件發送給文檔,也即 load 回調函數開始執行的時間 // 注意若是沒有綁定 load 事件,值爲 0 loadEventStart: 1441112693214, // load 事件的回調函數執行完畢的時間 loadEventEnd: 1441112693215 } };
鏈路複用
資源內聯
在移動APP上面,在特定狀況下會將CSS樣式放在.html
中
組件化開發
服務端渲染
Node.js
進行服務端渲染