定义大型网站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
进行服务端渲染