Linux: Apache
- TAGS: Linux
1 Internet和HTTP协议
1.1 Internet 因特网
因特网是“Internet”的中文译名,它起源于美国的五角大楼,它的前身是美国 国防部高级研究计划局(ARPA)主持研制的ARPAnet。20世纪50年代末,正处于 冷战时期。当时美国军方为了自己的计算机网络在受到袭击时,即使部分网络被 摧毁,其余部分仍能保持通信联系,便由美国国防部的高级研究计划局(ARPA) 建设了一个军用网,叫做“阿帕网”(ARPAnet)。阿帕网于1969年正式启用, 当时仅连接了4台计算机,供科学家们进行计算机联网实验用,这就是因特网的 前身。到70年代,ARPAnet已经有了好几十个计算机网络,但是每个网络只能在 网络内部的计算机之间互联通信,不同计算机网络之间仍然不能互通。为此, ARPA又设立了新的研究项目,支持学术界和工业界进行有关的研究,研究的主要 内容就是想用一种新的方法将不同的计算机局域网互联,形成“互联网”。研究 人员称之为“internetwork”,简称“Internet”
ARPA DNS反向解析
在研究实现互联的过程中,计算机软件起了主要的作用。1974年,出现了连接分组网络的协议,其中就包括了TCP/IP协议。TCP/IP有一个非常重要的特点,就是开放性,即TCP/IP的规范和Internet的技术都是公开的。目的就是使任何厂家生产的计算机都能相互通信,使Internet成为一个开放的系统,这正是后来Internet得到飞速发展的重要原因。ARPA在1982年接受了TCP/IP,选定Internet为主要的计算机通信系统,并把其它的军用计算机网络都转换到TCP/IP。1983年,ARPAnet分成两部分:一部分军用,称为MILNET;另一部分仍称ARPAnet,供民用。
1986年,美国国家科学基金组织(NSF)将分布在美国各地的5个为科研教育服务的超级计算机中心互联,并支持地区网络,形成SNSFnet。1988 年,SNSFnet替代ARPAnet成为Internet的主干网。NSFnet主干网利用了在ARPAnet中已证明是非常成功的TCP/IP技术,准许各大学、政府或私人科研机构的网络加入。1989年,ARPAnet解散,Internet从军用转向民用。
Internet的发展引起了商家的极大兴趣。1992年,美国IBM、MCI、MERIT三家公司联合组建了一个高级网络服务公司(SNS),建立了一个新的网络,叫做SNSnet,成为Internet的另一个主干网。它与SNSFnet不同,NSFnet是由国家出资建立的,而SNSnet则是SNS公司所有,从而使Internet开始走向商业化。
1995年4月30日,SNSFnet正式宣布停止运作。而此时Internet的骨干网已经覆盖了全球91个国家,主机已超过400万台。而在当前,因特网仍以惊人的速度向前发展
在90年代,超文本标识语言(HTML),即一个可以获得因特网的图像信息的超文本因特网协议被采用,使每一个人可以产生自己的图像页面(网址),然后成为一个巨大的虚拟超文本网络的组成部分。这个增强型的因特网又被非正式地称为万维网,与此同时产生了数量庞大的新用户群。于是,许多人用“因特网” 一词指这个网络的物理结构,包括连接所有事物的客户机、服务器和网络;而用“万维网”一词指利用这个网络可以访问的所有网站和信息。
1.2 Internet 和中国
北京时间1987年9月14日,钱天白建立起一个网络节点,通过电话拨号连接到国 际互联网,向他的德国朋友发出来自中国的第一封电子邮件:Across the Great Wall we can reach every corner in the world,自此,中国与国际计算机网 络开始连接在一起
1990年10月, 钱天白教授代表中国正式在国际互联网络信息中心的前身DDN-NIC注册登记了我国的顶级域名CN,并且从此开通了使用中国顶级域名CN的国际电子邮件服务。由于当时中国尚未正式连入Internet,所以委托德国卡尔斯鲁厄大学运行CN域名服务器
1993年3月2日, 中国科学院高能物理研究所租用AT&T公司的国际卫星信道接入美国斯坦福线性加速器中心(SLAC)的64K专线正式开通,专线开通后,美国政府以Internet上有许多科技信息和其它各种资源,不能让社会主义国家接入为由,只允许这条专线进入美国能源网而不能连接到其它地方。尽管如此,这条专线仍是我国部分连入Internet的第一根专线
1994年4月20日,中国通过一条64k的国际专线全功能接入国际互联网,成为国际互联网大家庭中的第77个成员,正式开启了互联网时代。随后,中科院高能物理研究所推出第一个WWW网站和第一套网页
1994年5月21日, 在钱天白教授和德国卡尔斯鲁厄大学的协助下,中国科学院计算机网络信息中心完成了中国国家顶级域名(CN)服务器的设置,改变了中国CN顶级域名服务器一直放在国外的历史
1995年5月17日, 第27个世界电信日,邮电部正式宣布,向国内社会开放计算机互联网接入服务
1995年5月,北京的中关村南大街上出现了一块巨大的广告牌,"中国离信息高速公路还有多远?向北1500米。"那个位置就是一家叫“瀛海威”的网络科教馆,瀛海威正是information highway的音译,作为中国第一个互联网接入服务商,瀛海威几乎就是当时互联网的代名词
1996年1月,中国互联网全国骨干网建成并正式开通,开始提供服务
1995年4月,马云凑了两万块钱,成立杭州海博网络公司,专门给企业做主页
1997年5月,丁磊创立网易
1998年2月, 张朝阳创立搜狐
1998年6月18日,刘强东在中关村创办京东公司,代理销售光磁产品
1998年11月,马化腾和张志东成立深圳市腾讯计算机系统有限公司,OICQ开通
1998年12月, 新浪网成立,关键人物:王志东
1999年5月18日,中国第一家电子商务企业8848.com成立,创始人王峻涛也曾被誉为“中国电子商务教父”。2000年底,调查显示接近70%的人说上网买东西首选
8848
2000年1月,李彦宏创建了百度
2003年5月,阿里巴巴集团在创立淘宝网
2003年10月, 淘宝网首次推出支付宝服务
2004年1月,京东多媒体网正式开通,启用域名<www.jdlaser.com>
2010年4月,雷军创办小米
2011年1月21日,腾讯公司推出微信 (WeChat)
2012年3月,今日头条由张一鸣于创建
2012年7月10日,北京小桔科技有限公司成立,滴滴司机端3个月后北京上线
下一个又是谁呢?
中国互联网连接世界
1885年台湾建省,首任巡抚刘铭传派人与福州船政联系,使用船政电报学堂毕业生为技术人员,于1887年铺设成功台湾淡水至福州川石海底电缆,全长117海里。这是我国自行设计安装的第一条海底电缆。此电缆毁于第二次世界大战我国于1989年开始投入到全球海底光缆的投资与建设中来,并于1993年实现了首条国际海底光缆的登陆(中日之间C-J海底光缆系统);随后在1997年,我国参与建设的全球海底光缆系统(FLAG)建成并投入运营,这也是第一条在我国登陆的洲际海底光缆中国连接世界目前共有8条光缆,四个登陆站允许入境,目前我国的登陆站设立在三个城市的四个地区,分别是山东青岛登陆站(隶属中国联通)、上海崇明登陆站(隶属中国电信)、上海南汇登陆站(隶属中国联通)和 广东汕头登陆站(隶属中国电信)
1.3 跨网络的主机间通讯
Socket套接字
套接字Socket是进程间通信IPC的一种实现,允许位于不同主机(或同一主机)上不同进程之间进行通信和数据交换,SocketAPI出现于1983年,4.2 BSD实现
在建立通信连接的每一端,进程间的传输要有两个标志:*IP地址和端口号,合称为套接字*地址
socket address
客户机套接字地址定义了一个唯一的客户进程
服务器套接字地址定义了一个唯一的服务器进程
Socket API
封装了内核中所提供的socket通信相关的系统调用
- Socket Domain:根据其所使用的地址
- AF_INET:Address Family,IPv4
- AF_INET6:IPv6
- AF_UNIX:同一主机上不同进程之间通信时使用
- Socket Type:根据使用的传输层协议
- SOCK_STREAM:流,tcp套接字,可靠地传递、面向连接
- SOCK_DGRAM:数据报,udp套接字,不可靠地传递、无连接
- SOCK_RAW: 裸套接字,无须tcp或udp,APP直接通过IP包通信
客户/服务器程序的套接字函数
*套接字相关的系统调用*:
- socket() 创建一个套接字
- bind() 绑定IP和端口
- listen() 监听
- accept() 接收请求
- connect() 请求连接建立
- write() 发送
- read() 接收
- close()关闭连接
范例:
#利用nc实现服务器端 [root@centos8 ~]#nc -l 8000 hello,I am CentOS8 hello,I am CentOS7 #利用nc实现客户端 [root@centos7 ~]#nc 10.0.0.8 8000 hello,I am CentOS8 hello,I am CentOS7
范例:查看socket实现过程
[root@centos8 ~]#strace -ff -o nc.log nc -l 8000 [root@centos7 ~]#nc 10.0.0.8 8000
范例:socket 相关系统调用
[root@centos8 ~]#dnf -y install man-pages [root@centos8 ~]#man 2 socket [root@centos8 ~]#man 2 bind [root@centos8 ~]#man 2 listen [root@centos8 ~]#man 2 accept [root@centos8 ~]#man 2 read [root@centos8 ~]#man 2 write [root@centos8 ~]#man 2 connect [root@centos8 ~]#man 2 close
范例:Socket通信Python 3.6实现
#需要安装python3 [root@centos8 ~]#dnf install python3 #服务器端tcpserver.py #!/usr/bin/python3 import socket HOST='127.0.0.1' PORT=9527 BUFFER=4096 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # IPv4协议 tcp协议 sock.bind((HOST,PORT)) #绑定地址信息 sock.listen(3) #打开端口,让他处于监听状态 print('tcpServer listen at: %s:%s\n\r' %(HOST,PORT)) while True: client_sock,client_addr=sock.accept() print('%s:%s connect' %client_addr) while True: recv=client_sock.recv(BUFFER) if not recv: client_sock.close() break print('[Client %s:%s said]:%s' % (client_addr[0],client_addr[1],recv.decode())) client_sock.send(b'tcpServer has received your message') sock.close() #客户端tcpclient.py #客户端不需要绑定地址信息,使用随机 #!/usr/bin/python3 import socket HOST='127.0.0.1' PORT=9527 BUFFER=4096 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.connect((HOST,PORT)) #连接服务器的地址和端口 sock.send(b'hello, tcpServer!,I am tcp client') recv=sock.recv(BUFFER) print('[tcpServer said]: %s' % recv.decode()) sock.close()
1.4 HTTP 超文本传输协议
1.4.1 HTTP相关概念
互联网:是网络的网络,是所有类型网络的母集。
因特网:世界上最大的互联网网络。即因特网概念从属于互联网概念。习惯上,大家把连接在因特网上的计算机都成为主机。
万维网:WWW(world wide web)万维网并非某种特殊的计算机网络,是一个大规模的、联机式的信息贮藏所, 使用链接的方法能非常方便地从因特网上的一个站点访问另一个站点 (超链技术),具有提供分布式服务的特点。万维网是一个分布式的超媒体系统,是超文本系统的扩充,基于B/S架构实现
URL :万维网使用*统一资源定位符*(Uniform Resource Locator)来标志万维网上的各种文档,并使每个文档在整个因特网的范围内具有唯一的标识符URL。
HTTP:为解决“用什么样的网络协议来实现整个因特网上的万维网文档”这一难题,就要使万维网客户程序(以浏览器为主,但不限于浏览器)与万维网服务器程序之间的交互遵守严格的协议,即超文本传送协议(HyperText Transfer Protocol)。HTTP是处于应用层的协议,使用TCP传输层协议进行可靠的传送。因此,需要特别提醒的是,万维网是基于因特网的一种广泛因特网应用系统,且万维网采用的是HTTP(80/TCP)和 HTTPS(443/TCP)的传输协议,但因特网还有其他的网络应用系统(如:FTP、SMTP等等)。
HTML:为了解决“怎样使不同作者创作的不同风格的万维网文档,都能在因特网上的各种主机上显示出来,同时使用户清楚地知道在什么地方存在着链接”这一问题,万维网使用超文本标记语言(HyperText Markup Language),使得万维网页面的设计者可以很方便地用链接从页面的某处链接到因特网的任何一个万维网页面,并且能够在自己的主机品目上将这些页面显示出来。HTML与txt一样,仅仅是是一种文档,不同之处在于,这种文档专供于浏览器上为浏览器用户提供统一的界面呈现的统一规约。且具备结构化的特征,这是txt所不具备的强制规定。
1.4.2 浏览器访问网站的过程
1.4.3 HTTP协议通信过程
HTTP(HyperText Transfer Protocol,超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础设计HTTP最初的目的是为了提供一种远距离共享知识的方式,借助多文档进行关联实现超文本,连成相互参阅的WWW(world wide web,万维网)
HTTP的发展是由蒂姆·伯纳斯-李(Tim Berners-Lee)于1989年在欧洲核子研究组织(CERN)所发起。HTTP的标准制定由万维网协会(World Wide Web Consortium,W3C)和互联网工程任务组(Internet Engineering Task Force,IETF)进行协调,最终发布了一系列的RFC,其中最著名的是1999年6月公布的 RFC 2616,定义了HTTP协议中现今广泛使用的一个版本-–—HTTP 1.1版
HTTP服务通信过程
HTTP协议分层
1.4.4 HTTP相关技术
WEB开发语言
*http*:Hyper Text Transfer Protocol 应用层协议,默认端口: 80/tcp
WEB前端开发语言 :
- html
- css
- javascript
html
Hyper Text Markup Language 超文本标记语言,编程语言,主要负责实现页面的结构
范例:html 语言
<html> <head> <meta http-equiv=Content-Type content="text/html;charset=utf-8"> <title>HTML语言</title> </head> <body> <img src="http://www.ciciedu.com/wp-content/uploads/2017/09/logo.png" > <h1 style="color:red">欢迎</h1> <p><a href=http://www.ciciedu.com>马哥教育</a>欢迎你</p> </body> </html>
CSS
Cascading Style Sheet 层叠样式表, 定义了如何显示(装扮) HTML元素,比如:字体大小和颜色属性等。样式通常保存在外部的 .css文件中。通过仅编辑一个简单的 CSS文档,可以同时改变站点中所有页面的布局和外观。
范例 :CSS
#test.html <html> <head> <meta http-equiv=Content-Type content="text/html;charset=utf-8"> <link rel="stylesheet" type="text/css" href="mystyle.css" /> </head> <body> <h1>这是 heading 1</h1> <p>这是一段普通的段落。请注意,该段落的文本是红色的。在 body 选择器中定义了本页面中的默认文本颜色。</p> <p class="ex">该段落定义了 class="ex"。该段落中的文本是蓝色的。</p> </body> </html> #mystyle.css body {color:red} h1 {color:#00ff00} p.ex {color:rgb(0,0,255)}
Js
javascript,实现网页的动画效果,但实属于静态资源
范例:javascript
<!DOCTYPE html> <html> <head> <meta http-equiv=Content-Type content="text/html;charset=utf-8"> </head> <body> <h2>我的第一段 JavaScript</h2> <button type="button" onclick="document.getElementById('demo').innerHTML = Date()"> 点击这里来显示日期和时间 </button> <p id="demo"></p> </body> </html>
MIME
MIME : Multipurpose Internet Mail Extensions 多用途互联网邮件扩展
文件 /etc/mime.types ,来自于mailcap包
MIME格式:major/minor
参考链接:
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/MIME_types
- https://www.w3school.com.cn/media/media_mimeref.asp
范例:
text/plain text/html text/css image/jpeg image/png video/mp4 application/javascript
URI和URL
URI: Uniform Resource Identifier 统一资源标识,分为URL 和 URN
URN:Uniform Resource Naming,统一资源命名
示例 : P2P下载使用的磁力链接是URN的一种实现 magnet:?xt=urn:btih:660557A6890EF888666
URL:Uniform Resorce Locator,统一资源定位符,用于描述某服务器某特定资源位置
两者区别:URN如同一个人的名称,而URL代表一个人的住址。换言之,URN定义某事物的身份,而URL提供查找该事物的方法。URN仅用于命名,而不指定地址
URL组成
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag> 用户密码省略 端口没改的话也省略 http://www.cicin.com/testdir/test.html https://list.jd.com/list.html?cat=9987,653,655 #京东搜手机 scheme #方案,访问服务器以获取资源时要使用哪种协议 user #用户,某些方案访问资源时需要的用户名 password #密码,用户对应的密码,中间用:分隔 Host #主机,资源宿主服务器的主机名或IP地址 port #端口,资源宿主服务器正在监听的端口号,很多方案有默认端口号 path #路径,服务器资源的本地名,由一个/将其与前面的URL组件分隔 params #参数,指定输入的参数,参数为名/值对,多个参数,用;分隔 query #查询,传递参数给程序,如数据库,用?分隔,多个查询用&分隔 frag #片段,一小片或一部分资源的名字,此组件在客户端使用,用#分隔
URL示例
http://www.ciciedu.com:8080/images/logo.jpg ftp://cici:[email protected]/pub/linux.ppt rtsp://videoserver/video_demo/ #Real Time Streaming Protocol 实时流协议 gcomm://10.0.0.8,10.0.0.18,10.0.0.28 #PXC http://www.ciciedu.com/bbs/hello;gender=f/send;type=title https://list.jd.com/list.html?cat=670,671,672&ev=14_2&sort=sort_totalsales15_desc&trans=1 http://apache.org/index.html#projects-list
网站访问量
网站访问量统计的重要指标
- IP(独立IP):即Internet Protocol,指独立IP数。一天内来自相同客户机IP地 址只计算一次,记录远程客户机IP地址的计算机访问网站的次数,是衡量网站 流量的重要指标
- PV(访问量): 即Page View,页面浏览量或点击量,用户每次刷新即被计算一 次,PV反映的是浏览某网站的页面数,PV与来访者的数量成正比,PV并不是页 面的来访者数量,而是网站被访问的页面数量
- UV(独立访客):即Unique Visitor,访问网站的一台电脑为一个访客。一天内 相同的客户端只被计算一次。可以理解成访问某网站的电脑的数量。网站判断 来访电脑的身份是通过cookies实现的。如果更换了IP后但不清除cookies,再 访问相同网站,该网站的统计中UV数是不变的
网站统计 : http://www.alexa.cn/rank/
范例:网站访问统计
1. 甲乙丙三人在同一台通过 ADSL上网的电脑上(中间没有断网),分别访问www.ciciedu.com 网站, 并且每人共用一个浏览器,各浏览了2个页面,那么网站的流量统计是: IP: 1 PV:6 UV:1 2. 若三人都是ADSL重新拨号后,各浏览了2个页面,则 IP: 3 PV:6 UV:1
网站访问量
QPS:request per second,每秒请求数
PV,QPS和并发连接数换算公式
- QPS= PV * 页面衍生连接次数/ 统计时间(86400)
- 并发连接数 =QPS * http平均响应时间
峰值时间:每天80%的访问集中在20%的时间里,这20%时间为峰值时间
峰值时间每秒请求数(QPS)=( 总PV数 *页面衍生连接次数)*80% ) / ( 每天秒数 * 20% )
1.4.5 HTTP工作机制
一次http事务包括:
- http请求:http request
- http响应:http response
Web资源 :web resource,一个网页由多个资源(文件)构成,打开一个页面, 通常会有多个资源展示出来,但是每个资源都要单独请求。因此,一个“Web页 面”通常并不是单个资源,而是一组资源的集合
资源类型 :
静态文件:无需服务端做出额外处理
文件后缀:.html, .txt, .jpg, .js, .css, .mp3, .avi
动态文件:服务端执行程序,返回执行的结果
文件后缀:.php, .jsp ,.asp
HTTP连接请求
串行和并行连接
串行,持久连接和管道
其中管道化持久连接效率最高
提高HTTP连接性能
- 并行连接:通过多条TCP连接发起并发的HTTP请求
- 持久连接:keep-alive,重用TCP连接,以消除连接和关闭的时延,以事务个数和时间来决定是否关闭连接
- 管道化连接:通过共享TCP连接,发起并发的HTTP请求
- 复用的连接:交替传送请求和响应报文(实验阶段)
1.4.6 HTTP 协议版本
http/0.9:
1991,原型版本,功能简陋,只有一个命令GET。GET /index.html,服务器只能回应HTML格式字符串,不能回应别的格式
http/1.0
1996年5月,支持cache, MIME, method
每个TCP连接只能发送一个请求,发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接
引入了POST命令和HEAD命令
头信息是 ASCII码,后面数据可为任何格式。服务器回应时会告诉客户端,数据是什么格式,即Content-Type字段的作用。这些数据类型总称为MIME 多用途互联网邮件扩展,每个值包括一级类型和二级类型,预定义的类型,也可自定义类型, 常见Content-Type值:text/xml image/jpeg audio/mp3
http/1.1
1997年1月,引入了*持久连接*(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。对于同一个域名,大多数浏览器允许同时建立6个持久连接引入了管道机制,即在同一个TCP连接里,客户端可以同时发送多个请求,进一步改进了HTTP协议的效率
新增方法:PUT、PATCH、OPTIONS、DELETE
同一个TCP连接里,所有的数据通信是按次序进行的。服务器只能顺序处理回应,前面的回应慢,会有许多请求排队,造成”队头堵塞”(Head-of-line blocking)
为避免上述问题,两种方法:一是减少请求数,二是*同时多开持久连接*。
网页优化技巧,如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等
HTTP 协议不带有状态,每次请求都必须附上所有信息。请求的很多字段都是重复的,浪费带宽,影响速度
HTTP1.0和HTTP1.1的区别
1.0版本 : 三次握手建立连接后只说了一句话就断开了
1.1版本 : 三次握手建立连接后可以进行多次交互
- 缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-NoneMatch等更多可供选择的缓存头来控制缓存策略
- 带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如:客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),方便了开发者自由的选择以便于充分利用带宽和连接
- 错误通知的管理,在HTTP1.1中新增24个状态响应码,如409(Conflict)表示请求的资源与资源当前状态冲突;410(Gone)表示服务器上的某个资源被永久性的删除
Host 头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request) - 长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,弥补了HTTP1.0每次请求都要创建连接的缺点
HTTP1.0和1.1的问题
- HTTP1.x在传输数据时,每次都需要重新建立连接,无疑增加了大量的延迟时间,特别是在移动端更为突出
- HTTP1.x在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,无法保证数据的安全性
- HTTP1.x在使用时,header里携带的内容过大,增加了传输的成本,并且每次请求header基本不怎么变化,尤其在移动端增加用户流量
- 虽然HTTP1.x支持了keep-alive,来弥补多次创建连接产生的延迟,但是keep-alive使用多了同样会给服务端带来大量的性能压力,并且对于单个文件被不断请求的服务(例如图片存放网站),keep-alive可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间
*HTTPS协议*:
为解决安全问题,网景在1994年创建了HTTPS,并应用在网景导航者浏览器中。 最初,HTTPS是与SSL一起使用的;在SSL逐渐演变到TLS时(其实两个是一个东西,只是名字不同而已),最新的HTTPS也由在2000年五月公布的RFC 2818正式确定下来。HTTPS就是安全版的HTTP,目前大型网站基本实现全站HTTPS
HTTPS特点
- HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费
- HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上 , SSL/TLS运行在TCP之上,所有传输的内容都经过加密的
- HTTP和HTTPS使用的是不同的连接方式,端口不同,前者是80,后者是443
- HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题
- HTTPS 实现过程降低用户访问速度,但经过合理优化和部署,HTTPS 对速度的影响还是可以接受的
SPDY协议
SPDY:2009年谷歌研发,综合HTTPS和HTTP两者有点于一体的传输协议,主要特点:
- 降低延迟,针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式,解决了HOL blocking的问题,降低了延迟同时提高了带宽的利用率
- 请求优先级(request prioritization)。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,重要的请求就会优先得到响应。比如浏览器加载首页,首页的html内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,可以保证用户能第一时间看到网页内容
- header压缩。HTTP1.x的header很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量
- 基于HTTPS的加密协议传输,大大提高了传输数据的可靠性
- 服务端推送(server push),采用了SPDY的网页,例如网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js 时就可以直接从缓存中获取到,不用再发请求了
HTTP2协议
http/2.0:2015年,HTTP2.0是SPDY的升级版
- 头信息和数据体都是二进制,称为头信息帧和数据帧
- 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,且不用按顺序一 一对应,避免了“队头堵塞“,此双向的实时通信称为多工(Multiplexing)
- 引入头信息压缩机制(header compression),头信息使用gzip或compress压缩后再发送;客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,不发送同样字段,只发送索引号,提高速度
- HTTP/2 允许服务器未经请求,主动向客户端发送资源,即服务器推送(server push)
HTTP2.0和SPDY区别 :
- HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
- HTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATE
1.4.7 HTTP 请求访问的完整过程
一次完整的http请求处理过程
1、建立连接:接收或拒绝连接请求
2、接收请求:接收客户端请求报文中对某资源的一次请求的过程
Web访问响应模型(Web I/O)
- 单进程I/O模型:启动一个进程处理用户请求,而且一次只处理一个,多个请求被串行响应
- 多进程I/O模型:并行启动多个进程,每个进程响应一个连接请求 (apache采用,浪费资源)
- 复用I/O结构:启动一个进程,同时响应N个连接请求
- 复用的多进程I/O模型:启动M个进程,每个进程响应N个连接请求,同时接收M*N个请求
3、处理请求:服务器对请求报文进行解析,并获取请求的资源及请求方法等相关信息,根据方法,资源,首部和可选的主体部分对请求进行处理
常用请求Method: GET、POST、HEAD、PUT、DELETE、TRACE、OPTIONS
4、访问资源:
服务器获取请求报文中请求的资源web服务器,即存放了web资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源
5、构建响应报文:
一旦Web服务器识别除了资源,就执行请求方法中描述的动作,并返回响应报文。响应报文中 包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主体
1)响应实体:如果事务处理产生了响应主体,就将内容放在响应报文中回送过去。响应报文中通常包括:
- 描述了响应主体MIME类型的Content-Type首部
- 描述了响应主体长度的Content-Length
- 实际报文的主体内容
2)URL重定向:web服务构建的响应并非客户端请求的资源,而是资源另外一个访问路径
3)MIME类型: Web服务器要负责确定响应主体的MIME类型。多种配置服务器的方法可将MIME类型与资源管理起来
- 魔法分类:Apache web服务器可以扫描每个资源的内容,并将其与一个已知模式表(被称为魔法文件)进行匹配,以决定每个文件的MIME类型。这样做可能比较慢,但很方便,尤其是文件没有标准扩展名时
- 显式分类:可以对Web服务器进行配置,使其不考虑文件的扩展名或内容,强制特定文件或目录内容拥有某个MIME类型
- 类型协商: 有些Web服务器经过配置,可以以多种文档格式来存储资源。在这种情况下,可以配置Web服务器,使其可以通过与用户的协商来决定使用哪种格式(及相关的MIME类型)"最好"
6、发送响应报文
Web服务器通过连接发送数据时也会面临与接收数据一样的问题。服务器可能有很多条到各个客户端的连接,有些是空闲的,有些在向服务器发送数据,还有一些在向客户端回送响应数据。服务器要记录连接的状态,还要特别注意对持久连接的处理。对非持久连接而言,服务器应该在发送了整条报文之后,关闭自己这一端的连接。对持久连接来说,连接可能仍保持打开状态,在这种情况下,服务器要正确地计算Content-Length首部,不然客户端就无法知道响应什么时候结束
7、记录日志
最后,当事务结束时,Web服务器会在日志文件中添加一个条目,来描述已执行的事务
2 httpd 安装和组成
http 服务基于 C/S 结构
2.1 常见http服务器程序
- httpd apache,存在C10K(10K connections)问题
- nginx 解决C10K问题
- lighttpd
- IIS .asp 应用程序服务器
- tomcat .jsp 应用程序服务器
- jetty 开源的servlet容器,基于Java的web容器
- Resin CAUCHO公司,支持servlets和jsp的引擎
- webshpere:IBM公司
- weblogic:BEA,Oracle
- jboss:RedHat,IBM
- oc4j:Oracle
HTTP服务器市场占有率统计 : http://www.netcraft.com
2.2 apache介绍和特点
2.2.1 apache 介绍
20世纪90年代初,国家超级计算机应用中心NCSA开发,1995年开源社区发布apache
apache 名字来源,流传最广的解释是(也是最显而易见的):这个名字来自于一个事实:当Apache在1995年初开发的时候,它是由当时最流行的HTTP服务器NCSA HTTPd 1.3的代码修改而成的,因此是“一个修补的(apatchy)”服务器。然而,在Apache服务器官方网站的FAQ中是这么解释的:"Apache 这个名字是为了纪念名为Apache的美洲原住民印第安人的一支,众所周知他们拥有高超的作战策略和无穷的耐性。"贝伦多夫说:"我选择阿帕奇这个名字是取其积极含义。阿帕奇族是最后一个屈服于美国政府的民族。当时我们担心大公司迟早会参与竞争并‘教化'这块最早的网络之地,所以在我看来,阿帕奇是个很好的名称,也有人说这个词一语双关-因为正如Apache(与"a patchy”谐音)的名字所表明的那样,他们确实是在给服务器打补丁。”
软件基金会
- ASF:apache software foundation
- FSF:Free Software Foundation
apache特性 :
- 高度模块化:core + modules
- DSO:Dynamic Shared Object 动态加载/卸载
- MPM:multi-processing module 多路处理模块
apache 功能 :
- 虚拟主机:IP、Port、FQDN
- CGI:Common Gateway Interface,通用网关接口
- 反向代理
- 负载均衡
- 路径别名
- 丰富的用户认证机制:basic,digest
- 支持第三方模块
httpd-2.4 新特性
- MPM支持运行为DSO机制;以模块形式按需加载
- event MPM生产环境可用
- 异步读写机制
- 支持每模块及每目录的单独日志级别定义
- 每请求相关的专用配置
- 增强版的表达式分析式
- 毫秒级持久连接时长定义
- 基于FQDN的虚拟主机不需要NameVirutalHost指令
- 新指令
- 支持用户自定义变量
- .更低的内存消耗
2.2.2 MPM multi-processing module 工作模式
prefork :多进程I/O模型,每个进程响应一个请求,CentOS 7 默认模型
一个主进程:生成和回收n个子进程,创建套接字,不响应请求
多个子进程:工作work进程,每个子进程处理一个请求;系统初始时,预先生成多个空闲进程,等待请求
Prefork MPM: 预派生模式,有一个主控制进程,然后生成多个子进程,每个子进程有一个独立的线程响应用户请求,相对比较占用内存,但是比较稳定,可以设置最大和最小进程数,是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景优点:稳定
缺点:慢,占用资源,不适用于高并发场景
worker:复用的多进程I/O模型,多进程多线程,IIS使用此模型
一个主进程:生成m个子进程,每个子进程负责生个n个线程,每个线程响应一个请求,并发响应请求:m*n
worker MPM:是一种多进程和多线程混合的模型,有一个控制进程,启动多个子进程,每个子进程里面包含固定的线程,使用线程来处理请求,当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,由于其使用了线程处理请求,因此可以承受更高的并发。
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keep-alive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用。(该问题在prefork模式下,同样会发生)
event:事件驱动模型(worker模型的变种),CentOS8 默认模型
一个主进程:生成m个子进程,每个子进程负责生个n个线程,每个线程响应一个请求,并发响应请求:m*n,有专门的监控线程来管理这些keep-alive类型的线程,当有真实请求时,将请求传递给服务线程,执行完毕后,又允许释放。这样增强了高并发场景下的请求处理能力uevent MPM:Apache中最新的模式,属于事件驱动模型(epoll),每个进程响应多个请求,在现在版本里的已经是稳定可用的模式。它和worker模式很像,最大的区别在于,它解决了keep-alive场景下,长期被占用的线程的资源浪费问题(某些线程因为被keep-alive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)。event MPM中,会有一个专门的线程来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力
event只在有数据发送的时候才开始建立连接,连接请求才会触发工作线程,即使用了TCP的一个选项,叫做延迟接受连接TCP_DEFER_ACCEPT,加了这个选项后,若客户端只进行TCP连接,不发送请求,则不会触发Accept操作,也就不会触发工作线程去干活,进行了简单的防攻击(TCP连接)
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
缺点:没有线程安全控制
httpd-2.4:event 稳定版,centos7 以后默认
httpd-2.2:event 测试版,centos6 默认
2.3 Httpd 安装和相关文件
2.3.1 rpm包安装httpd并启动httpd服务
版本说明:CentOS 7 以上,默认系统是httpd 2.4,CentOS 6 版默认为httpd 2.2
安装方式 :
- rpm:centos发行版,稳定,建议使用
- 编译:定制或特殊需求
范例:安装httpd 2.4
[root@centos8 ~]#yum install -y httpd Last metadata expiration check: 0:21:54 ago on Tue 23 Jun 2020 09:25:23 AM CST. Dependencies resolved. =========================================================================================================== Package Architecture Version Repository Size =========================================================================================================== Installing: httpd x86_64 2.4.37-16.module_el8.1.0+256+ae790463 AppStream 1.7 M Installing dependencies: mailcap noarch 2.1.48-3.el8 base 39 k apr x86_64 1.6.3-9.el8 AppStream 125 k apr-util x86_64 1.6.1-6.el8 AppStream 105 k centos-logos-httpd noarch 80.5-2.el8 AppStream 24 k ...省略... Install 10 Packages Total download size: 2.3 M Installed size: 6.6 M Downloading Packages: Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 Installing : apr-1.6.3-9.el8.x86_64 1/9 Running scriptlet: apr-1.6.3-9.el8.x86_64 1/9 ...省略... Complete! [root@centos8 ~]#systemctl start httpd [root@centos8 ~]#ss -ntl |grep :80 State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:80 0.0.0.0:* [root@centos8 ~]#lsof -i :80 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME httpd 4666 root 3u IPv4 42696 0t0 TCP *:http (LISTEN) httpd 4669 apache 3u IPv4 42696 0t0 TCP *:http (LISTEN) httpd 4670 apache 3u IPv4 42696 0t0 TCP *:http (LISTEN) httpd 4671 apache 3u IPv4 42696 0t0 TCP *:http (LISTEN) httpd 4884 apache 3u IPv4 42696 0t0 TCP *:http (LISTEN) [root@centos8 ~]#rpm -qf /var/www/html/ httpd-filesystem-2.4.37-16.module_el8.1.0+256+ae790463.noarch
2.3.2 httpd-2.4 相关文件
配置文件:
- /etc/httpd/conf/httpd.conf 主配置文件
- /etc/httpd/conf.d/*.conf 子配置文件
- etc/httpd/conf.d/conf.modules.d 模块加载的配置文件
检查配置语法:httpd –t
服务单元文件:
- /usr/lib/systemd/system/httpd.service
- 配置文件:/etc/sysconfig/httpd
服务控制和启动
- systemctl enable|disable httpd.service
- systemctl {start|stop|restart|status|reload} httpd.service
- apachectl start|stop|restart|configtest
站点网页文档根目录:/var/www/html
模块文件路径:
- /etc/httpd/modules
- /usr/lib64/httpd/modules
主服务器程序文件: /usr/sbin/httpd
主进程文件: /etc/httpd/run/httpd.pid
日志文件目录:/var/log/httpd
- access_log: 访问日志
- error_log:错误日志
帮助文档包:httpd-manual
http://10.0.0.8/manual/
2.3.3 httpd 配置文件的组成
主要组成
- Global Environment
- Main server configuration
- virtual host
配置文件格式:
directive value
格式说明:
- directive 不区分字符大小写
- value 为路径时,是否区分大小写,取决于文件系统
配置文件语法检查:
apachectl configtest httpd -t
配置官方帮助: http://httpd.apache.org/docs/2.4/
范例:CentOS 8.0 默认配置文件
[root@centos8 ~]#cp /etc/httpd/conf/httpd.conf{,.bak} #先做备份,免得重装系统 [root@centos8 ~]#grep -Ev '^ *#|^$' /etc/httpd/conf/httpd.conf ServerRoot "/etc/httpd" Listen 80 Include conf.modules.d/*.conf User apache Group apache ServerAdmin root@localhost <Directory /> AllowOverride none Require all denied </Directory> DocumentRoot "/var/www/html" <Directory "/var/www"> AllowOverride None Require all granted </Directory> <Directory "/var/www/html"> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> <IfModule dir_module> DirectoryIndex haha.html index.html #网站主页面,可以有备用的,修改后建议用systemctl reload httpd ,不会停止进程 </IfModule> <Files ".ht*"> Require all denied </Files> ErrorLog "logs/error_log" LogLevel warn <IfModule log_config_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common <IfModule logio_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </IfModule> CustomLog "logs/access_log" combined </IfModule> <IfModule alias_module> ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" </IfModule> <Directory "/var/www/cgi-bin"> AllowOverride None Options None Require all granted </Directory> <IfModule mime_module> TypesConfig /etc/mime.types AddType application/x-compress .Z AddType application/x-gzip .gz .tgz AddType text/html .shtml AddOutputFilter INCLUDES .shtml </IfModule> AddDefaultCharset UTF-8 <IfModule mime_magic_module> MIMEMagicFile conf/magic </IfModule> EnableSendfile on IncludeOptional conf.d/*.conf
2.3.4 编译安装httpd 2.4
编译说明和准备
APR:Apache portable Run-time libraries,Apache可移植运行库,主要为上层的应用程序提供一个可以跨越多操作系统平台使用的底层支持接口库。在早期的Apache版本中,应用程序本身必须能够处理各种具体操作系统平台的细节,并针对不同的平台调用不同的处理函数随着Apache的进一步开发,Apache组织决定将这些通用的函数独立出来并发展成为一个新的项目。这样,APR的开发就从Apache 中独立出来,Apache仅仅是使用 APR而已。目前APR主要还是由Apache使用,由于APR的较好的移植性,因此一些需要进行移植的C程序也开始使用APR,开源项目:比如用于服务器压力测试的Flood loader tester,项目站点:http://httpd.apache.org/test/flood
APR官网:http://apr.apache.org
说明:安装httpd-2.4,依赖于apr-1.4+, apr-util-1.4+
编译安装httpd-2.4准备
#安装相关包: [root@centos7 ~]#yum -y install gcc make pcre-devel openssl-devel expat-devel #下载源代码并解压缩: [root@centos7 ~]#wget https://downloads.apache.org//apr/apr-1.7.0.tar.bz2 [root@centos7 ~]#wget https://downloads.apache.org//apr/apr-util-1.6.1.tar.bz2 [root@centos7 ~]#wget https://downloads.apache.org//httpd/httpd-2.4.43.tar.bz2 [root@centos7 ~]#ls httpd-2.4.43.tar.bz2,apr-1.7.0.tar.bz2,apr-util-1.6.1.tar.bz2 [root@centos7 ~]#tar xvf apr-1.7.0.tar.bz2 [root@centos7 ~]#tar xvf apr-util-1.6.1.tar.bz2 [root@centos7 ~]#tar xvf httpd-2.4.43.tar.bz2
编译安装httpd-2.4 方法一
编译安装apr
cd apr-1.7.0 ./configure --prefix=/app/apr make && make install
编译安装apr-util
cd ./apr-util-1.6.1 ./configure --prefix=/app/apr-util --with-apr=/app/apr/ make -j 2 && make install
编译安装 httpd-2.4
cd ../httpd-2.4.41 ./configure --prefix=/app/httpd24 \ --enable-so \ --enable-ssl \ --enable-cgi \ --enable-rewrite \ --with-zlib \ --with-pcre \ --with-apr=/app/apr/ \ --with-apr-util=/app/apr-util/ \ --enable-modules=most \ --enable-mpms-shared=all \ --with-mpm=prefork #当前mpm设置为prefork模型 make -j 4 && make install
编译安装httpd-2.4方法二
将apr 和apr-util源码与httpd 源码合并
mv apr-1.7.0 httpd-2.4.41/srclib/apr mv apr-util-1.6.1 httpd-2.4.41/srclib/apr-util ls httpd-2.4.41/srclib/ apr apr-util Makefile.in
将三者一并编译并安装
cd httpd-2.4.41/ ./configure \ --prefix=/app/httpd24 \ --enable-so \ --enable-ssl \ --enable-cgi \ --enable-rewrite \ --with-zlib \ --with-pcre \ --with-included-apr \ --enable-modules=most \ #大部分模块都加进去 --enable-mpms-shared=all \ #启用mpms多功能处理模块 --with-mpm=prefork #当前mpm设置为prefork模型 make -j 4 && make install
编译安装后配置
Httpd编译过程:/app/httpd24/build/config.nice
自带的服务控制脚本:/app/httpd24/bin/apachectl
创建专用用户
useradd -s /sbin/nologin -r apache
指定运行httpd的用户
vim /app/httpd24/conf/httpd.conf user apache group apache
配置环境变量
方法一: vim /etc/profile.d/httpd24.sh PATH=/app/httpd24/bin:$PATH 方法二: ln -s /app/httpd24/bin/* /usr/bin/
配置帮助
vim /etc/man_db.conf MANDATORY_MANPATH /app/httpd24/man #默认没有man帮助 [root@Centos7 ~]#man httpd No manual entry for httpd #下面是httpd的man路径 [root@Centos7 ~]#ls /app/httpd24/ bin build cgi-bin conf error htdocs icons include lib logs man manual modules [root@Centos7 ~]#ls /app/httpd24/man man1 man8 #修改man帮助配置文件 [root@Centos7 ~]#vim /etc/man_db.conf MANDATORY_MANPATH /app/httpd24/man #加入这一行 #重新加载 [root@Centos7 ~]#mandb
设置开机自动启动
vim /etc/rc.d/rc.local /app/httpd24/bin/apachectl start chmod +x /etc/rc.d/rc.local
创建service unit文件(CentOS 7 以上版本)
vim /usr/lib/systemd/system/httpd24.service [Unit] Description=The Apache HTTP Server After=network.target remote-fs.target nss-lookup.target Documentation=man:httpd(8) Documentation=man:apachectl(8) [Service] Type=forking #EnvironmentFile=/etc/sysconfig/httpd ExecStart=/app/httpd24/bin/apachectl start #ExecStart=/app/httpd24/bin/httpd $OPTIONS -k start ExecReload=/app/httpd24/bin/apachectl graceful #ExecReload=/app/httpd24/bin/httpd $OPTIONS -k graceful ExecStop=/app/httpd24/bin/apachectl stop KillSignal=SIGCONT PrivateTmp=true [Install] WantedBy=multi-user.target #重新加载 [root@Centos7 ~]#systemctl daemon-reload [root@Centos7 ~]#systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled) Active: inactive (dead) Docs: man:httpd(8) man:apachectl(8)
实验:设置页面
[root@Centos7 ~]#cd /app/httpd24/htdocs/
[root@Centos7 htdocs]#ls
index.html
[root@Centos7 htdocs]#cat index.html
<html><body><h1>It works!</h1></body></html>
[root@Centos7 htdocs]#mkdir /data/www/
[root@Centos7 htdocs]#vim /app/httpd24/conf/httpd.conf
DocumentRoot "/data/www"
<directory /data/www>
require all granted
</directory>
[root@Centos7 htdocs]#httpd -t
Syntax OK
[root@Centos7 htdocs]#systemctl reload httpd
[root@Centos7 htdocs]#echo /data/www/ > /data/www/index.html
效果如下图:
创建启动脚本(CentOS 6 以前版本)
#自定义启动脚本(参考httpd-2.2的服务脚本) cp /etc/rc.d/init.d/httpd /etc/rc.d/init.d/httpd24 vim /etc/rc.d/init.d/httpd24 apachectl=/app/httpd24/bin/apachectl httpd=${HTTPD-/app/httpd24/bin/httpd} pidfile=${PIDFILE-/app/httpd24/logs/httpd.pid} lockfile=${LOCKFILE-/var/lock/subsys/httpd24} chkconfig –add httpd24 chkconfig –list httpd24
3 httpd 常见配置
3.1 指定服务器名
[root@centos8 ~]#httpd -t AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using centos8.localdomain. Set the 'ServerName' directive globally to suppress this message Syntax OK [root@centos8 ~]#vim /etc/httpd/conf/httpd.conf #ServerName www.example.com:80 servername www.ciciedu.org [root@centos8 ~]#httpd -t Syntax OK
3.2 显示服务器版本信息
ServerTokens Major|Minor|Min[imal]|Prod[uctOnly]|OS|Full
范例:
ServerTokens Prod[uctOnly] :Server: Apache ServerTokens Major: Server: Apache/2 ServerTokens Minor: Server: Apache/2.0 ServerTokens Min[imal]: Server: Apache/2.0.41 ServerTokens OS: Server: Apache/2.0.41 (Unix) ServerTokens Full (or not specified): Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2
建议使用:ServerTokens Prod
#默认效果 [root@Centos7 htdocs]#curl -I http://10.0.0.17 HTTP/1.1 200 OK Date: Tue, 23 Jun 2020 12:08:06 GMT Server: Apache/2.4.43 (Unix) Last-Modified: Tue, 23 Jun 2020 09:45:00 GMT ETag: "b-5a8bd367e085a" Accept-Ranges: bytes Content-Length: 11 Content-Type: text/html [root@Centos7 ~]#cd /app/httpd24/conf/ [root@Centos7 conf]#ls extra httpd.conf magic mime.types original [root@Centos7 conf]#vim httpd.conf #尽可能不改主配置文件 Include conf.d/*.conf [root@Centos7 conf]#cd .. [root@Centos7 httpd24]#ls bin cgi-bin error icons lib man modules build conf htdocs include logs manual [root@Centos7 httpd24]#mkdir conf.d [root@Centos7 httpd24]#vim conf.d/test.conf [root@Centos7 httpd24]#httpd -t Syntax OK [root@Centos7 httpd24]#systemctl reload httpd [root@Centos7 httpd24]#curl -I http://10.0.0.17 HTTP/1.1 200 OK Date: Tue, 23 Jun 2020 12:15:17 GMT Server: Apache Last-Modified: Tue, 23 Jun 2020 09:45:00 GMT ETag: "b-5a8bd367e085a" Accept-Ranges: bytes Content-Length: 11 Content-Type: text/html
3.2 包含其它配置文件
指令:
Include file-path|directory-path|wildcard IncludeOptional file-path|directory-path|wildcard
说明:
- Include和IncludeOptional功能相同,都可以包括其它配置文件
- 但是当无匹配文件时,include会报错,IncludeOptional会忽略错误
范例:
#Wildcards may be included in the directory or file portion of the path. This example will fail if there is no subdirectory in conf/vhosts that contains at least one *.conf file: Include conf/vhosts/*/*.conf #Alternatively, the following command will just be ignored in case of missing files or directories: IncludeOptional conf/vhosts/*/*.conf
3.3 监听的IP和Port
Listen [IP:]PORT
说明:
(1) 省略IP表示为本机所有IP
(2) Listen指令至少一个,可重复出现多次
范例:
vim /app/httpd24/httpd.conf Listen 192.168.1.100:8080 #此ip只能通过8080端口访问 Lsten 80
3.4 持久连接
Persistent Connection:连接建立,每个资源获取完成后不会断开连接,而是继续等待其它的请求完成,默认开启持久连接
断开条件:
时间限制:以秒为单位, 默认5s,httpd-2.4 支持毫秒级 请求数量: 请求数达到指定值,也会断开
副作用:对并发访问量大的服务器,持久连接会使有些请求得不到响应
折衷:使用较短的持久连接时间
持久连接相关指令:
KeepAlive On|Off KeepAliveTimeout 15 #连接持续15s,可以以ms为单位,默认值为5s MaxKeepAliveRequests 500 #持久连接最大接收的请求数,默认值100
测试方法:
telnet WEB_SERVER_IP PORT GET /URL HTTP/1.1 Host: WEB_SERVER_IP
3.5 DSO (Dynamic Shared Object)
*Dynamic Shared Object*,加载动态模块配置,不需重启即生效
动态模块所在路径: usr/lib64/httpd/modules
主配置 /etc/httpd/conf/httpd.conf 文件中指定加载模块配置文件
ServerRoot "/etc/httpd"
Include conf.modules.d/*.conf
配置指定实现模块加载格式:
LoadModule <mod_name> <mod_path>
模块文件路径可使用相对路径:相对于ServerRoot(默认/etc/httpd)
范例:查看模块加载的配置文件
[root@centos8 ~]#ls /etc/httpd/conf.modules.d/ 00-base.conf 00-lua.conf 00-optional.conf 00-systemd.conf 10-h2.conf README 00-dav.conf 00-mpm.conf 00-proxy.conf 01-cgi.conf 10-proxy_h2.conf [root@centos8 ~]#cat /etc/httpd/conf.modules.d/00-base.conf # # This file loads most of the modules included with the Apache HTTP # Server itself. # LoadModule access_compat_module modules/mod_access_compat.so LoadModule actions_module modules/mod_actions.so LoadModule alias_module modules/mod_alias.so LoadModule allowmethods_module modules/mod_allowmethods.so LoadModule auth_basic_module modules/mod_auth_basic.so ...省略...
查看静态编译的模块 :httpd -l
查看静态编译及动态装载的模块 :httpd –M
范例:
#列出静态编译模块 [root@centos8 ~]#httpd -l Compiled in modules: core.c mod_so.c http_core.c #列出静态和动态编译的模块 [root@centos8 ~]#httpd -M AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using centos8.localdomain. Set the 'ServerName' directive globally to suppress this message Loaded Modules: core_module (static) so_module (static) http_module (static) access_compat_module (shared) actions_module (shared) alias_module (shared) allowmethods_module (shared) auth_basic_module (shared) ...省略...
3.6 MPM (Multi-Processing Module) 多路处理模块
httpd 支持三种MPM工作模式:prefork, worker, event
切换使用的MPM:
#启用要启用的MPM相关的LoadModule指令即可,其它未启用的两项需要在行首加#注释 vim /etc/httpd/conf.modules.d/00-mpm.conf #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so #LoadModule mpm_worker_module modules/mod_mpm_worker.so LoadModule mpm_event_module modules/mod_mpm_event.so
注意:不要同时启用多个MPM模块,否则会出现以下错误
AH00534: httpd: Configuration error: More than one MPM loaded.
范例:查看CentOS 8 和 CentOS 7 默认的MPM工作模式
#查看CentOS 8 默认的MPM工作模式 [root@centos8 ~]#httpd -M |grep mpm AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using centos8.localdomain. Set the 'ServerName' directive globally to suppress this message mpm_event_module (shared) #查看CentOS 7 默认的MPM工作模式 [root@centos7 ~]#httpd -M |grep mpm AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using centos7.localdomain. Set the 'ServerName' directive globally to suppress this message mpm_prefork_module (shared)
范例:修改CentOS 8使用 prefork 模型
[root@centos8 ~]#vim /etc/httpd/conf.modules.d/00-mpm.conf [root@centos8 ~]#grep Load /etc/httpd/conf.modules.d/00-mpm.conf # one of the following LoadModule lines. See the httpd.conf(5) man LoadModule mpm_prefork_module modules/mod_mpm_prefork.so #LoadModule mpm_worker_module modules/mod_mpm_worker.so #LoadModule mpm_event_module modules/mod_mpm_event.so [root@centos8 ~]#httpd -M | grep mpm AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using centos8.localdomain. Set the 'ServerName' directive globally to suppress this message mpm_prefork_module (shared)
3.7 prefork 模式相关的配置:
StartServers 2000 MinSpareServers 1000 #最少空闲进程数 MaxSpareServers 3000 #最多空闲进程数 ServerLimit 2560 #最多进程数,最大值 20000 MaxRequestWorkers 2560 #最大的并发连接数,默认256 MaxConnectionsPerChild 4000 #子进程最多能处理的请求数量。在处理MaxRequestsPerChild 个请求之后,子进程将会被父进程终止,这时候子进程占用的内存就会释放(为0时永远不释放) MaxRequestsPerChild 4000 #从 httpd.2.3.9开始被MaxConnectionsPerChild代替
实验:
[root@Centos7 httpd24]#cat conf.d/test.conf ServerTokens Prod StartServers 100 MinSpareServers 80 MaxSpareServers 90 ServerLimit 2560 MaxRequestWorkers 2560 [root@Centos7 httpd24]#ps aux | grep httpd |wc -l 92 #其中有两个root
3.8 worker和event 模式相关的配置
ServerLimit 16 #最多开启worker进程的数量Upper limit on configurable number of processes StartServers 10 #开启的进程数 Number of child server processes created at startup MaxRequestWorkers 150 # 最大处理连接数量 Maximum number of connections that will be processed simultaneously MinSpareThreads 25 #最少空闲线程 MaxSpareThreads 75 #最多空闲线程 ThreadsPerChild 25 #每个进程里的线程数 Number of threads created by each child process
3.9 定义Main server的文档页面路径
DocumentRoot "/path" <directory /path> Require all granted #必须授权 </directory>
说明:
- DocumentRoot指向的路径为URL路径的起始位置
- /path 必须显式授权后才可以访问
范例:
DocumentRoot "/data/html"
<directory /data/html>
Require all granted
</directory>
http://host:port/test/index.html –> /data/html/test/index.html
3.10 定义站点主页面
DirectoryIndex index.php index.html
3.11 可实现访问控制的资源
可以针对文件系统和URI的资源进行访问控制
说明: 所谓文件系统是指一个目录能不能访问 ,URI是统一资源标识,分为URN和URL,通常我们指的是URL(统一资源定位服务)
文件系统路径:
#基于目录 <Directory “/path"> ... </Directory> #基于文件 <File “/path/file”> ... </File> #基于文件通配符 <File “/path/*file*”> ... </File> #基于扩展正则表达式 <FileMatch “regex”> ... </FileMatch>
范例:
#.+表示一个字符以上 \.表示对.转义 |表示或 e?表示e可有可无 匹配文件名事宜图片为后缀 <FilesMatch ".+\.(gif|jpe?g|png)$"> # ... #此处可以填是否允许访问 </FilesMatch> <Files ".ht*"> #通配符,表示.ht开头 Require all denied </Files>
URL路径:
<Location "URL"> ... </Location> <LocationMatch "regex"> #location的正则表达式 ... </LocationMatch>
范例:
#/private1, /private1/,/private1/file.txt 匹配 #/private1other 不匹配 <Location "/private1"> # ... </Location> #/private2/,/private2/file.txt 匹配 #/private2,/private2other 不匹配 <Location "/private2/"> # ... </Location>
范例:
<Location /status>
<LocationMatch "/(extra|special)/data">
3.12 针对目录和URL实现访问控制
(1) Options指令:
后跟1个或多个以空白字符分隔的选项列表, 在选项前的+,-表示增加或删除指定选项
常见选项:
- Indexes:指明的URL路径下不存在与定义的主页面资源相符的资源文件时,返回索引列表给用户
- FollowSymLinks:允许访问符号链接文件所指向的源文件
- None:全部禁用
- All: 全部允许
范例:
<Directory /web/docs> Options -Indexes -FollowSymLinks </Directory> <Directory /web/docs/spec> Options -FollowSymLinks </Directory>
范例:
[root@centos8 ~]#cd /etc/httpd/conf.d/ [root@centos8 conf.d]#mv welcome.conf{,.bak} #欢迎页面挪走后,将显示默认的文件列表 [root@centos8 conf.d]#cd /var/www/html/ [root@centos8 html]#cp /etc/fstab f1.txt [root@centos8 html]#mkdir dir1 [root@centos8 html]#ln -s /etc/ etclink [root@centos8 html]#ll total 4 drwxr-xr-x 2 root root 6 Jun 25 10:50 dir1 lrwxrwxrwx 1 root root 5 Jun 25 10:51 etclink -> /etc/ -rw-r--r-- 1 root root 709 Jun 25 10:50 f1.txt [root@centos8 ~]#systemctl restart httpd
打开浏览器,访问 http://httpd主机ip/ 可看到下面所示
[root@centos8 ~]#vim /etc/httpd/conf/httpd.conf #Options Indexes FollowSymLinks Options Indexes #将上面行加注释,修改为此行 [root@centos8 ~]#systemctl restart httpd
打开浏览器,访问 http://httpd主机ip/ 可看到下面所示,无法看软链接目录datalink
把Options Indexes这一行删除,则会有下面提示
(2) AllowOverride指令
与访问控制相关的哪些指令可以放在指定目录下的.htaccess(由AccessFileName 指令指定,AccessFileName .htaccess 为默认值)文件中,覆盖之前的配置指令,只对语句有效
常见用法:
- AllowOverride All: .htaccess中所有指令都有效
- AllowOverride None: .htaccess 文件无效,此为httpd 2.3.9以后版的默认值
- AllowOverride AuthConfig .htaccess 文件中,除了AuthConfig 其它指令都无法生效
范例:
vim /etc/httpd/conf/httpd.conf #Options Indexes FollowSymLinks Options Indexes #AllowOverride None AllowOverride options=FollowSymLinks,indexes #注释上一行,修改为此行 [root@centos8 ~]#vim /var/www/html/dir1/.htaccess Options FollowSymLinks indexes #加此行 [root@centos8 ~]#cd /var/www/html/dir1/ [root@centos8 dir1]#cp /etc/fstab f2.txt [root@centos8 dir1]#mkdir dir2 [root@centos8 dir1]#ln -s /tmp tmplink [root@centos8 dir1]#ll total 4 drwxr-xr-x 2 root root 6 Jun 25 11:00 dir2 -rw-r--r-- 1 root root 709 Jun 25 11:00 f2.txt lrwxrwxrwx 1 root root 4 Jun 25 11:00 tmplink -> /tmp [root@centos8 dir1]#pwd /var/www/html/dir1 [root@centos8 ~]#systemctl restart httpd
打开浏览器,访问 http://httpd主机ip/dir1 ,可以看到tmplink的软链接
打开浏览器,访问 http://httpd主机ip/
可看到下面所示,无法看软链接目录datalink
范例:.htaccess文件默认被禁止访问
[root@centos7 test2]#grep -Ev '^ *#|^$' /app/httpd24/conf/httpd.conf |grep -A 2 'ht\*' <Files ".ht*"> Require all denied </Files>
3.13 基于客户端 IP 地址实现访问控制
针对各种资源,可以基于以下两种方式的访问控制:
- 客户端来源地址
- 用户账号
基于客户端的IP地址的访问控制:
- 无明确授权的目录,默认拒绝
- 允许所有主机访问:Require all granted
- 拒绝所有主机访问:Require all denied
控制特定的IP访问:
Require ip IPADDR:授权指定来源的IP访问
Require not ip IPADDR:拒绝特定的IP访问
控制特定的主机访问:
Require host HOSTNAME:授权特定主机访问
Require not host HOSTNAME:拒绝
- HOSTNAME:
- FQDN:特定主机
- domin.tld:指定域名下的所有主机
- HOSTNAME:
不能有失败,至少有一个成功匹配才成功,即失败优先
<RequireAll> Require all granted Require not ip 172.16.1.1 #拒绝特定IP </RequireAll>
多个语句有一个成功,则成功,即成功优先
<RequireAny> Require all denied require ip 172.16.1.1 #允许特定IP </RequireAny>
提示:早期版本使用 mod_access_compat 模块提供的 Allow,Deny,Order指令,将被废弃,不推荐使用
http://httpd.apache.org/docs/2.4/mod/mod_access_compat.html
Available in Apache HTTP Server 2.3 as a compatibility module with previous versions of Apache httpd 2.x. The directives provided by this module have been deprecated by the new authz refactoring. Please see mod_authz_host
The Allow , Deny , and Order directives, provided by mod_access_compat , are deprecated and will go away in a future version. You should avoid using them, and avoid outdated tutorials recommending their use.
范例:
<directory /var/www/html/dir> <requireany> require all denied Require ip 10.0.0.0/24 </requireany> </directory>
3.14 日志设定
httpd有两种日志类型
- 访问日志
- 错误日志
3.14.1 错误日志
LogLevel warn #LogLevel 可选值: debug, info, notice, warn,error, crit, alert,emerg ErrorLog logs/error_log #相对路径,相对于/etc/httpd,配置文件里有一行ServerRoot
3.14.2 访问日志
定义日志格式
LogFormat format nickname
使用日志格式
CustomLog file nickname
范例
LogFormat "%h %l %u %{%F %T}t "%r" %>s %b "%{Referer}i"\"%{User-Agent}i\"" testlog
参考帮助:http://httpd.apache.org/docs/2.4/mod/mod_log_config.html#formats
%h #客户端IP地址 %l #远程用户,启用mod_ident才有效,通常为减号"-” %u #验证(basic,digest)远程用户,非登录访问时,为一个减号"-” %t #服务器收到请求时的时间 %r #First line of request,即表示请求报文的首行;记录了此次请求的"方法”,"URL”以及协议版本 %>s #响应状态码 %b #响应报文的大小,单位是字节;不包括响应报文http首部 %{Referer}i #请求报文中首部"referer”的值;即从哪个页面中的超链接跳转至当前页面的 %{User-Agent}i #请求报文中首部"User-Agent”的值;即发出请求的应用程序 %{VARNAME}i #The contents of VARNAME: header line(s) in the request sent to the server
范例: 通过自定义访问日志格式,实现自定义时间格式
[root@centos8 ~]#vim /etc/httpd/conf/httpd.conf logFormat "%h \"%{%F %T}t\" %>s %{User-Agent}i" testlog CustomLog "logs/access_log" testlog [root@centos8 ~]#tail -f /var/log/httpd/access_log 10.0.0.7 "2020-06-24 10:26:51" 200 curl/7.29.0
实验:查看报文头部
#模仿chrome浏览器对163进行访问,查看报文头部 [root@Centos7 ~]#curl -A chrome -I http://www.163.com HTTP/1.1 200 OK Date: Thu, 25 Jun 2020 06:12:01 GMT Content-Type: text/html; charset=GBK Connection: keep-alive Expires: Thu, 25 Jun 2020 06:13:15 GMT Server: nginx Vary: Accept-Encoding Cache-Control: no-cache,no-store,private X-Cache-Spec: Yes X-Via: 1.1 PS-CZX-0165159:5 (Cdn Cache Server V2.0), 1.1 PSsdzbwt5he22:2 (Cdn Cache Server V2.0), 1.1 tjtg129:2 (Cdn Cache Server V2.0) X-Ws-Request-Id: 5ef44030_tjtg129_31362-51585
3.15 设定默认字符集
设定字符集指令
AddDefaultCharset UTF-8 #此为默认值
中文字符集:GBK, GB2312, GB18030
3.16 定义路径别名
格式:
Alias /URL/ "/PATH/"
范例:
DocumentRoot "/www/htdocs" #http://www.ciciedu.com/download/bash.rpm ==>/www/htdocs/download/bash.rpm Alias /download/ "/rpms/pub/" #http://www.ciciedu.com/download/bash.rpm ==>/rpms/pub/bash.rpm #http://www.ciciedu.com/images/logo.png ==>/www/htdocs/images/logo.png
范例:
[root@centos8 html]#mkdir /data/newsdir
[root@centos8 html]#echo /data/newsdir/index.html > /data/newsdir/index.html
[root@centos8 ~]#cat /etc/httpd/conf.d/test.conf
alias /news /data/html/newsdir/
<directory /data/html/newsdir>
require all granted
</directory>
效果如下图:
3.17 基于用户的访问控制
认证质询:WWW-Authenticate,响应码为401,拒绝客户端请求,并说明要求客户端需要提供账号和密码
认证:Authorization,客户端用户填入账号和密码后再次发送请求报文;认证通过时,则服务器发送响应的资源
认证方式两种:
- basic:明文
- digest:消息摘要认证,兼容性差
安全域:需要用户认证后方能访问的路径;应该通过名称对其进行标识,以便于告知用户认证的原因
用户的账号和密码
虚拟账号:仅用于访问某服务时用到的认证标识
存储:文本文件,SQL数据库,ldap目录存储,nis等
basic认证配置示例:
(1) 定义安全域
<Directory "/path"> Options None AllowOverride None AuthType Basic AuthName "String" AuthUserFile "/PATH/HTTPD_USER_PASSWD_FILE" Require user username1 username2 ... </Directory>
允许账号文件中的所有用户登录访问:
Require valid-user
(2) 提供账号和密码存储(文本文件)
使用专用命令完成此类文件的创建及用户管理
htpasswd [options] /PATH/HTTPD_PASSWD_FILE username #apache用户需要有read权限 setfacl -m u:apache:r /PATH/HTTPD_PASSWD_FILE
选项:
-c 自动创建文件,仅应该在文件不存在时使用 -p 明文密码 -d CRYPT格式加密,默认 -m md5格式加密 -s sha格式加密 -D 删除指定用户 htpasswd -b .passwd Jack 123456 去掉 -c 选项,即可在第一个用户之后添加第二个用户,依此类推。 利用 htpasswd 命令修改密码 htpasswd -D .passwd Jack # 删除用户 htpasswd -b .passwd Jack 123456
基于组账号进行认证
(1) 定义安全域
<Directory "/path"> AuthType Basic AuthName "String" AuthUserFile "/PATH/HTTPD_USER_PASSWD_FILE" AuthGroupFile "/PATH/HTTPD_GROUP_FILE" Require group grpname1 grpname2 ... </Directory>
范例:方法1
[root@centos8 html]#mkdir admin [root@centos8 html]#echo /var/www/html/admin/index.html > admin/index.html [root@centos8 ~]#cat /etc/httpd/conf.d/test.conf <directory /var/www/html/admin> AuthType Basic AuthName "Please input valid user and password" AuthUserFile "/etc/httpd/conf.d/.httpuser" #Require user xiaoming xiaohong #指定用户才可以访问 require valid-user </directory> [root@centos8 ~]#htpasswd -c /etc/httpd/conf.d/.httpuser xiaoming [root@centos8 ~]#htpasswd -c /etc/httpd/conf.d/.httpuser xiaohong [root@centos8 ~]#cd /etc/httpd/conf.d [root@centos8 conf.d]#cat .httpduser xiaoming:$apr1$4m8msymf$Fa.r4sSRz/nIhpZzxRx3J. xiaohong:$apr1$pPruVR2y$yKuN.TkgMy2.tTAoc2YBA1 [root@centos8 conf.d]#pwd /etc/httpd/conf.d [root@centos8 conf.d]#ll -a total 24 drwxr-xr-x 2 root root 121 Jun 25 14:57 . drwxr-xr-x 5 root root 105 Jun 25 10:45 .. -rw-r--r-- 1 root root 2926 Dec 24 2019 autoindex.conf -rw-r--r-- 1 root root 236 Jun 25 14:59 .httpduser -rw-r--r-- 1 root root 400 Dec 24 2019 README -rw-r--r-- 1 root root 198 Jun 25 14:34 test.conf -rw-r--r-- 1 root root 1252 Dec 24 2019 userdir.conf -rw-r--r-- 1 root root 738 Dec 24 2019 welcome.conf.bak [root@centos8 conf.d]#chmod 600 .httpduser [root@centos8 conf.d]#ll .httpduser -rw------- 1 root root 236 Jun 25 14:59 .httpduser [root@centos8 ~]#systemctl reload httpd
浏览器访问 http://httpd服务器/admin 可以看到以下显示
#apache用户需要有读权限 setfacl -m u:apache:r /etc/httpd/conf.d/.httpduser
使用wireshark 抓包软件,可以看到明文密码
查看访问日志文件/var/logs/httpd/access_log,可以观察到以下内容
[root@centos8 html]#tail -f /var/log/httpd/access_log 10.0.0.1 xiaoming "2020-06-25 15:36:18" 301 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36 10.0.0.1 xiaoming "2020-06-25 15:36:18" 200 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36
范例:方法2
[root@centos8 ~]#mkdir /var/www/html/secret [root@centos8 ~]#echo /var/www/html/secret/index.html > /var/www/html/secret/index.html [root@centos8 ~]#cd /var/www/html/secret/ [root@centos8 secret]#ls index.html [root@centos8 secret]#vim .htaccess [root@centos8 ~]#cat /var/www/html/secret/.htaccess AuthType Basic AuthName "FBI warning" AuthUserFile "/etc/httpd/conf.d/.httpuser" Require user xiaoming [root@centos8 ~]#vim /etc/httpd/conf.d/test.conf [root@centos8 ~]#cat /etc/httpd/conf.d/test.conf <directory /var/www/html/admin> AuthType Basic AuthName "FBI warning" AuthUserFile "/etc/httpd/conf.d/.httpuser" #Require user xiaoming xiaohong require valid-user </directory> <directory /var/www/html/secret> allowoverride authconfig </directory> [root@centos8 ~]#systemctl reload httpd
(2) 创建用户账号和组账号文件
组文件:每一行定义一个组
GRP_NAME: username1 username2 ...
范例:
<Directory "/www/htdocs/admin"> Options None AllowOverride None AuthType Basic AuthName "Administator private" AuthUserFile "/etc/httpd/conf.d/.htpasswd" AuthGroupFile "/etc/httpd/conf.d/.htgroup" Require group webadmins </Directory> vim /etc/httpd/conf.d/.htgroup webadmins:wang cici
范例:
[root@centos8 ~]#cat /var/www/html/secret/.htaccess AuthType Basic AuthName "FBI warning" AuthUserFile "/etc/httpd/conf.d/.httpuser" AuthGroupFile "/etc/httpd/conf.d/.httpgroup" #Require user xiaoming Require group webadmins [root@centos8 ~]#cat /etc/httpd/conf.d/.httpgroup webadmins: xiaoming xiaobai [root@centos8 ~]#cat /etc/httpd/conf.d/test.conf <directory /var/www/html/admin> AuthType Basic AuthName "FBI warning" AuthUserFile "/etc/httpd/conf.d/.httpuser" #Require user xiaoming xiaohong require valid-user </directory> <directory /var/www/html/secret> allowoverride authconfig </directory>
3.18 远程客户端和用户验证的控制
Satisfy ALL|Any
说明:
ALL 客户机IP和用户验证都需要通过才可以,此为默认值
Any 客户机IP和用户验证,有一个满足即可
范例:
#针对/var/www/html/test目录,来自192.168.1.0/24的客户可以访问,其它网络的用户需要经过用户验证才能访问 <Directory "/var/www/html/test"> Require valid-user Allow from 192.168.1 Satisfy Any </Directory> #/var/www/private目录只有用户验证才能访问 <Directory "/var/www/private"> Require valid-user </Directory> #/var/www/private/public 不需要用户验证,任何客户都可以访问 <Directory "/var/www/private/public"> Allow from all Satisfy Any </Directory>
3.19 实现用户家目录的http共享
基于模块 mod_userdir.so 实现
相关设置:
vim /etc/httpd/conf.d/userdir.conf <IfModule mod_userdir.c> #UserDir disabled #将此行注释 UserDir public_html #将此行注释取消,指定共享目录的名称 </IfModule> #准备目录 su – wang; mkdir ~/public_html setfacl –m u:apache:x ~wang #访问 http://localhost/~wang/index.html
范例:对家目录共享
[root@centos8 ~]#su - wang [wang@centos8 ~]$mkdir html [wang@centos8 ~]$echo /home/wang/html/index.html > html/index.html [wang@centos8 ~]$setfacl -m u:apache:x /home/wang [root@centos8 ~]#vim /etc/httpd/conf.d/userdir.conf [root@centos8 ~]#grep -v '^ *#' /etc/httpd/conf.d/userdir.conf <IfModule mod_userdir.c> UserDir html </IfModule> <directory /home/wang/html> require all granted </directory> 浏览器访问 http://localhost/~wang/
范例:对家目录共享并实现basic验证
Vi /etc/httpd/conf.d/userdir.conf centos7 <IfModule mod_userdir.c> #UserDir disabled UserDir public_html </IfModule> #注释下面几行 #<Directory "/home/*/public_html"> # AllowOverride FileInfo AuthConfig Limit Indexes # Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec # Require method GET POST OPTIONS #</Directory> Vi /etc/httpd/conf.d/userdir.conf #加下面几行,实现匿名访问 <Directory "/home/test/public_html"> Require all granted </Directory> #准备目录和网页文件 su – test mkdir ~/public_html echo testhomewebsite > ~/public_html/index.html #加权限才成功 setfacl –m u:apache:x ~test #访问 http://localhost/~test/index.html #删除上面行,增加下面行实现认证功能 Vi /etc/httpd/conf.d/userdir.conf <directory /home/test/public_html> AuthType Basic AuthName "test home" AuthUserFile "/etc/httpd/conf.d/htuser" require user http1 </directory> Systemctl restart httpd #新建密码文件 htpasswd -c -m /etc/httpd/conf/.htpasswd test #再次访问 http://localhost/~test/index.html
3.20 隐藏服务器版本信息
ServerTokens Major|Minor|Min[imal]|Prod[uctOnly]|OS|Full
范例:
ServerTokens Prod[uctOnly] :Server: Apache ServerTokens Major: Server: Apache/2 ServerTokens Minor: Server: Apache/2.0 ServerTokens Min[imal]: Server: Apache/2.0.41 ServerTokens OS: Server: Apache/2.0.41 (Unix) ServerTokens Full (or not specified): Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2
建议使用:ServerTokens Prod
禁止错误网页版本泄露
ServerSignature On | Off | EMail
默认值Off,如果ServerTokens 使用默认值,并且ServerSignature选项为on,当客户请求的网页并不存在时,服务器将产生错误文档,错误文档的最后一行将包含服务器名字、Apache版本等信息,如果不对外显示这些信息,就可将这个参数设置为Off, 如果设置为Email,将显示ServerAdmin 的Email提示
ServerSignature on
3.21 禁止trace方法
TraceEnable [on|off|extended]
默认on,基于安全风险,建议关闭
范例:关闭 trace方法
[root@centos8 ~]#curl -IX OPTIONS http://www.apache.org
HTTP/1.1 200 OK
Date: Wed, 24 Jun 2020 06:02:45 GMT
Server: Apache/2.4.18 (Ubuntu)
Allow: GET,HEAD,POST,OPTIONS
Cache-Control: max-age=3600
Expires: Wed, 24 Jun 2020 07:02:45 GMT
Content-Length: 0
Content-Type: text/html
[root@centos8 ~]#curl -IX OPTIONS http://127.0.0.1
HTTP/1.1 200 OK
Date: Wed, 24 Jun 2020 06:04:45 GMT
Server: Apache/2.4.37 (centos)
Allow: POST,OPTIONS,HEAD,GET,TRACE
Content-Length: 0
Content-Type: httpd/unix-directory
[root@centos8 ~]#vim /etc/httpd/conf.d/test.conf
TraceEnable off
[root@centos8 ~]#curl -IX OPTIONS http://127.0.0.1
HTTP/1.1 200 OK
Date: Tue, 10 Dec 2019 04:09:41 GMT
Server: Apache/2.4.37 (centos)
Allow: GET,POST,OPTIONS,HEAD
Content-Length: 0
Content-Type: text/html; charset=UTF-8
3.22 status 状态页
httpd 提供了状态页,可以用来观察httpd的运行情况。此功能需要加载mod_status.so模块才能实现
LoadModule status_module modules/mod_status.so <Location "/status"> SetHandler server-status </Location> ExtendedStatus On #显示扩展信息,httpd 2.3.6以后版默认为On
范例:启动状态页
#确认加载mod_status.so模块 [root@centos8 conf.d]#httpd -M |grep status status_module (shared) [root@centos8 ~]#vim /etc/httpd/conf.d/status.conf <Location "/status"> SetHandler server-status #针对status目录开启状态页面 <RequireAny> Require all denied require ip 172.16.1.1 #允许特定IP </RequireAny> #Order Deny,Allow 此方式也可以控制访问 #Deny from all #Allow from 192.168.100 </Location> ExtendedStatus Off #是否详细的信息,默认值为on [root@centos8 ~]#systemctl restart httpd #打开浏览器访问http://httpd服务器IP/status可以参看到以下页面
3.23 多虚拟主机
httpd 支持在一台物理主机上实现多个网站,即多虚拟主机
网站的唯一标识:
- IP相同,但端口不同
- IP不同,但端口均为默认端口
- FQDN不同, IP和端口都相同
多虚拟主机有三种实现方案:
- 基于ip:为每个虚拟主机准备至少一个ip地址
- 基于port:为每个虚拟主机使用至少一个独立的port
- 基于FQDN:为每个虚拟主机使用至少一个FQDN,请求报文中首部 Host: www.ciciedu.com
注意:httpd 2.4版本中,基于FQDN的虚拟主机不再需要NameVirutalHost指令
虚拟主机的基本配置方法:
<VirtualHost IP:PORT>
ServerName FQDN
DocumentRoot "/path"
</VirtualHost>
建议:上述配置存放在独立的配置文件中
其它常用可用指令:
ServerAlias:虚拟主机的别名;可多次使用
ErrorLog: 错误日志
CustomLog:访问日志
<Directory "/path"> </Directory>
范例:基于端口的虚拟主机
[root@centos8 ~]#echo /data/website1/index.html > /data/website1/index.html [root@centos8 ~]#echo /data/website2/index.html > /data/website2/index.html [root@centos8 ~]#echo /data/website3/index.html > /data/website3/index.html [root@centos8 ~]#cat /etc/httpd/conf.d/test.conf listen 81 listen 82 listen 83 <virtualhost *:81> documentroot /data/website1/ CustomLog logs/website1_access.log combined <directory /data/website1> require all granted </directory> </virtualhost> <virtualhost *:82> documentroot /data/website2/ CustomLog logs/website2_access.log combined <directory /data/website2> require all granted </directory> </virtualhost> <virtualhost *:83> documentroot /data/website3/ CustomLog logs/website3_access.log combined <directory /data/website3> require all granted </directory> </virtualhost> [root@centos8 ~]#ll /var/log/httpd/ total 44 -rw-r--r-- 1 root root 10679 Dec 10 12:00 access_log -rw-r--r-- 1 root root 18883 Dec 10 11:59 error_log -rw-r--r-- 1 root root 1969 Dec 10 12:00 website1_access.log -rw-r--r-- 1 root root 482 Dec 10 12:00 website2_access.log -rw-r--r-- 1 root root 482 Dec 10 12:00 website3_access.log #浏览器访问不同端口,得到不同的页面 http://10.0.0.8:81/ http://10.0.0.8:82/ http://10.0.0.8:83/
范例:基于IP的虚拟主机
说明:这样做的话需要在互联网上申请三个公网ip
[root@centos8 ~]#ip a a 10.0.0.8/24 dev eth0 label eth0:1 [root@centos8 ~]#ip a a 10.0.0.18/24 dev eth0 label eth0:2 [root@centos8 ~]#ip a a 10.0.0.28/24 dev eth0 label eth0:3 [root@centos8 ~]#ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:0c:29:f9:8d:90 brd ff:ff:ff:ff:ff:ff inet 192.168.39.8/24 brd 192.168.39.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet 10.0.0.8/24 scope global eth0 valid_lft forever preferred_lft forever inet 10.0.0.18/24 scope global secondary eth0 valid_lft forever preferred_lft forever inet 10.0.0.28/24 scope global secondary eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fef9:8d90/64 scope link valid_lft forever preferred_lft forever [root@centos8 ~]#vim /etc/httpd/conf.d/test.conf [root@centos8 ~]#cat /etc/httpd/conf.d/test.conf <virtualhost 10.0.0.8:80> documentroot /data/website1/ CustomLog logs/website1_access.log combined <directory /data/website1> require all granted </directory> </virtualhost> <virtualhost 10.0.0.18:80> documentroot /data/website2/ CustomLog logs/website2_access.log combined <directory /data/website2> require all granted </directory> </virtualhost> <virtualhost 10.0.0.28:80> documentroot /data/website3/ CustomLog logs/website3_access.log combined <directory /data/website3> require all granted </directory> </virtualhost> [root@centos8 ~]#httpd -t Syntax OK [root@centos8 ~]#systemctl reload httpd [root@centos8 ~]#curl 10.0.0.8 /data/website1/index.html [root@centos8 ~]#curl 10.0.0.18 /data/website2/index.html [root@centos8 ~]#curl 10.0.0.28 /data/website3/index.html
范例:基于FQDN(主机头)虚拟主机
<VirtualHost *:80> ServerName www.a.com DocumentRoot "/www/a.com/htdocs" <Directory "/www/a.com/htdocs"> ErrorLog "logs/a_error_log" CustomLog "logs/a_access_log" combined Options None AllowOverride None Require all granted </Directory> </VirtualHost> <VirtualHost *:80> ServerName www.b.net DocumentRoot "/www/b.net/htdocs" <Directory "/www/b.net/htdocs"> ErrorLog "logs/b_error_log" CustomLog "logs/b_access_log" combined Options None AllowOverride None Require all granted </Directory> </VirtualHost> <VirtualHost *:80> ServerName www.c.org DocumentRoot "/www/c.org/htdocs" <Directory "/www/c.org/htdocs"> errorLog "logs/c_error_log" CustomLog "logs/c_access_log" combined Options None AllowOverride None Require all granted </Directory> </VirtualHost>
注意:
- 任意目录下的页面只有显式授权才能被访问
- 三种方式的虚拟主机可以混和使用
3.24 压缩
使用mod_deflate模块压缩页面优化传输速度
LoadModule deflate_module modules/mod_deflate.so SetOutputFilter
适用场景:
(1) 节约带宽,额外消耗CPU;同时,可能有些较老浏览器不支持
(2) 压缩适于压缩的资源,例如文本文件
压缩指令
#可选项 SetOutputFilter DEFLATE # 指定对哪种MIME类型进行压缩,必须指定项 AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE text/javascript AddOutputFilterByType DEFLATE text/css #压缩级别 (Highest 9 - Lowest 1) DeflateCompressionLevel 9 #排除特定旧版本的浏览器,不支持压缩 #Netscape 4.x 只压缩text/html BrowserMatch ^Mozilla/4 gzip-only-text/html #Netscape 4.06-08 三个版本 不压缩 BrowserMatch ^Mozilla/4\.0[678] no-gzip #Internet Explorer标识本身为"Mozilla / 4”,但实际上是能够处理请求的压缩。如果用户代理首部匹配字符串"MSIE”("B”为单词边界”),就关闭之前定义的限制 BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
3.25 实现 https
https:http over ssl ,实现验证和加密功能
3.25.1 HTTPS 会话的简化过程
- 客户端发送可供选择的加密方式,并向服务器请求证书
- 服务器端发送证书以及选定的加密方式给客户端
客户端取得证书并进行证书验证,如果信任给其发证书的CA
(a) 验证证书来源的合法性;用CA的公钥解密证书上数字签名
(b) 验证证书的内容的合法性:完整性验证
(c) 检查证书的有效期限
(d) 检查证书是否被吊销
(e) 证书中拥有者的名字,与访问的目标主机要一致
- 客户端生成临时会话密钥(对称密钥),并使用服务器端的公钥加密此数据发送给服务器,完成密钥交换
- 服务用此密钥加密用户请求的资源,响应给客户端
注意:SSL是基于IP地址实现,单IP的httpd主机,仅可以使用一个https虚拟主机
3.25.2 apache实现https过程
为服务器申请数字证书
可以通过私建CA颁发证书实现
(a) 创建私有CA
(b) 在服务器创建证书签署请求
(c) CA签证
配置httpd支持使用ssl,及使用的证书
#安装mod_ssl包 yum -y install mod_ssl #修改对应的配置文件:/etc/httpd/conf.d/ssl.conf DocumentRoot ServerName SSLCertificateFile /path/file SSLCertificateKeyFile /path/file SSLCACertificateFile /path/file
测试基于https访问相应的主机
openssl s_client [-connect host:port] [-cert filename] [-CApath directory] [-CAfile filename]
范例:
[root@centos8 ssl]#openssl s_client -connect www.cicin.com:443 -CAfile 3395645_cicin.com_chain.crt
3.25.3 实现https 实战案例
3.25.3.1 范例1:生成自签名证书
[root@centos8 ~]#yum -y install mod_ssl [root@centos7 ~]#cd /etc/pki/tls/certs [root@centos7 certs]#pwd /etc/pki/tls/certs [root@centos7 certs]#ls ca-bundle.crt ca-bundle.trust.crt make-dummy-cert Makefile renew-dummy-cert [root@centos7 certs]#vim Makefile #/usr/bin/openssl genrsa -aes128 $(KEYLEN) > $@ /usr/bin/openssl genrsa $(KEYLEN) > $@ [root@centos7 certs]#make ciciedu.org make: *** No rule to make target 'ciciedu.org'. Stop. [root@centos7 certs]#make ciciedu.org.crt umask 77 ; \ #/usr/bin/openssl genrsa -aes128 2048 > ciciedu.org.key /usr/bin/openssl genrsa 2048 > ciciedu.org.key Generating RSA private key, 2048 bit long modulus ......................+++ ...+++ e is 65537 (0x10001) umask 77 ; \ /usr/bin/openssl req -utf8 -new -key ciciedu.org.key -x509 -days 365 -out ciciedu.org.crt You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:beijing Locality Name (eg, city) [Default City]:beijing Organization Name (eg, company) [Default Company Ltd]:ciciedu Organizational Unit Name (eg, section) []:devops Common Name (eg, your name or your server's hostname) []:www.ciciedu.org Email Address []: [root@centos7 certs]#ls ca-bundle.crt ca-bundle.trust.crt ciciedu.org.crt ciciedu.org.key make-dummycert Makefile renew-dummy-cert [root@Centos7 ~]#mkdir /etc/httpd/conf.d/ssl [root@Centos7 ~]#ll /etc/httpd/conf.d/ssl total 16 -rw-r--r-- 1 root root 1143 Jun 25 23:40 cacert.pem -rw-r--r-- 1 root root 1078 Jun 25 23:40 www.b.com.crt -rw-r--r-- 1 root root 976 Jun 25 23:40 www.b.com.csr -rw------- 1 root root 1708 Jun 25 23:40 www.b.com.key [root@Centos7 ~]#vim /etc/httpd/conf.d/ssl.conf [root@Centos7 ~]#systemctl restart httpd [root@Centos7 ~]#echo centos7 > /var/www/html/index.html
3.25.3.2 范例2:互联网网站证书实现 (待补充)
[root@centos8 ~]#dnf -y install mod_ssl
[root@centos8 ~]#ll /etc/httpd/conf.d/ssl/
total 24
-rw-r--r-- 1 root root 1679 Dec 10 2019 www.cicin.com_chain.crt
-rw-r--r-- 1 root root 1675 Dec 10 2019 www.cicin.com.key
-rw-r--r-- 1 root root 2021 Dec 10 2019 www.cicin.com_public.crt
[root@centos8 ~]#cd /etc/httpd/conf.d/ssl/
[root@centos8 ssl]#openssl x509 -in www.cicin.com_public.crt -noout -text
[root@centos8 ~]#grep -Ev "^ *#|^$" /etc/httpd/conf.d/ssl.conf
3.26 URL重定向
URL重定向,即将httpd 请求的URL转发至另一个的URL
重定向指令
Redirect [status] URL-path URL
*status状态*:
- permanent: 返回永久重定向状态码 301,浏览器会将 此重定向信息进行缓存
- temp:返回临时重定向状态码302. 此为默认值
说明:
服务器返回301或者302的值是公司的一种策略,并不是强制约定
范例:
[root@centos8 ~]#vim /etc/httpd/conf.d/test.conf Redirect permanent / https://www.ciciedu.com/
范例:
[root@centos8 ~]#vim /etc/httpd/conf.d/test.conf Redirect permanent / http://www.b.com/
范例:
[root@centos8 ~]#vim /etc/httpd/conf.d/test.conf Redirect temp / http://www.b.com/
Redirect permanent / https://www.a.com/
RewriteEngine on RewriteRule ^(/.*)$ https://%{HTTP_HOST}$1 [redirect=302]
实验 :
[root@Centos7 ~]#curl -I http://www.jd.com/ HTTP/1.1 302 Moved Temporarily Server: nginx Date: Fri, 26 Jun 2020 02:10:04 GMT Content-Type: text/html Content-Length: 138 Connection: keep-alive Location: https://www.jd.com/ Access-Control-Allow-Origin: * Timing-Allow-Origin: * X-Trace: 302-1593137404905-0-0-0-0-0 Strict-Transport-Security: max-age=360 [root@Centos7 ~]#curl -I http://www.taobao.com/ HTTP/1.1 301 Moved Permanently Server: Tengine Date: Fri, 26 Jun 2020 02:10:18 GMT Content-Type: text/html Content-Length: 278 Connection: keep-alive Location: https://www.taobao.com/ Via: cache19.cn2588[,0] Timing-Allow-Origin: * EagleId: 6fa02c9515931374188153124e
3.27 实现HSTS
HSTS:HTTP Strict Transport Security , 服务器端配置支持HSTS后,会在给浏览器返回的HTTP首部中携带HSTS字段。浏览器获取到该信息后,会将所有HTTP访问请求在内部做307跳转到HTTPS。而无需任何网络过程,实现更高的安全性
HSTS preload list:
是Chrome浏览器中的HSTS预载入列表,在该列表中的网站,使用Chrome浏览器访问时,会自动转换成HTTPS。Firefox、Safari、Edge浏览器也会采用这个列表
范例:
[root@Centos7 ~]#curl -Ik http://www.tmall.com/ HTTP/1.1 302 Found Server: Tengine Date: Fri, 26 Jun 2020 07:15:31 GMT Content-Type: text/html Content-Length: 258 Connection: keep-alive Location: https://www.tmall.com/ Via: cache8.cn791[,0] Timing-Allow-Origin: * EagleId: 77f9309c15931557314598911e Strict-Transport-Security: max-age=31536000 [root@centos7 ~]#curl -Ik http://www.jd.com/ HTTP/1.1 302 Moved Temporarily Server: nginx Date: Fri, 26 Jun 2020 07:15:38 GMT Content-Type: text/html Content-Length: 138 Connection: keep-alive Location: https://www.jd.com/ Access-Control-Allow-Origin: * Timing-Allow-Origin: * X-Trace: 302-1593155738017-0-0-0-0-0 Strict-Transport-Security: max-age=360
范例:实现HSTS
#严格的传输安全,一年有效期 [root@centos8 ~]#vim /etc/httpd/conf.d/test.conf Header always set Strict-Transport-Security "max-age=31536000" RewriteEngine on RewriteRule ^(/.*)$ https://%{HTTP_HOST}$1 [redirect=302] [root@Centos7 ~]#curl -I http://www.a.com/ HTTP/1.1 302 Found Date: Fri, 26 Jun 2020 03:45:27 GMT Server: Apache/2.4.37 (centos) OpenSSL/1.1.1c Strict-Transport-Security: max-age=31536000 Location: https://www.a.com/ Content-Type: text/html; charset=iso-8859-1 #只能看到302的跳转信息,看不到希望看到的最终页面 [root@Centos7 ~]#curl http://www.a.com/ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>302 Found</title> </head><body> <h1>Found</h1> <p>The document has moved <a href="https://www.a.com/">here</a>.</p> </body></html> #按照跳转的结果去访问页面,最终访问到加密的页面 [root@Centos7 ~]#curl -L http://www.a.com/ curl: (60) Peer's certificate issuer has been marked as not trusted by the user. More details here: http://curl.haxx.se/docs/sslcerts.html curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option. If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL). If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option. #加k选项,忽略证书检查,看到最终的页面 [root@Centos7 ~]#curl -Lk http://www.a.com/ <h1>/var/www/html/index.html</h1>
3.28 正向代理和反向代理
正向代理说明: 服务于客户端,隐藏了客户端的IP地址
假设某小区里的几个用户想要去网上看一个500M的视频 , 500M的视频会反复地下载,这样小区的带宽就被重复da的公司的浪费掉了, 搭建了正向代理服务器后,每个用户就通过代理服务器进行上网,这时用户再去看视频时,代理服务器就会替用户把视频下载缓存下来,其他用户再浏览同一个视频时,就不需要再从服务器上下载,于是网络带宽的消耗大幅减少 ; 另外,在代理服务器上还可以设置访问控制,实现安全策略
反向代理说明: 服务于服务端,隐藏了服务端的IP地址
大的公司可能会有多个服务器 ,用户访问时就不知道访问哪个,反向代理服务器就像一个接待者,首先用户向DNS发请求,DNS给用户一个反向代理服务器的地址,反向代理服务器收到请求后,转发给它觉得合理的服务器上去
启用反向代理
ProxyPass "/" "http://www.example.com/" ProxyPassReverse "/" "http://www.example.com/"
特定URL反向代理
ProxyPass "/images" "http://www.example.com/" ProxyPassReverse "/images" http://www.example.com/
范例:
<VirtualHost *> ServerName www.ciciedu.com ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/ </VirtualHost>
3.29 Sendfile 机制
设置Sendfile 功能
EnableSendfile On|Off
属于”零复制”技术
不用 sendfile 的传统网络传输过程:
read(file, tmp_buf, len)
write(socket, tmp_buf, len)
硬盘 >> kernel buffer >> user buffer >> kernel socket buffer >> 协议栈
一般网络应用通过读硬盘数据,写数据到 socket 来完成网络传输,底层执行过程:
- 系统调用 read() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后 DMA 执行拷贝,把文件数据从硬盘读到一个 kernel buffer 里
- 数据从 kernel buffer 拷贝到 user buffer,然后系统调用 read() 返回,这时又产生一个上下文切换:从kernel mode 切换到 user mode
- 系统调用 write() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后把步骤2读到 user buffer 的数据拷贝到 kernel buffer(数据第2次拷贝到 kernel buffer),不过这次是个不同的 kernel buffer,这个 buffer和 socket 相关联
- 系统调用 write() 返回,产生一个上下文切换:从 kernel mode 切换到 user mode(第4次切换),然后DMA从 kernel buffer 拷贝数据到协议栈(第4次拷贝)
上面4个步骤有4次上下文切换,有4次拷贝,如果能减少切换次数和拷贝次数将会有效提升性能
Sendfile机制
在kernel 2.0+ 版本中,系统调用 sendfile() 就是用来简化上面步骤提升性能的。sendfile() 不但能减少切换次数而且还能减少拷贝次数用 sendfile() 来进行网络传输的过程:
sendfile(socket, file, len);
硬盘 >> kernel buffer (快速拷贝到kernel socket buffer) >> 协议栈
- 系统调用 sendfile() 通过 DMA 把硬盘数据拷贝到 kernel buffer,然后数据被 kernel 直接拷贝到另外一个与 socket 相关的 kernel buffer。这里没有 user mode 和 kernel mode 之间的切换,在 kernel 中直接完成了从一个 buffer 到另一个 buffer 的拷贝
- DMA 把数据从 kernel buffer 直接拷贝给协议栈,没有切换,也不需要数据从 user mode 拷贝到 kernel mode,因为数据就在 kernel 里
3.30 指定文件类型 content type
相关指令
#指定文件和content type 的对应文件 TypesConfig file-path #在给定的文件扩展名与特定的content type内容类型之间建立映射关系。MIME-type指明了包含extension扩展名的文件的媒体类型。这个映射关系会添加在所有有效的映射关系上,并覆盖所有相同的extension扩展名映射,extension参数是不区分大小的,并且可以带或不带前导点 AddType MIME-type extension [extension] ...
范例:
TypesConfig /etc/mime.types #默认指向配置文件 AddType image/jpeg jpeg jpg jpe AddType application/x-httpd-php .php
4 http 协议及报文头部结构
浏览器访问网页的过程
http协议:http/0.9, http/1.0, http/1.1, http/2.0,http/3.0
http协议:stateless 无状态, 服务器无法持续追踪访问者来源
解决http协议无状态方法
- cookie 客户端存放
- session 服务端存放
http事务:一次访问的过程
- 请求:request
- 响应:response
HTTP报文结构
协议查看或分析的工具:tcpdump, wireshark,tshark
4.1 HTTP请求报文
request报文格式
<method> <request-URL> <version> <headers> <entity-body
范例:
GET / HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate Connection: keep-alive Host: www.ciciedu.com User-Agent: HTTPie/0.9.4
范例:
#post.html <form action="index.html" method="POST"> username:<br> <input type="text" name="username" > <br> password:<br> <input type="text" name="password" > <br><br> <input type="submit" value="Submit"> </form>
4.2 HTTP响应报文
response报文格式
<version> <status> <reason-phrase> <headers> <entity-body>
范例:
HTTP/1.1 200 OK
Cache-Control: max-age=3, must-revalidate
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=UTF-8
Date: Thu, 07 Nov 2019 03:44:14 GMT
Server: Tengine
Transfer-Encoding: chunked
Vary: Accept-Encoding
Vary: Accept-Encoding, Cookie
4.3 HTTP报文格式详解
4.3.1 Method 方法
请求方法,标明客户端希望服务器对资源执行的动作,包括以下:
- GET: 从服务器获取一个资源
- HEAD: 只从服务器获取文档的响应首部
- POST: 向服务器输入数据,通常会再由网关程序继续处理
- PUT: 将请求的主体部分存储在服务器中,如上传文件
- DELETE: 请求删除服务器上指定的文档
- TRACE: 追踪请求到达服务器中间经过的代理服务器
- OPTIONS:请求服务器返回对指定资源支持使用的请求方法
- CONNECT:建立一个到由目标资源标识的服务器的隧道
- PATCH:用于对资源应用部分修改
其中GET,HEAD,POST用得较多
4.3.2 version版本
HTTP/<major>.<minor>
范例:
HTTP/1.1
4.3.3 status 状态码
三位数字,标记请求处理过程中发生的情况
参考资料:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
http协议状态码分类
1xx:100-101 信息提示 2xx:200-206 成功 3xx:300-307 重定向 4xx:400-415 错误类信息,客户端错误 5xx:500-505 错误类信息,服务器端错误
http协议常用的状态码
200: 成功,请求数据通过响应报文的entity-body部分发送;OK 301: 请求的URL指向的资源已经被删除;但在响应报文中通过首部Location指明了资源现在所处的新位置;Moved Permanently 302: 响应报文Location指明资源临时新位置 Moved Temporarily 304: 客户端发出了条件式请求,但服务器上的资源未曾发生改变,则通过响应此响应状态码通知客户端;Not Modified 307: 浏览器内部重定向 401: 需要输入账号和密码认证方能访问资源;Unauthorized 403: 请求被禁止;Forbidden 404: 服务器无法找到客户端请求的资源;Not Found 500: 服务器内部错误;Internal Server Error 502: 代理服务器从后端服务器收到了一条伪响应,如无法连接到网关;Bad Gateway 503: 服务不可用,临时服务器维护或过载,服务器无法处理请求 504: 网关超时
4.3.4 reason-phrase原因短语
状态码所标记的状态的简要描述
4.3.5 headers首部字段头
首部字段包含的信息最为丰富。首部字段同时存在于请求和响应报文内,并涵盖 HTTP 报文相关的内容信息。使用首部字段是为了给客服端和服务器端提供报文主体大小、所使用的语言、认证信息等内容
首部字段是由首部字段名和字段值构成的,中间用冒号”:”分隔字段值对应,即key/value 键/值对单个 HTTP 首部字段可以有多个值
参考资料:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
*首部的分类*:
- 通用首部:请求报文和响应报文两方都会使用的首部
- 请求首部:从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、请求内容相关优先级等信息
- 响应首部:从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息
- 实体首部:针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的的信息
- 扩展首部
*通用首部*:
- Date: 报文的创建时间
- Connection:连接状态,如keep-alive, close
- Via:显示报文经过的中间节点(代理,网关)
- Cache-Control:控制缓存,如缓存时长
- MIME-Version:发送端使用的MIME版本
- Warning:错误通知
*请求首部*:
- Accept:通知服务器自己可接受的媒体类型
- Accept-Charset: 客户端可接受的字符集
- Accept-Encoding:客户端可接受编码格式,如gzip
- Accept-Language:客户端可接受的语言
- Client-IP: 请求的客户端IP
- Host: 请求的服务器名称和端口号
- Referer:跳转至当前URI的前一个URL
User-Agent:客户端代理,浏览器版本
条件式请求首部 :
- Expect:允许客户端列出某请求所要求的服务器行为
- If-Modified-Since:自从指定的时间之后,请求的资源是否发生过修改
- If-Unmodified-Since:与上面相反
- If-None-Match:本地缓存中存储的文档的ETag标签是否与服务器文档的Etag不匹配
If-Match:与上面相反
安全请求首部 :
- Authorization:向服务器发送认证信息,如账号和密码
Cookie: 客户端向服务器发送cookie
代理请求首部 :
- Proxy-Authorization: 向代理服务器认证
响应首部 :
信息性:
- Age:从最初创建开始,响应持续时长
- Server:服务器程序软件名称和版本
协商首部:某资源有多种表示方法时使用
- Accept-Ranges:服务器可接受的请求范围类型
- Vary:服务器查看的其它首部列表
安全响应首部:
- Set-Cookie:向客户端设置cookie
- WWW-Authenticate:来自服务器对客户端的质询列表
*实体首部*:
- Allow: 列出对此资源实体可使用的请求方法
- Location:告诉客户端真正的实体位于何处
- Content-Encoding:对主体执行的编码
- Content-Language:理解主体时最适合的语言
- Content-Length: 主体的长度
- Content-Location: 实体真正所处位置
Content-Type:主体的对象类型,如text
缓存相关 :
- ETag:实体的扩展标签
- Expires:实体的过期时间
- Last-Modified:最后一次修改的时间
4.3.6 entity-body实体
请求时附加的数据或响应时附加的数据,例如:登录网站时的用户名和密码,博客的上传文章,论坛上的发言等。
4.4 Cookie 和 session
无状态协议 是指协议对事物处理 没有记忆能力 。缺少状态意味着如果后 续处理需要前面的信息,则必须重传,这样可能导致每次连接传送的数据量增大。 另一方面,在服务器不需要先前信息时它应答就很快。
HTTP是超本文传输协议,顾名思义,这个协议支持超文本的传输。什么是超文本?说白了就是使用HTML编写的页面。通常,我们使用客户端浏览器访问服务器的资源,最常见的URL也是以html为后缀的文件,因此可以说超文本是网络上最主要的资源。
既然HTTP协议的目的是在于支持超文本的传输,也就是资源的传输,那么客户端浏览器向HTTP服务器发送请求,继而HTTP服务器将相信资源发回给客户端这样一个过程中,无论对于客户端还是服务器,都没有必要记录这个过程,因为每一次请求和响应都是相对独立的,一般而言,一个URL对应着一个唯一的超文本,正是因为这样的唯一性,使得记录用户的行为状态变得毫无意义,所以,HTTP协议被设计为无状态的连接协议符合它本身的需求。
HTTP协议这种特性有优点也有缺点,优点在于解放了服务器,每一次请求”点到为止”,不会造成不必要的连接占用,缺点在于如果为了保留状态,每次请求都会传输大量的重复信息内容。
可是随着 Web 的不断发展,很多业务都需要对通信状态进行保存.
如果是一次性会话的过程: 打开浏览器 -> 访问一些服务器内容 -> 关闭浏览器
但目前有很多WEB访问场景,并不是一次性会话,而是多次相关的会话,比如:
登录场景:打开浏览器 -> 浏览到登陆页面 -> 输入用户名和密码 -> 访问到用户主页(显示用户名) -> 修改密码(输入原密码)-> 修改收货地址…
问题:在此处登录会话过程中产生的数据(用户会话数据)如何保存下来呢?
购物场景:打开浏览器 -> 浏览商品列表 -> 加入购物车(把商品信息保存下来) -> 关闭浏览器
打开浏览器-> 直接进入购物车 -> 查看到上次加入购物车的商品 -> 下订单 -> 支付
问题: 在购物会话过程中,如何保存商品信息?
以上场景都需要保留会话数据,需要会话管理机制。
会话管理: 管理浏览器客户端和服务器端之间会话过程中产生的会话数据。
为了会话管理,HTTP就需要传输大量重复信息内容的问题,造成大量的网络带宽消耗。于是 Cookie 和 Session 技术闪亮登场了,它们可以为用户进行会话管理,实现保存状态。
4.4.1 Cookie
Cookie 又称为”小甜饼”。类型为”小型文本文件”,指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。由网景公司的前雇员卢·蒙特利在1993年3月发明
因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结帐时,由于HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么,所以Cookie就是用来绕开HTTP的无状态性的”额外手段”之一。服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。
在上面的购物场景中,当用户选购了第一项商品,服务器在向用户发送网页的同时,还发送了一段Cookie,记录着那项商品的信息。当用户访问另一个页面,浏览器会把Cookie发送给服务器,于是服务器知道他之前选购了什么。用户继续选购饮料,服务器就在原来那段Cookie里追加新的商品信息。结帐时,服务器读取发送来的Cookie就行了。
set-cookie是首部字段
Cookie基于HTTP协议,也叫Web Cookie或浏览器Cookie,是服务器发送到用户浏览器并保存在客户端本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie使基于无状态的HTTP协议记录稳定的状态信息成为了可能。
Cookie主要用于以下三个方面:
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
使用 Cookie 的状态管理
Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。当服务器收到HTTP请求时,服务器可以在响应头里面添加一个Set-Cookie选项。浏览器收到响应后通常会保存下Cookie,之后对该服务器每一次请求中都通过Cookie请求头部将Cookie信息发送给服务器。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息.另外,Cookie的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。
Set-Cookie首部字段
- NAME=VALUE 赋予 Cookie 的名称和其值,此为必需项
expires=DATE Cookie 的有效期,若不明确指定则默认为浏览器关闭前为止
会话期Cookie
基于内存保存,会话期Cookie是最简单的Cookie:*浏览器关闭之后它会被自动删除*,也就是说它仅在会话期内有效。会话期Cookie不需要指定过期时间(Expires)或者有效期(Max-Age)。需要注意的是,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期Cookie也会被保留下来,就好像浏览器从来没有关闭一样。
持久性Cookie
基于硬盘保存,和关闭浏览器便失效的会话期Cookie不同,持久性Cookie可以指定一个特定的过期时间(Expires)或有效期(Max-Age)。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; 过期时间
提示:当Cookie的过期时间被设定时,设定的日期和时间只与客户端相关,而不是服务端。
path=PATH 指定了主机下的哪些路径可以接受Cookie(该URL路径必须存在于请求URL中)。若不指定则默认为文档所在的文件目录,以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。
例如,设置 Path=/docs ,则以下地址都会匹配:
- /docs
- docs/Web
- /docs/Web/HTTP
domain=域名 指定了哪些主机可以接受Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了Domain,则一般包含子域名。
例如,如果设置 Domain=ciciedu.com,则Cookie也包含子域名(如:study.ciciedu.com)
- Secure 标记为 Secure 的Cookie只应通过被HTTPS协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过Cookie传输,因为Cookie有其固有的不安全性,Secure 标记也无法提供确实的安全保障。从 Chrome 52 和 Firefox 52 开始,不安全的站点(http:%EF%BC%89%E6%97%A0%E6%B3%95%E4%BD%BF%E7%94%A8Cookie%E7%9A%84 Secure 标记。
- HttpOnly 加以限制使 Cookie 不能被 JavaScript 脚本访问,为避免跨域脚本 (XSS) 攻击,通过JavaScript的 Document.cookie API无法访问带有 HttpOnly 标记的Cookie,它们只应该发送给服务端。如果包含服务端 Session 信息的 Cookie 不想被客户端 JavaScript 脚本调用,那么就应该为其设置 HttpOnly 标记
*浏览器对cookie的限制*:
Cookie 存储的限制是不一样的。例如:单个域名可存储的 Cookie 数量、Cookie 大小等。
IE6.0 | IE7.0/8.0 | Opera | FF | Safari | Chrome | |
---|---|---|---|---|---|---|
cookie个数 | 每个域为20个 | 每个域为50个 | 每个域为30个 | 每个域为50个 | 没有个数限制 | 每个域为53个 |
cookie大小 | 4095个字节 | 4095个字节 | 4096个字节 | 4097个字节 | 4097个字节 | 4097个字节 |
在进行页面 Cookie 操作的时候,应该尽量保证 Cookie 的个数小于 20 个,总大小小于 4KB,这是一个安全且保险的范围。
范例:响应报文中的set-cookie首部
HTTP/1.0 200 OK Content-type: text/html Set-Cookie: yummy_cookie=choco Set-Cookie: tasty_cookie=strawberry
范例:请求报文中的cookie首部字段
GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: yummy_cookie=choco; tasty_cookie=strawberry
范例:响应报文set-cookie中的Secure 和 HttpOnly
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
范例:浏览器查看cookie
范例:chrome 浏览器禁止cookie
范例:php语言实现cookie的管理
#设置cookie #cat setcookie.php <?php setcookie('title','cto'); #有效期为会话级 setcookie('user','wang',time()+3600*12); #有效期为12小时 echo "<h1>test setcookie </h1>" ?> #说明:setcookie设置的cookie,只有下一次http请求才能生效 #显示cookie cat showcookies.php <?php echo "<h1>test showcookie </h1>"; echo $_COOKIE["user"]; #显示user的这一个cookie echo "<br />"; var_dump($_COOKIE); #显示所有cookie //print_r($_COOKIE); #不如上面方式详细 ?> #删除cookie,通过设置过期时间实现 #vim delcookie.php <?php setcookie('user','cui',time()-3600*12); echo "<h1>cookie:user is deleted </h1>"; ?>
显示cookie
4.4.2 Sessio
session
session是相对于cookie的另外一个状态保持的解决方案,它是通过服务器来保持状态的。session指的是服务器上为每个客户端所开辟的独立存储空间,在其中保存的信息就是用于保存状态的。
Session是服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建session的方法。在创建了session的同时,服务器会为该session生成唯一的sessionId,而这个sessionId被创建了之后,就可以调用session相关的方法往session中增加内容了,而这些内容只会保存在服务器中,每个sessionid就像数据库中主键,可以根据SessionId 关联每个session的相关信息,比如:购物车里的商器,登录用户等。但发送给客户端浏览器的只有sessionId。当客户端浏览器再次发送http请求时,会自动地将这个sessionId 附加在请求报文中 ,服务器收到请求之后就会根据sessionId找到对应的session,从而再次使用,使得用户的状态得以保持。
每个session都有一个sessionId,这个ID存放有两种方式:
1、通过URL存取,比如:Java程序中,URL会带上一个jsessionId=xxxxxx等,这样每次重新请求的时候都传了sessionId给服务器
2、通过cookie存取(Tomcat默认如此),这种cookie是session cookie,区别于persistent cookies也就是我们常说的cookie,session cookie要注意的是存储在浏览器内存中,而不是写到硬盘上。程序一开始执行,服务器就生成一个sessionId并通过cookie携带客户端浏览器的缓存中,当下一次访问的时候,服务器先检测一下是否有这个cookie,如果有就取它的ID,如果没有就再生成一个。这就是为什么关闭浏览器之后,再进去session已经没有了,其实在服务器端session并没有清空,而是sessionId变了。
当将浏览器关闭,服务器保存的session数据不是立即释放的,此时数据还会存在一段时间(可以在程序中加以设置,Tomcat默认15分钟),只要我们知道那个sessionId,就可以继续通过请求获得此session的信息。session里面的数据都放在服务器端,通过sessionId保证不会访问错误,服务端自动对session进行管理,如果在规定的时间内没有访问,则释放掉这个session。
最后提两点:
1、sessionId通常是看不到的,但是当我们把浏览器的cookie禁止之后,Web服务器会采用URL重写的方式传递sessionId,这样就可以在地址栏看到sessionId了
2、session cookie不可以跨窗口使用,但可以跨同一个窗口的多个标签页。
范例:PHP的PHPSESSID
<?php session_start(); echo session_id(); ?> #执行结果如下图
范例:JAVA的JSESSIONID
4.4.3 cookie和session比较
cookie和session的相同和不同:
- cookie和session两者都是在服务器端生成
- session 将数据信息保存在服务器端,可以是内存,文件,数据库等多种形式,cookie 将数据保存在客户端的内存或文件中
- 单个cookie保存的数据不能超过4K,每个站点cookie个数有限制,比如IE8为50个、Firefox为50个、Opera为30个;session存储在服务器,没有容量限制
- cookie存放在用户本地,可以被轻松访问和修改,安全性不高;session存储于服务器,比较安全
- cookie有会话cookie和持久cookie,生命周期为浏览器会话期的会话cookie保存在缓存,关闭浏览器窗口就消失,持久cookie被保存在硬盘,知道超过设定的过期时间;随着服务端session存储压力增大,会根据需要定期清理session数据
- session中有众多数据,只将sessionID这一项可以通过cookie发送至客户端进行保留,客户端下次访问时,在请求报文中的cookie会自动携带sessionID,从而和服务器上的的session进行关联
cookie缺点:
1、使用cookie来传递信息,随着cookie个数的增多和访问量的增加,它占用的网络带宽也很大,试想假如cookie占用200字节,如果一天的PV有几个亿,那么它要占用多少带宽?
2、cookie并不安全,因为cookie是存放在客户端的,所以这些cookie可以被访问到,设置可以通过插件添加、修改cookie。所以从这个角度来说,我们要使用sesssion,session是将数据保存在服务端的,只是通过cookie传递一个sessionId而已,所以session更适合存储用户隐私和重要的数据
session 缺点:
1、不容易在多台服务器之间共享,可以使用session绑定,session复制,session共享解决
2、session存放在服务器中,所以session如果太多会非常消耗服务器的性能
cookie和session各有优缺点,在大型互联网系统中,单独使用cookie和session都是不可行的
5 Web相关工具
5.1 links
格式:
links [OPTION]... [URL]...
常用选项:
- -dump 非交互式模式,显示输出结果
- -source 打印源码
5.2 wget
格式:
wget [OPTION]... [URL]...
常用选项:
#启动 -V, –version 显示wget的版本后退出 -h, –help 打印语法帮助 -b, –background 启动后转入后台执行 -e, –execute=COMMAND 执行'.wgetrc'格式的命令,wgetrc格式参见/etc/wgetrc或~/.wgetrc #记录和输入文件 -o, –output-file=FILE 把记录写到FILE文件中 -a, –append-output=FILE 把记录追加到FILE文件中 -d, –debug 打印调试输出 -q, –quiet 安静模式(没有输出) -v, –verbose 冗长模式(这是缺省设置) -nv, –non-verbose 关掉冗长模式,但不是安静模式 -i, –input-file=FILE 下载在FILE文件中出现的URLs -F, –force-html 把输入文件当作HTML格式文件对待 -B, –base=URL 将URL作为在-F -i参数指定的文件中出现的相对链接的前缀 –sslcertfile=FILE 可选客户端证书 –sslcertkey=KEYFILE 可选客户端证书的KEYFILE –egd-file=FILE 指定EGD socket的文件名 #下载 -bind-address=ADDRESS 指定本地使用地址(主机名或IP,当本地有多个IP或名字时使用) -t, –tries=NUMBER 设定最大尝试链接次数(0 表示无限制). -O –output-document=FILE 把文档写到FILE文件中 -nc, –no-clobber 不要覆盖存在的文件或使用.#前缀 -c, –continue 接着下载没下载完的文件 -progress=TYPE 设定进程条标记 -N, –timestamping 不要重新下载文件除非比本地文件新 -S, –server-response 打印服务器的回应 -spider 不下载任何东西 -T, –timeout=SECONDS 设定响应超时的秒数 -w, –wait=SECONDS 两次尝试之间间隔SECONDS秒 -waitretry=SECONDS 在重新链接之间等待1…SECONDS秒 -random-wait 在下载之间等待0…2*WAIT秒 -Y, –proxy=on/off 打开或关闭代理 -Q, –quota=NUMBER 设置下载的容量限制 -limit-rate=RATE 限定下载输率 #目录 -nd –no-directories 不创建目录 -x, –force-directories 强制创建目录 -nH, –no-host-directories 不创建主机目录 -P , –directory-prefix=PREFIX 将文件保存到目录 PREFIX/… –cut-dirs=NUMBER 忽略 NUMBER层远程目录 #HTTP 选项 –http-user=USER 设定HTTP用户名为 USER. –http-passwd=PASS 设定http密码为 PASS. -C, –cache=on/off 允许/不允许服务器端的数据缓存 (一般情况下允许). -E, –html-extension 将所有text/html文档以.html扩展名保存 –ignore-length 忽略 'Content-Length'头域 –header=STRING 在headers中插入字符串 STRING –proxy-user=USER 设定代理的用户名为 USER –proxy-passwd=PASS 设定代理的密码为 PASS –referer=URL 在HTTP请求中包含 'Referer: URL'头 -s, –save-headers 保存HTTP头到文件 -U, –user-agent=AGENT 设定代理的名称为 AGENT而不是 Wget/VERSION. –no-http-keep-alive 关闭 HTTP活动链接 (永远链接). –cookies=off 不使用 cookies. –load-cookies=FILE 在开始会话前从文件 FILE中加载cookie –save-cookies=FILE 在会话结束后将 cookies保存到 FILE文件中 #FTP 选项 -nr, –dont-remove-listing 不移走 '.listing'文件 -g, –glob=on/off 打开或关闭文件名的 globbing机制 –passive-ftp 使用被动传输模式 (缺省值). –active-ftp 使用主动传输模式 –retr-symlinks 在递归的时候,将链接指向文件(而不是目录) #递归下载 -r, –recursive 递归下载--慎用! -l, –level=NUMBER 最大递归深度 (inf 或 0 代表无穷). –delete-after 在现在完毕后局部删除文件 -k, –convert-links 转换非相对链接为相对链接 -K, –backup-converted 在转换文件X之前,将之备份为 X.orig -m, –mirror 等价于 -r -N -l inf -nr. -p, –page-requisites 下载显示HTML文件的所有图片 #递归下载中的包含和不包含(accept/reject) -A, –accept=LIST 分号分隔的被接受扩展名的列表 -R, –reject=LIST 分号分隔的不被接受的扩展名的列表 -D, –domains=LIST 分号分隔的被接受域的列表 –exclude-domains=LIST 分号分隔的不被接受的域的列表 –follow-ftp 跟踪HTML文档中的FTP链接 –follow-tags=LIST 分号分隔的被跟踪的HTML标签的列表 -G, –ignore-tags=LIST 分号分隔的被忽略的HTML标签的列表 -H, –span-hosts 当递归时转到外部主机 -L, –relative 仅仅跟踪相对链接 -I, –include-directories=LIST 允许目录的列表 -X, –exclude-directories=LIST 不被包含目录的列表 -np, –no-parent 不要追溯到父目录
常用选项:
-q 静默模式 -c 断点续传 -P /path 保存在指定目录 -O filename 保存为指定文件名,filename 为 – 时,发送至标准输出 --limit-rate= 指定传输速率,单位K,M等
范例:
[root@centos8 ~]#wget --limit-rate 1M -P /data
https://mirrors.aliyun.com/centos/8/isos/x86_64/CentOS-8-x86_64-1905-dvd1.iso
--2019-12-12 13:02:18-- https://mirrors.aliyun.com/centos/8/isos/x86_64/CentOS-8-x86_64-1905-dvd1.iso
Resolving mirrors.aliyun.com (mirrors.aliyun.com)... 27.221.92.112,
119.167.168.225, 61.240.128.248, ...
Connecting to mirrors.aliyun.com (mirrors.aliyun.com)|27.221.92.112|:443...connected.
HTTP request sent, awaiting response... 200 OK
Length: 7135559680 (6.6G) [application/octet-stream]
Saving to: ‘/data/CentOS-8-x86_64-1905-dvd1.iso’
CentOS-8-x86_64-1905-dvd1.iso 100%
[========================================================================================>] 6.65G 1.04MB/s in 1h 53m
2019-12-12 14:55:45 (1024 KB/s) - ‘/data/CentOS-8-x86_64-1905-dvd1.iso’ saved[7135559680/7135559680]
[root@centos8 ~]#ls /data
CentOS-8-x86_64-1905-dvd1.iso
范例:实现浏览器功能
#有些容器中命令比较少,可能会缺少curl,此时就可以用wget代替curl实现浏览器功能 [root@Centos7 ~]#wget -qO - http://10.0.0.8/ <h1>welcome to centos8</h1> [root@Centos7 ~]#curl http://10.0.0.8/ <h1>welcome to centos8</h1>
范例: 下载指定目录
[root@centos8 ~]#wget -r -np -nH -R index.html http://www.example.com/dir/ [root@centos8 ~]#wget -c -r -np -k -L -p http://www.example.com/dir/ -r : 遍历所有子目录 -np : 不到上一层子目录去 -nH : 不要将文件保存到主机名文件夹 -R index.html : 不下载 index.html 文件
5.3 curl
curl是基于URL语法在命令行方式下工作的文件传输工具,它支持FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE及LDAP等协议。curl支持HTTPS认证,并且支持HTTP的POST、PUT等方法, FTP 上传, kerberos认证,HTTP上传,代理服务器,cookies,用户名/密码认证, 下载文件断点续传,上载文件断点续传, http代理服务器管道( proxy tunneling),还支持IPv6,socks5代理服务器,通过http代理服务器上传文件到FTP服务器等,功能十分强大
格式:
curl [options] [URL...]
常见选项:
-A/--user-agent <string> 设置用户代理发送给服务器 -e/--referer <URL> 来源网址 --cacert <file> CA证书 (SSL) -k/--insecure 允许忽略证书进行 SSL 连接 --compressed 要求返回是压缩的格式 -H/--header "key:value” 自定义首部字段传递给服务器 -i 显示页面内容,包括报文首部信息 -I/--head 只显示响应报文首部信息 -D/--dump-header <file>将url的header信息存放在指定文件中 --basic 使用HTTP基本认证 -u/--user <user[:password]>设置服务器的用户和密码 -L 如果有3xx响应码,重新发请求到新位置 -O 使用URL中默认的文件名保存文件到本地 -o <file> 将网络文件保存为指定的文件中 --limit-rate <rate> 设置传输速度 -0/--http1.0 数字0,使用HTTP 1.0 -v/--verbose 更详细 -C 选项可对文件使用断点续传功能 -c/--cookie-jar <file name> 将url中cookie存放在指定文件中 -x/--proxy <proxyhost[:port]> 指定代理服务器地址 -X/--request <command> 向服务器发送指定请求方法 -U/--proxy-user <user:password> 代理服务器用户和密码 -T 选项可将指定的本地文件上传到FTP服务器上 --data/-d 方式指定使用POST方式传递数据 -s --silent Silent mode -b name=data 从服务器响应set-cookie得到值,返回给服务器 -w <format> 显示相应的指定的报文信息,如:%{http_code},%{remote_ip}等 -m, --max-time <time> 允许最大传输时间
范例:
[root@centos8 ~]#curl -I http://www.163.com HTTP/1.1 403 Forbidden Date: Thu, 12 Dec 2019 01:18:11 GMT Content-Type: text/html Content-Length: 234 Connection: keep-alive Server: web cache Expires: Thu, 12 Dec 2019 01:18:11 GMT X-Ser: BC14_lt-tianjin-tianjin-3-cache-3 Cache-Control: no-cache,no-store,private cdn-user-ip: 123.118.223.243 cdn-ip: 125.39.21.14 X-Cache-Remote: HIT cdn-source: baishan [root@centos8 ~]#curl -I -A ie10 http://www.163.com HTTP/1.1 200 OK Date: Thu, 12 Dec 2019 01:19:30 GMT Content-Type: text/html; charset=GBK Connection: keep-alive Expires: Thu, 12 Dec 2019 01:20:45 GMT Server: nginx Cache-Control: no-cache,no-store,private Age: 5 Vary: Accept-Encoding X-Ser: BC20_dx-lt-yd-fujian-xiamen-8-cache-2, BC57_dx-lt-yd-fujian-xiamen-8- cache-2, BC5_lt-tianjin-tianjin-3-cache-3, BC13_lt-tianjin-tianjin-3-cache-3 cdn-user-ip: 123.118.223.243 cdn-ip: 125.39.21.13 X-Cache-Remote: HIT cdn-source: baishan [root@centos6 ~]#curl -H "user-agent: firefox" 192.168.100.8
范例:利用curl 获取响应码和远程主机IP
[root@ubuntu ~]#curl -s -I -m10 -o /dev/null -w %{http_code} http://www.baidu.com/ 200 [root@ubuntu ~]#curl -s -I -m10 -o /dev/null -w %{remote_ip} http://cicin.com/ 58.87.87.99 [root@centos8 ~]#curl -s -I -m10 -o /dev/null -w %{local_ip} http://cicin.com/ 10.0.0.8 [root@centos8 ~]#curl -s -I -m10 -o /dev/null -w %{local_port} http://cicin.com/ 45304 [root@centos8 ~]#curl -s -I -m10 -o /dev/null -w %{remote_port} http://cicin.com/ 80
5.4 httpie
HTTPie 工具是现代的 HTTP 命令行客户端,它能通过命令行界面与 Web 服务进行交互。它提供一个简单的 http 命令,允许使用简单而自然的语法发送任意的 HTTP 请求,并会显示彩色的输出
HTTPie 能用于测试、调试及与 HTTP 服务器交互。
主要特点:
- 具表达力的和直观语法
- 格式化的及彩色化的终端输出
- 内置 JSON 支持
- 表单和文件上传
- HTTPS、代理和认证
- 任意请求数据
- 自定义头部
- 持久化会话
- 类似 wget 的下载
- 支持 Python 2.7 和 3.x
官方网站:https://httpie.org
安装:基于EPEL(CentOS 8 目前还不支持)
yum install httpie
范例:查看帮助
[root@Centos7 ~]#http --help usage: http [--json] [--form] [--pretty {all,colors,format,none}] [--style STYLE] [--print WHAT] [--headers] [--body] [--verbose] [--all] [--history-print WHAT] [--stream] [--output FILE] [--download] [--continue] [--session SESSION_NAME_OR_PATH | --session-read-only SESSION_NAME_OR_PATH] [--auth USER[:PASS]] [--auth-type {basic,digest}] [--proxy PROTOCOL:PROXY_URL] [--follow] [--max-redirects MAX_REDIRECTS] [--timeout SECONDS] [--check-status] [--verify VERIFY] [--ssl {ssl2.3,ssl3,tls1,tls1.1,tls1.2}] [--cert CERT] [--cert-key CERT_KEY] [--ignore-stdin] [--help] [--version] [--traceback] [--debug] [METHOD] URL [REQUEST_ITEM [REQUEST_ITEM ...]]
范例:
# 显示信息(包含响应头200) http www.ciciedu.com # 显示详细的请求(包含请求和返回头200) http -v www.ciciedu.com # 只显示Header http -h www.ciciedu.com http --head www.ciciedu.com http --header www.ciciedu.com http --headers www.ciciedu.com # 只显示Body http -b www.ciciedu.com http --body ciciedu.com # 下载文件 http -d www.ciciedu.com # 模拟提交表单 http -f POST www.ciciedu.com username='wang' # 请求删除的方法 http DELETE www.ciciedu.com # 传递JSON数据请求(默认就是JSON数据请求) http PUT www.ciciedu.com username='wang' password='ciciedu' # 如果JSON数据存在不是字符串则用:=分隔,例如 http PUT www.ciciedu.com username='wang' password='ciciedu' age:=30 a:=true streets:='["a", "b"]' # 模拟Form的Post请求, Content-Type: application/x-www-form-urlencoded; charset=utf-8 http --form POST www.ciciedu.com username='wang' # 模拟Form的上传, Content-Type: multipart/form-data http -f POST www.ciciedu.com/jobs username='wang' file@~/test.pdf # 修改请求头, 使用:分隔 http www.ciciedu.com User-Agent:ciciedu-agent/1.0 'Cookie:a=b;b=c' Referer:http://www.google.com/ # 认证 http -a username:password www.ciciedu.com http -A basic -a username:password www.ciciedu.com # 使用http代理 http --proxy=http:http://172.16.0.100:8081 proxy.ciciedu.com http --proxy=http:http://user:[email protected]:8081 proxy.ciciedu.com http --proxy=https:http://172.16.0.100:8118 proxy.ciciedu.com http --proxy=https:http://user:[email protected]:8118 proxy.ciciedu.com
范例:查看信息及响应头
[root@centos7 ~]#http 192.168.8.8/test.html HTTP/1.1 200 OK Accept-Ranges: bytes Connection: Keep-Alive Content-Length: 30 Content-Type: text/html; charset=UTF-8 Date: Thu, 07 Nov 2019 09:09:34 GMT ETag: "1e-596be05bc9a34" Keep-Alive: timeout=5, max=100 Last-Modified: Thu, 07 Nov 2019 09:09:27 GMT Server: Apache/2.4.37 (centos) <strong>马哥教育</strong>
范例:查看请示和响应头部及信息
[root@centos7 ~]#http -v 192.168.8.8/test.html GET /test.html HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate Connection: keep-alive Host: 192.168.8.8 User-Agent: HTTPie/0.9.4 HTTP/1.1 200 OK Accept-Ranges: bytes Connection: Keep-Alive Content-Length: 30 Content-Type: text/html; charset=UTF-8 Date: Thu, 07 Nov 2019 09:09:39 GMT ETag: "1e-596be05bc9a34" Keep-Alive: timeout=5, max=100 Last-Modified: Thu, 07 Nov 2019 09:09:27 GMT Server: Apache/2.4.37 (centos) <strong>马哥教育</strong>
范例:查看响应报文头部
[root@centos7 ~]#http HEAD http://www.ciciedu.com HTTP/1.1 200 OK Connection: keep-alive Content-Encoding: gzip Content-Type: text/html; charset=UTF-8 Date: Thu, 07 Nov 2019 08:09:49 GMT Link: <http://www.ciciedu.com/wp-json/>; rel="https://api.w.org/" Link: <http://www.ciciedu.com/>; rel=shortlink Server: Tengine Vary: Accept-Encoding Vary: Accept-Encoding, Cookie
范例: 查看请求和响应报文头部
[root@centos7 ~]#http -p Hh http://www.ciciedu.com
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: www.ciciedu.com
User-Agent: HTTPie/0.9.4
HTTP/1.1 200 OK
Cache-Control: max-age=3, must-revalidate
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=UTF-8
Date: Thu, 07 Nov 2019 03:44:14 GMT
Server: Tengine
Transfer-Encoding: chunked
Vary: Accept-Encoding
Vary: Accept-Encoding, Cookie
范例:指定请求头部的首部字段
[root@centos7 ~]#http -p H http://www.ciciedu.com User-Agent:wangtest Referer:http://www.baidu.com GET / HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate Connection: keep-alive Host: www.ciciedu.com Referer: http://www.baidu.com User-Agent: wangtest
范例:下载资源
#方法1 [root@centos7 ~]#http http://www.ciciedu.com/wpcontent/uploads/2018/12/2018122312035677.png > logo.png #方法2 [root@centos7 ~]#file logo.png logo.png: PNG image data, 411 x 127, 8-bit/color RGBA, non-interlaced [root@centos7 ~]#http --download http://www.ciciedu.com/wpcontent/uploads/2018/12/2018122312035677.png HTTP/1.1 200 OK Accept-Ranges: bytes Cache-Control: max-age=604800 Connection: keep-alive Content-Length: 8983 Content-Type: image/png Date: Thu, 07 Nov 2019 08:20:44 GMT ETag: "5c1f79ac-2317" Expires: Thu, 14 Nov 2019 08:20:44 GMT Last-Modified: Sun, 23 Dec 2018 12:03:56 GMT Server: Tengine Vary: Accept-Encoding Downloading 8.77 kB to "2018122312035677.png" Done. 8.77 kB in 0.00091s (9.46 MB/s)
范例:用POST方法提交json格式的数据
[root@centos7 ~]#http http://www.ciciedu.com user=wang password=ciciedu
范例:用POST方法,指交表单数据
[root@centos7 ~]#http -f POST http://www.ciciedu.com user=wang password=ciciedu
5.5 压力测试工具
httpd的压力测试工具:
- ab, webbench, http_load, seige
- Jmeter 开源
- Loadrunner 商业,有相关认证
- tcpcopy:网易,复制生产环境中的真实请求,并将之保存
ab 来自httpd-tools包
命令格式
ab [OPTIONS] URL
常见选项
-n:总请求数
-c:模拟的并发数
-k:以持久连接模式测试
说明:并发数高于1024时,需要用 ulimit –n # 调整能打开的文件数
5.6 httpd自带的工具程序
htpasswd:basic认证基于文件实现时,用到的账号密码文件生成工具
apachectl:httpd自带的服务控制脚本,支持start和stop
rotatelogs:日志滚动工具
access.log --> access.log, access.1.log --> access.log, acccess.1.log, access.2.log
摘要:本文介绍LAMP架构
[toc]
实现LAMP架构
本章内容
- LAMP介绍
- PHP配置
- 实现LAMP应用数据库管理系统phpMyadmin
- 实现LAMP应用博客系统wordpress
- 实现LAMP应用论坛系统Discuz!
- 实现LAMP应用PowerDNS
- opcache等PHP加速器
- PHP-FPM模式
- 源码编译安装实现LAMP
1 LAMP介绍
1.1 动态资源与语言
*WEB 资源类型*:
- 静态资源:原始形式与响应内容一致,在客户端浏览器执行
- 动态资源:原始形式通常为程序文件,需要在服务器端执行之后,将执行结果返回给客户端
注意:静态和动态的区别,不在于网页是否能动态变化,而在于服务端的页面文件和客户端得到页面文件是否一致
范例:静态资源
#客户端主机现在的时间: vim /var/www/html/test.html <script type="text/javascript"> document.write(new Date()); </script>
WEB 相关语言
客户端技术: html,javascript,css
服务器端技术:php,python,javascript(Node.js),jsp,asp,Perl、Ruby
1.2 LAMP架构组成
LAM(M)P:
- L:linux
- A:apache (httpd)
- M:mysql, mariadb
- P:php, perl, python
1.3 CGI和fastcgi
1.3.1 CGI
CGI:Common Gateway Interface 公共网关接口
CGI 在2000年或更早的时候用得比较多,以前web服务器一般只处理静态的请求,如果碰到一个动态请求怎么办呢?web服务器会根据这次请求的内容,然后会 fork 一个新进程来运行外部的 C 程序或者bash,perl脚本等,这个进程会把处理完的数据返回给web服务器,最后web服务器把内容发送给用户,刚才fork的进程也随之退出。 如果下次用户还请求改动态脚本,那么web服务器又再次fork一个新进程,周而复始的进行。
CGI 可以让一个客户端,从网页浏览器通过http服务器向执行在网络服务器上的程序传输数据;CGI描述了客户端和服务器程序之间传输的一种标准
请求流程 :
Client – (http协议) –> httpd – (cgi协议) –> application server (program file) – (mysql协议) –> mysql
范例:httpd 利用CGI运行shell脚本
[root@centos8 ~]#vim /etc/httpd/conf/httpd.conf ...省略... <directory /data/script> require all granted </directory> <IfModule alias_module> ...省略... #ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" ScriptAlias /sh/ "/data/script/" #/sh/是/data/script/的别名 </IfModule> <directory /data/script> require all granted </directory> ...省略... [root@centos8 ~]#cat /data/script/cgi.sh #!/bin/bash # cat << EOF Content-Type: text/html #响应报文的内容 <pre> My username is: $(id -un) My id is: $(id -u) My shell settings are: $(set) My environment variables are: $(env) Here is the file in /etc: $(ls -l /etc/redhat-release ) $( cat /etc/redhat-release ) </pre> EOF [root@centos8 ~]#chmod +x /data/script/cgi.sh [root@centos8 ~]#ll /data/script/cgi.sh -rwxr-xr-x 1 root root 269 Dec 21 21:08 /data/script/cgi.sh [root@centos8 ~]#curl http://10.0.0.8/sh/cgi.sh <pre> My username is: apache My id is: 48 My shell settings are: BASH=/bin/bash BASHOPTS=cmdhist:complete_fullquote:extquote:force_fignore:hostcomplete:interact ive_comments:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() BASH_LINENO=([0]="0") BASH_SOURCE=([0]="/data/script/cgi.sh") BASH_VERSINFO=([0]="4" [1]="4" [2]="19" [3]="1" [4]="release" [5]="x86_64- redhat-linux-gnu") BASH_VERSION='4.4.19(1)-release' CONTEXT_DOCUMENT_ROOT=/data/script/ CONTEXT_PREFIX=/sh/ DIRSTACK=() DOCUMENT_ROOT=/var/www/html EUID=48 GATEWAY_INTERFACE=CGI/1.1 GROUPS=() HOSTNAME=centos8.localdomain HOSTTYPE=x86_64 HTTP_ACCEPT='*/*' HTTP_HOST=10.0.0.8 HTTP_USER_AGENT=curl/7.61.1 IFS=$' \t\n' MACHTYPE=x86_64-redhat-linux-gnu OPTERR=1 OPTIND=1 OSTYPE=linux-gnu PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin PPID=11692 PS4='+ ' PWD=/data/script QUERY_STRING= REMOTE_ADDR=10.0.0.8 REMOTE_PORT=56396 REQUEST_METHOD=GET REQUEST_SCHEME=http REQUEST_URI=/sh/cgi.sh SCRIPT_FILENAME=/data/script/cgi.sh SCRIPT_NAME=/sh/cgi.sh SERVER_ADDR=10.0.0.8 SERVER_ADMIN=root@localhost SERVER_NAME=10.0.0.8 SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.1 SERVER_SIGNATURE= SERVER_SOFTWARE='Apache/2.4.37 (centos)' SHELL=/sbin/nologin SHELLOPTS=braceexpand:hashall:interactive-comments SHLVL=1 TERM=dumb UID=48 UNIQUE_ID=Xf4ZhJSefdICWmRjEggE1wAAAAg _=/bin/bash My environment variables are: HTTP_HOST=10.0.0.8 CONTEXT_DOCUMENT_ROOT=/data/script/ HTTP_USER_AGENT=curl/7.61.1 SERVER_ADMIN=root@localhost CONTEXT_PREFIX=/sh/ SERVER_PORT=80 SERVER_NAME=10.0.0.8 QUERY_STRING= SCRIPT_FILENAME=/data/script/cgi.sh PWD=/data/script HTTP_ACCEPT=*/* REQUEST_METHOD=GET SERVER_SIGNATURE= SCRIPT_NAME=/sh/cgi.sh REMOTE_PORT=56396 UNIQUE_ID=Xf4ZhJSefdICWmRjEggE1wAAAAg DOCUMENT_ROOT=/var/www/html SHLVL=1 SERVER_PROTOCOL=HTTP/1.1 REQUEST_URI=/sh/cgi.sh PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin SERVER_ADDR=10.0.0.8 GATEWAY_INTERFACE=CGI/1.1 REQUEST_SCHEME=http REMOTE_ADDR=10.0.0.8 SERVER_SOFTWARE=Apache/2.4.37 (centos) _=/usr/bin/env Here is the file in /etc: lrwxrwxrwx. 1 root root 14 Aug 14 14:42 /etc/redhat-release -> centos-release CentOS Linux release 8.0.1905 (Core) </pre> #观察错误日志 [root@centos8 ~]#tail /var/log/httpd/error_log #修改cgi.sh最后加一行sleep 100 [root@centos8 ~]#vim /data/script/cgi.sh [root@centos8 ~]#tail -3 /data/script/cgi.sh </pre> EOF rm -rf /data/script sleep 100 #再次运行后,可以观察到下面进程树 [root@centos8 ~]#curl http://10.0.0.8/sh/cgi.sh
如果多次访问,可以看到开启了多个子进程
1.3.2 fastcgi
fastcgi的方式是,web服务器收到一个请求时,不会重新fork一个进程(因为这个进程在web服务器启动时就开启了,而且不会退出),web服务器直接把内容传递给这个进程(进程间通信,但fastcgi使用了别的方式,tcp方式通信),这个进程收到请求后进行处理,把结果返回给web服务器,最后自己接着等待下一个请求的到来,而不是退出
请求流程 :
Client – (http协议) –> httpd – (fastcgi协议) –> fastcgi服务器 –(mysql协议) –> mysql
1.3.3 CGI和fastcgi 比较
CGI: 兼职, 一次性的过河拆迁式服务
FASTCGI: 专职,全周期的持续式服务
名称 | 在web服务器方面 | 在对数据进行处理的进程方面 |
---|---|---|
cgi | fork一个新的进程进行处理 | 读取参数,处理数据,然后就结束生命期 |
fastcgi | 用tcp方式跟远程机子上的进程或本地进程建立连接 | 要开启TCP端口,进入循环,等待数据的到来,处理数据 |
1.4 PHP
1.4.1 PHP 简介
PHP官网:http://www.php.net/
PHP是通用服务器端脚本编程语言,*主要用于web开发实现动态web页面*,也是最早实现将脚本嵌入HTML源码文档中的服务器端脚本语言之一。同时,php还提供了一个命令行接口,因此,其也可以在大多数系统上作为一个独立的shell来使用
Rasmus Lerdorf于1994年开始开发PHP,最初是一组被Rasmus Lerdorf称作“Personal Home Page Tool” 的Perl脚本, 可以用于显示作者的简历并记录用户对其网站的访问。后来,Rasmus Lerdorf 使用 C语言将这些Perl脚本重写为CGI程序,还为其增加了运行Web forms的能力以及与数据库交互的特性,并将其重命名为“Personal Home Page/Forms Interpreter”或“PHP/FI”。此时,PHP/FI已经可以用于开发简单的动态web程序了,这即PHP1.0。1995年6月,Rasmus Lerdorf把它的PHP发布于comp.infosystems.www.authoring.cgi Usenet讨论组,从此PHP开始走进人们的视野。1997年,其2.0版本发布
1997年,两名以色列程序员Zeev Suraski和Andi Gutmans重写的PHP的分析器(parser)成为PHP发展到3.0的基础,而且从此将PHP重命名为PHP: Hypertext Preprocessor。此后,这两名程序员开始重写整个PHP核心,并于1999年发布了Zend Engine 1.0,这也意味着PHP 4.0的诞生。2004年7月,Zend Engine 2.0发布,由此也将PHP带入了PHP 5时代。PHP5包含了许多重要的新特性,如增强的面向对象编程的支持、支持PDO(PHP Data Objects)扩展机制以及一系列对PHP性能的改进
Zend Engine是开源的、PHP脚本语言的解释器,它最早是由以色列理工学院(Technion)的学生Andi Gutmans和Zeev Suraski所开发,Zend也正是此二人名字的合称。后来两人联合创立了Zend Technologies公司
Zend Engine 1.0于1999年随PHP 4发布,由C语言开发且经过高度优化,并能够做为PHP的后端模块使用。Zend Engine为PHP提供了内存和资源管理的功能以及其它的一些标准服务,其高性能、可靠性和可扩展性在促进PHP成为一种流行的语言方面发挥了重要作用
Zend Engine的出现将PHP代码的处理过程分成了两个阶段:首先是分析PHP代码并将其转换为称作Zend opcode的二进制格式opcode(类似Java的字节码),并将其存储于内存中;第二阶段是使用Zend Engine去执行这些转换后的Opcode
php各种版本官方支持时间:
1.4.2 PHP的Opcode语言
Opcode是一种PHP脚本编译后的中间语言,类似于Java的ByteCode,或者.NET的MSL
PHP的语言引擎Zend执行PHP脚本代码一般会经过如下4个步骤
1、Scanning 词法分析,将PHP代码转换为语言片段(Tokens)
2、Parsing 语义分析,将Tokens转换成简单而有意义的表达式
3、Compilation 将表达式编译成Opcode
4、Execution 顺次执行Opcode,每次一条,从而实现PHP脚本的功能
即:扫描–>分析–>编译–>执行
1.4.3 php配置
php 的配置文件:/etc/php.ini, /etc/php.d/*.ini
配置文件在php解释器启动时被读取
对配置文件的修改生效方法
- Modules:重启httpd服务
- FastCGI:重启php-fpm服务
*/etc/php.ini配置文件格式*:
[foo]:Section Header directive = value
注释符:
- 以#开头,纯粹的注释信息
- 以 ; 开头,用于注释可启用的directive
提示:较新的版本中,已经完全使用 “ ; ” 进行注释
*php.ini 配置参考文档*:
php.ini的核心配置选项文档: http://php.net/manual/zh/ini.core.php
php.ini配置选项列表:http://php.net/manual/zh/ini.list.php
php常见设置:
expose_php = On #响应报文显示首部字段x-powered-by: PHP/x.y.z,暴露php版本,建议为off max_execution_time= 30 #最长执行时间30s memory_limit=128M #生产不够,可调大 display_errors=off #调试使用,不要打开,否则可能暴露重要信息 display_startup_errors=off #建议关闭 post_max_size=8M #最大上传数据大小,生产可能调大,比下面项大 upload_max_filesize =2M #最大上传文件,生产可能要调大 max_file_uploads = 20 #同时上传最多文件数 date.timezone =Asia/Shanghai #指定时区 short_open_tag=on #开启短标签,如: <? phpinfo();?>
范例:
[root@centos7 ~]#yum -y install httpd php [root@centos7 ~]#systemctl start httpd [root@centos7 ~]#cat /var/www/html/test.php <?php phpinfo(); ?> [root@centos7 ~]#cat /var/www/html/session.php <?php session_start(); echo session_id(); ?> [root@centos6 ~]#curl -I 10.0.0.7/test.php HTTP/1.1 200 OK date: Thu, 02 Apr 2020 04:02:57 GMT server: Apache/2.4.6 (CentOS) PHP/5.4.16 x-powered-by: PHP/5.4.16 # 暴露PHP版本信息 content-type: text/html; charset=UTF-8 cache-control: private [root@centos7 ~]#vim /etc/php.ini expose_php = Off [root@centos7 ~]#systemctl restart httpd [root@centos6 ~]#curl -I 10.0.0.7/test.php HTTP/1.1 200 OK date: Thu, 02 Apr 2020 04:03:59 GMT server: Apache/2.4.6 (CentOS) content-type: text/html; charset=UTF-8 cache-control: private #生成会话信息 [root@centos6 ~]#curl http://10.0.0.7/session.php 9eun59j4a7j9f115cfr7dl14c2 [root@centos6 ~]#curl http://10.0.0.7/session.php 6tknsvrnn1lqgt9j3t9lue19p7 #查看生成的会话文件 [root@centos7 ~]#ll -d /var/lib/php/session #需要一定的权限 drwxrwx--- 2 root apache 6 Apr 1 12:11 /var/lib/php/session [root@centos7 ~]#ll /var/lib/php/session total 0 -rw------- 1 apache apache 0 Jun 29 14:46 sess_6tknsvrnn1lqgt9j3t9lue19p7 -rw------- 1 apache apache 0 Jun 29 14:43 sess_9eun59j4a7j9f115cfr7dl14c2
1.4.4 PHP语言格式
php语言有两种使用格式:
格式 1
<?php echo "<h1>Hello world!</h1>" ?>
格式 2
<h1> <?php echo "Hello world!" ?> </h1>
1.4.5 php测试代码
[root@centos8 ~]# cat /var/www/html/phpinfo.php <?php echo date("Y/m/d H:i:s"); phpinfo(); ?> [root@centos8 ~]#curl 127.0.0.1/phpinfo.php [root@centos8 ~]#cat ./phpinfo.php #!/bin/php <?php phpinfo(); ?> [root@centos8 ~]#chmod +x ./phpinfo.php [root@centos8 ~]#./phpinfo.php
1.5 LAMP实现方式
httpd 接收用户的web请求;静态资源则直接响应;动态资源为php脚本,对此类资源的请求将交由php来运行
httpd与php结合的方式
- modules :将php编译成为httpd的模块libphp5.so,只有prefork 模式才支持
- FastCGI
LAMP架构实现
静态资源:
Client – http –> httpd
动态资源:
Client – http –> httpd –> libphp5.so () – mysql –> MySQL server
Client – http –> httpd –>fastcgi– mysql –> MySQL server
2 实现LAMP
2.1 利用rpm包实现LAMP安装部署
CentOS 8
Module 模块方式
dnf install httpd mariadb-server php php-mysqlnd
FastCGI 方式
dnf install httpd mariadb-server php-fpm php-mysqlnd
CentOS 7
Module 模块方式
yum install httpd mariadb-server php php-mysql
FastCGI 方式
yum install httpd php-fpm php-mysql mariadb-server
CentOS 6:
Module 模块方式
yum install httpd, php, php-mysql, mysql-server
FastCGI方式:默认不支持
注意:基于module实现,httpd 需要 使用prefork模型
2.2 PHP连接MySQL的方式
2.2.1 使用mysql扩展连接数据库
使用mysql扩展模块mysql.so连接数据,此方式已经在php 7 版后淘汰
范例:php使用mysql扩展连接数据库的测试代码
<?php $conn = mysql_connect('mysqlserver','username','password'); if ($conn) echo "OK"; else echo "Failure"; #echo mysql_error(); mysql_close(); ?>
2.2.2 使用mysqli扩展连接数据库
使用mysqli扩展模块mysqli.so连接数据,此方式只能连接MySQL数据库,不支持其它数据库
范例:php使用mysqli扩展连接数据库的测试代码
<?php $mysqli=new mysqli("mysqlserver", "username", "password"); if(mysqli_connect_errno()){ echo "Failure"; $mysqli=null; exit; } echo "OK"; $mysqli->close(); ?>
- 2.2.3 使用PDO(PHP Data Object)扩展连接数据库
使用PDO扩展模块pdo_mysql.so连接数据库,此方式可以支持连接MySQL,Oracle等多种数据库
范例:php使用pdo扩展连接数据库的测试代码1
<?php $dsn='mysql:host=mysqlhost;port=3306;dbname=mysql'; $username='root'; $passwd='cici'; $dbh=new PDO($dsn,$username,$passwd); var_dump($dbh); ?>
范例:php使用pdo扩展连接数据库的测试代码2
<?php try { $user='root'; $pass='cici'; $dbh = new PDO('mysql:host=mysqlhost;port=3306;dbname=mysql', $user, $pass); foreach($dbh->query('SELECT user,host from user') as $row) { print_r($row); } $dbh = null; } catch (PDOException $e) { print "Error!: " . $e->getMessage() . "<br/>"; die(); } ?>
2.3 实现LAMP实战案例
范例:CentOS 8 默认使用factcgi模式,可以按下面步骤修改为httpd的模块方式(不建议)
[root@centos8 ~]#dnf -y install httpd php php-mysqlnd mariadb-server #修改为prefork模式支持httpd 模块方式 [root@centos8 ~]#vim /etc/httpd/conf.modules.d/00-mpm.conf LoadModule mpm_prefork_module modules/mod_mpm_prefork.so #LoadModule mpm_worker_module modules/mod_mpm_worker.so #LoadModule mpm_event_module modules/mod_mpm_event.so #CentOS 8的php 默认是factcgi模式 ,修改为httpd模块方式,此步非必须,是可选做 [root@centos8 html]#vim /etc/httpd/conf.d/php.conf #<IfModule !mod_php5.c> # <IfModule !mod_php7.c> # # Enable http authorization headers # SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 # # <FilesMatch \.(php|phar)$> # SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost" # </FilesMatch> # </IfModule> #</IfModule> [root@centos8 ~]#vim /var/www/html/lamp.php [root@centos8 ~]#cat /var/www/html/lamp.php <?php try { $user='root'; $pass=''; $dbh = new PDO('mysql:host=localhost;dbname=mysql', $user, $pass); foreach($dbh->query('SELECT user,host from user') as $row) { print_r($row); } $dbh = null; } catch (PDOException $e) { print "Error!: " . $e->getMessage() . "<br/>"; die(); } phpinfo(); ?> [root@centos8 ~]#systemctl start httpd mariadb
打开chrome浏览器,访问 http://httpd服务器ip/lamp.php 可以看到如下页面,说明LAMP 搭建成功
3 常见LAMP应用实现
3.1 常见LAMP应用介绍
- PhpMyAdmin是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库,官网:https://www.phpmyadmin.net/
- WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可把 WordPress当作一个内容管理系统(CMS)来使用,官网:https://cn.wordpress.org/
- PHPWind是2003年发布了PHPWind的前身版本ofstar,并发展成为包含BBS、CMS、博客、SNS等一系列程序的通用型建站软件, 于2008年加入阿里巴巴集团,官网:https://www.phpwind.net/
- Crossday Discuz! Board(简称 Discuz!)是一套通用的社区论坛软件系统。自2001年6月面世以来,是覆盖率最大的论坛软件系统之一。2010年8月23日与腾讯达成收购协议,官网:https://www.discuz.net/
- PowerDNS 是一个跨平台的开源DNS服务组件,它是高性能的域名服务器,除了支持普通的BIND配置文件,PowerDNS还可从MySQL,Oracle,PostgreSQL等的数据库读取数据。PowerDNS安装了Poweradmin(基于php实现),能实现Web管理DNS记录,非常方便
- ECShop是一款B2C独立网店系统,适合企业及个人快速构建个性化网上商店。系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序。2006年6月,ECShop推出第一个版本1.0
3.2 实现 phpMyadmin应用部署
范例:CentOS 8 部署 phpMyAdmin-5.0.1
[root@centos8 ~]#yum -y install httpd mariadb-server php php-mysqlnd php-json [root@centos8 ~]#systemctl start httpd mariadb [root@centos8 ~]#mysql_secure_installation [root@centos8 ~]#unzip phpMyAdmin-5.0.1-all-languages.zip [root@centos8 ~]#mv phpMyAdmin-5.0.1-all-languages /var/www/html/pma #如果出错,可以查看日志 [root@centos8 ~]#tail /var/log/php-fpm/www-error.log #浏览器访问http://LAMP服bash务器IP/pma/
范例:CentOS 7 利用清华Yum源安装php 7.4 部署 phpMyAdmin-5.0.2
[root@centos7 ~]#yum -y install https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm [root@centos7 ~]#yum -y install httpd php74-php php74-php-mbstring php74-phpmysqlnd mariadb-server unzip [root@centos7 ~]#systemctl enable --now httpd mariadb [root@centos7 ~]#mysqladmin password cici [root@centos7 ~]#wget https://files.phpmyadmin.net/phpMyAdmin/5.0.2/phpMyAdmin-5.0.2-all-languages.zip [root@centos7 ~]#unzip phpMyAdmin-5.0.2-all-languages.zip [root@centos7 ~]#mv phpMyAdmin-5.0.2-all-languages/ /var/www/html/pma #浏览器访问http://LAMP服务器IP/pma/
范例:CentOS 7 利用清华Yum源安装php 7.2 部署 phpMyAdmin-5.0.1
yum -y install https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remirelease-7.rpm yum -y install httpd php72-php php72-php-mbstring php72-php-mysqlnd mariadb-server systemctl start httpd mariadb wget https://files.phpmyadmin.net/phpMyAdmin/5.0.1/phpMyAdmin-5.0.1-alllanguages.zip yum install unzip -y unzip phpMyAdmin-5.0.1-all-languages.zip cd phpMyAdmin-5.0.1-all-languages/ mv phpMyAdmin-5.0.1-all-languages /var/www/html/pma #设置mysql的root密码,phpMyadmin不允许空密码登录 mysql_secure_installation #浏览器访问http://LAMP服务器IP/pma/
范例:CentOS 7 利用RPM包部署phpMyadmin4.4
[root@centos7 ~]#yum -y install httpd mariadb-server php php-mysql [root@centos7 ~]#systemctl start mariadb [root@centos7 ~]#mysql_secure_installation #下载:https://www.phpmyadmin.net/downloads/ [root@centos7 ~]#unzip phpMyAdmin-4.4.15.10-all-languages.zip [root@centos7 ~]#mv phpMyAdmin-4.4.15.10-all-languages /var/www/html/phpmyadmin [root@centos7 ~]#cd /var/www/html/phpmyadmin/ [root@centos7 ~]#cp config.sample.inc.php config.inc.php #如果mysql 服务器和phpmyadmin不在同一台主机,还需要修改以下设置 [root@centos7 ~]#vim config.inc.php $cfg['Servers'][$i]['host'] = 'mysqlserverIP'; [root@centos7 ~]#yum -y install php-mbstring [root@centos7 ~]#systemctl start httpd #浏览器访问:http://LAMP服务器IP/phpmyadmin,输入root及口令即可登录
3.3 实现 wordpress 应用部署
范例:CentOS 8 利用RPM包部署 wordpress
[root@centos8 ~]#dnf -y install httpd php php-json php-mysqlnd mariadb-server [root@centos8 ~]#systemctl enable --now httpd mariadb #创建数据库和账号 [root@centos8 ~]#mysql MariaDB [(none)]> create database wordpress; MariaDB [(none)]> grant all on wordpress.* to wordpress@'localhost' identified by 'cici'; #或者 [root@centos8 ~]#mysql -e 'create database wordpress;grant all on *.* to wordpress@"10.0.0.%" identified by "cici"' [root@centos8 ~]#wget https://cn.wordpress.org/latest-zh_CN.zip [root@centos8 ~]#tar xvf wordpress-5.4.2-zh_CN.tar.gz [root@centos8 ~]#mv wordpress/* /var/www/html/ [root@centos8 ~]#chown -R apache.apache /var/www/html/ #或者 [root@centos8 ~]#setfacl -Rm u:apache:rwx /var/www/html/wp-content/ #浏览器访问 http://LAMP服务器/wordpress
#安全加固 #用浏览器访问https://api.wordpress.org/secret-key/1.1/salt/,替代下面wp-config.php内容 [root@centos8 ~]#vim /var/www/html/wp-config.php
范例:CentOS 7 利用RPM包部署wordpress
#下载官网地址:https://cn.wordpress.org/ #解压缩WordPress博客程序到网页站点目录下 unzip wordpress-5.1.1-zh_CN.zip mv wordpress /var/www/html/ #新建wpdb库和wpuser用户 mysql> create database wpdb; mysql> grant all on wpdb.* to wpuser@'%' identified by "wppass"; setfacl –R –m u:apache:rwx /var/www/html/wordpress/ #或者chown –R apache.apache /var/www/html/wordpress #打开http://LAMP服务器IP/wordpress进行页面安装
3.4 实现 Discuz!应用部署
范例:CentOS 8 利用RPM包部署Discuz!
[root@centos8 ~]#dnf -y install httpd php php-xml php-mysqlnd mariadb-server [root@centos8 ~]#unzip Discuz_X3.4_SC_UTF8【20191201】.zip [root@centos8 ~]#mv upload/ /var/www/html/forum [root@centos8 ~]#chown -R apache.apache /var/www/html/forum [root@centos8 ~]#mysql MariaDB [ultrax]> create database ultrax; MariaDB [ultrax]> grant all on ultrax.* to ultrax@'localhost' identified by 'cici';
范例:CentOS 7 利用RPM包部署Discuz!
#官网:http://www.discuz.net #下载源码: wget http://download.comsenz.com/DiscuzX/3.3/Discuz_X3.3_SC_UTF8.zip unzip Discuz_X3.3_SC_UTF8.zip mv upload/ /var/www/html/forum setfacl -R -m u:apache:rwx /var/www/html/forum mysql>create database discuz; mysql>grant all on discuz.* to discuz@'172.16.0.%’identified by"cici"; 安装向导:http://localhost/forum
3.5 实现 PowerDNS 应用部署
PowerDNS 是一个跨平台的开源DNS服务组件,PowerDNS为DNS数据提供纯文本文件或第三方数据库(如MySQL,PostgreSQL,Microsoft SQL Server,Oracle或Sybase)中存储的数据。PowerDNS同时有Windows和Linux/Unix的版本。 PowerDNS在Windows下可以使用 Access的mdb文件记录DNS信息,而在Linux/Unix下则常使用MySQL来记录DNS信息。
Poweradmin 是为 PowerDNS 服务器的提供基于PHP语言实现的 Web 界面的DNS 管理工具。此工具支持 PowerDNS 的主要功能。
PowerDNS官网:https://www.powerdns.com/
PowerDNS文档:https://doc.powerdns.com/
Poweradmin官网:http://www.poweradmin.org/
范例:CentOS 8 利用RPM包部署PowerDNS(目前20200311,不支持powerdns,缺少相关php包)
[root@centos8 ~]#yum install -y pdns pdns-backend-mysql mariadb-server [root@centos8 ~]#systemctl start mariadb [root@centos8 ~]#mysql < pdns.sql [root@centos8 ~]#vim /etc/pdns/pdns.conf launch=gmysql gmysql-host=localhost gmysql-port=3306 gmysql-dbname=powerdns gmysql-user=powerdns gmysql-password=cici [root@centos8 ~]#grep -Ev "^#|^$" /etc/pdns/pdns.conf launch=gmysql #修改此行 gmysql-host=localhost #以下行是增加 gmysql-port=3306 gmysql-dbname=powerdns gmysql-user=powerdns gmysql-password=cici setgid=pdns #以下两行不变 setuid=pdns [root@centos8 ~]#systemctl enable --now pdns [root@centos8 ~]#ss -ntlpu |grep pdns_server udp UNCONN 0 0 0.0.0.0:53 0.0.0.0:* users:(("pdns_server",pid=3073,fd=9)) udp UNCONN 0 0 [::]:53 [::]:* users:(("pdns_server",pid=3073,fd=10)) tcp LISTEN 0 128 0.0.0.0:53 0.0.0.0:* users:(("pdns_server",pid=3073,fd=11)) tcp LISTEN 0 128 [::]:53 [::]:* users:(("pdns_server",pid=3073,fd=12)) [root@centos8 ~]#yum -y install httpd php php-devel php-gd php-ldap php-mysqlnd php-odbc php-pear php-xml php-xmlrpc php-mhash gettext [root@centos8 ~]#systemctl restart httpd
范例:CentOS 7 利用RPM包部署PowerDNS
#安装包:基于EPEL源 [root@centos7 ~]#yum install -y pdns pdns-backend-mysql mariadb-server [root@centos7 ~]#rpm -ql pdns /etc/pdns /etc/pdns/pdns.conf /usr/bin/pdns_control /usr/bin/pdns_zone2ldap /usr/bin/pdnsutil /usr/bin/zone2json /usr/bin/zone2sql /usr/lib/systemd/system/pdns.service /usr/lib/systemd/system/[email protected] /usr/lib64/pdns /usr/lib64/pdns/libbindbackend.so /usr/sbin/pdns_server /usr/share/doc/pdns-4.1.11 /usr/share/doc/pdns-4.1.11/README /usr/share/licenses/pdns-4.1.11 /usr/share/licenses/pdns-4.1.11/COPYING /usr/share/man/man1/pdns_control.1.gz /usr/share/man/man1/pdns_server.1.gz /usr/share/man/man1/pdns_zone2ldap.1.gz /usr/share/man/man1/pdnsutil.1.gz /usr/share/man/man1/zone2json.1.gz /usr/share/man/man1/zone2sql.1.gz [root@centos7 ~]#systemctl enable --now mariadb #准备mariadb中的数据库,表和用户 [root@centos7 ~]#mysql MariaDB [(none)]> CREATE DATABASE powerdns; MariaDB [(none)]> GRANT ALL ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'cici'; #创建powerdns数据库中的表,参看下面文档实现 #https://doc.powerdns.com/md/authoritative/backend-generic-mysql/ use powerdns; CREATE TABLE domains ( id INT AUTO_INCREMENT, name VARCHAR(255) NOT NULL, master VARCHAR(128) DEFAULT NULL, last_check INT DEFAULT NULL, type VARCHAR(6) NOT NULL, notified_serial INT DEFAULT NULL, account VARCHAR(40) DEFAULT NULL, PRIMARY KEY (id) ) Engine=InnoDB; CREATE UNIQUE INDEX name_index ON domains(name); CREATE TABLE records ( id BIGINT AUTO_INCREMENT, domain_id INT DEFAULT NULL, name VARCHAR(255) DEFAULT NULL, type VARCHAR(10) DEFAULT NULL, content VARCHAR(64000) DEFAULT NULL, ttl INT DEFAULT NULL, prio INT DEFAULT NULL, change_date INT DEFAULT NULL, disabled TINYINT(1) DEFAULT 0, ordername VARCHAR(255) BINARY DEFAULT NULL, auth TINYINT(1) DEFAULT 1, PRIMARY KEY (id) ) Engine=InnoDB; CREATE INDEX nametype_index ON records(name,type); CREATE INDEX domain_id ON records(domain_id); CREATE INDEX recordorder ON records (domain_id, ordername); CREATE TABLE supermasters ( ip VARCHAR(64) NOT NULL, nameserver VARCHAR(255) NOT NULL, account VARCHAR(40) NOT NULL, PRIMARY KEY (ip, nameserver) ) Engine=InnoDB; CREATE TABLE comments ( id INT AUTO_INCREMENT, domain_id INT NOT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(10) NOT NULL, modified_at INT NOT NULL, account VARCHAR(40) NOT NULL, comment VARCHAR(64000) NOT NULL, PRIMARY KEY (id) ) Engine=InnoDB; CREATE INDEX comments_domain_id_idx ON comments (domain_id); CREATE INDEX comments_name_type_idx ON comments (name, type); CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); CREATE TABLE domainmetadata ( id INT AUTO_INCREMENT, domain_id INT NOT NULL, kind VARCHAR(32), content TEXT, PRIMARY KEY (id) ) Engine=InnoDB; CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind); CREATE TABLE cryptokeys ( id INT AUTO_INCREMENT, domain_id INT NOT NULL, flags INT NOT NULL, active BOOL, content TEXT, PRIMARY KEY(id) ) Engine=InnoDB; CREATE INDEX domainidindex ON cryptokeys(domain_id); CREATE TABLE tsigkeys ( id INT AUTO_INCREMENT, name VARCHAR(255), algorithm VARCHAR(50), secret VARCHAR(255), PRIMARY KEY (id) ) Engine=InnoDB; CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); #配置PowerDNS使用mariadb作为后台数据存储 [root@centos7 ~]#vim /etc/pdns/pdns.conf,查找到包含launch= 的行,修改并添加下面的内容 launch=gmysql #修改此行 gmysql-host=localhost #以下行是增加的 gmysql-port=3306 gmysql-dbname=powerdns gmysql-user=powerdns gmysql-password=cici [root@centos7 ~]#grep -Ev "^#|^$" /etc/pdns/pdns.conf launch=gmysql gmysql-host=localhost gmysql-port=3306 gmysql-dbname=powerdns gmysql-user=powerdns gmysql-password=cici setgid=pdns setuid=pdns #启动服务 [root@centos7 ~]#systemctl enable --now pdns [root@Centos7 ~]#ss -ntlu Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port udp UNCONN 0 0 *:53 *:* udp UNCONN 0 0 [::]:53 [::]:* tcp LISTEN 0 128 *:53 *:* tcp LISTEN 0 128 *:22 *:* tcp LISTEN 0 50 *:3306 *:* tcp LISTEN 0 128 [::]:53 [::]:* tcp LISTEN 0 128 [::]:22 [::]:* #安装httpd和php相关包 [root@centos7 ~]#yum -y install httpd php php-devel php-gd php-mcrypt php-imap php-ldap php-mysql php-odbc php-pear php-xml php-xmlrpc php-mbstring php-mhash gettext [root@centos7 ~]#systemctl enable --now httpd #下载poweradmin程序,并解压缩到相应目录 [root@centos7 ~]#wget http://downloads.sourceforge.net/project/poweradmin/poweradmin-2.1.7.tgz [root@centos7 ~]#tar xvf poweradmin-2.1.7.tgz -C /var/www/html [root@centos7 ~]#cd /var/www/html [root@centos7 ~]#mv poweradmin-2.1.7 poweradmin
访问下面地址,启动PowerAdmin的网页安装向导:
http://powerdns服务器IP/poweradmin/install/
提供先前配置的数据库详情,同时为Poweradmin设置管理员密码
为Poweradmin创建一个受限用户
说明:
Username:PowerAdmin用户名
Password:上述用户的密码
Hostmaster:当创建SOA记录指定默认主机管理员
Primary nameserver:主域名服务器
Secondary namesever:辅域名服务器
按照下面页面说明,在数据库中创建用户并授权
MariaDB [(none)]>GRANT SELECT, INSERT, UPDATE, DELETE ON powerdns.* TO 'poweradmin'@'localhost‘ IDENTIFIED BY 'cici';
按下面页面说明,创建config.in.php文件内容
vim /var/www/html/poweradmin/inc/config.inc.php
安装完毕后
删除install目录
rm -rf /var/www/html/poweradmin/install/
登录 http://powerdns服务器ip/poweradmin/
username:admin
password:cici 参看第step 3
添加一条记录
[root@centos6 ~]#cat /etc/resolv.conf # Generated by NetworkManager search cuiqinghe.com nameserver 180.76.76.76 nameserver 10.0.0.17
论坛每秒只能处理30多个请求,性能较差,可以考虑使用加速器
4 php的加速器
php的加速器:基于PHP的特殊扩展机制如opcode缓存扩展也可以将opcode缓存于php的共享内存中,从而可以让同一段代码的后续重复执行时跳过编译阶段以提高性能。这些加速器并非真正提高了opcode的运行速度,而仅是通过分析opcode后并将它们重新排列以达到快速执行的目的
4.1 常见的第三方php加速器
1、APC (Alternative PHP Cache) 淘汰
遵循PHP License的开源框架,PHP opcode缓存加速器,目前的版本不适用于PHP5.4
项目地址:http://pecl.php.net/package/APC
2、eAccelerator 淘汰
源于Turck MMCache,早期的版本包含了一个PHP encoder和PHP loader,目前encoder已经不在持。项目地址 :http://eaccelerator.net/
3、XCache 淘汰
快速而且稳定的PHP opcode缓存,经过严格测试且被大量用于生产环境。项目地址:http://xcache.lighttpd.net/,收录EPEL源
4、Zend Optimizer和Zend Guard Loader
Zend Optimizer并非一个opcode加速器,它是由Zend Technologies为PHP5.2及以前的版本提供的一个免费、闭源的PHP扩展,其能够运行由Zend Guard生成的加密的PHP代码或模糊代码。 而Zend Guard Loader则是专为PHP5.3提供的类似于Zend Optimizer功能的扩展。项目地址http://www.zend.com/en/products/guard/runtime-decoders
5、NuSphere PhpExpress
NuSphere的一款开源PHP加速器,它支持装载通过NuSphere PHP Encoder编码的PHP程序文件,并能够实现对常规PHP文件的执行加速。项目地址,http://www.nusphere.com/products/phpexpress.htm
4.2 实现 xcache 加速 php 5.X
编译php-xcache加速访问,支持php 5.6版以下
官网:http://xcache.lighttpd.net/wiki/ReleaseArchive
案例:CentOS 7上安装清华源的php56,并编译安装 xcache加速
[root@centos7 ~]#yum -install https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm [root@centos7 ~]#yum -y install php56-php php56-php-mysqlnd mariadb-server [root@centos7 ~]#systemctl enable --now httpd mariadb Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service. Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service. [root@centos7 ~]#mysql MariaDB [(none)]> create database wordpress; MariaDB [(none)]> grant all on wordpress.* to wordpress@'localhost' identified by 'cici'; [root@centos7 ~]#tar xvf wordpress-5.3.2-zh_CN.tar.gz -C /var/www/html [root@centos7 ~]#cd /var/www/html [root@centos7 ~]#chown -R apache.apache wordpress/ [root@centos8 ~]#ab -c 10 -n 100 http://10.0.0.7/wordpress/ ...... Requests per second: 3.16 [#/sec] (mean) ...... #安装编译xcache [root@centos7 ~]#yum -y install gcc php56-php-devel #下载并解压缩xcache-3.2.0.tar.bz2 [root@centos7 ~]#tar xf xcache-3.2.0.tar.gz #生成编译环境 [root@centos7 ~]#cd xcache-3.2.0/ [root@centos7 xcache-3.2.0]#/opt/remi/php56/root/usr/bin/phpize Configuring for: PHP Api Version: 20131106 Zend Module Api No: 20131226 Zend Extension Api No: 220131226 [root@centos7 xcache-3.2.0]#./configure --enable-xcache --with-phpconfig=/opt/remi/php56/root/usr/bin/php-config [root@centos7 xcache-3.2.0]#make && make install ...省略... Installing shared extensions: /opt/remi/php56/root/usr/lib64/php/modules/ [root@centos7 xcache-3.2.0]#cat xcache.ini >> /opt/remi/php56/root/etc/php.ini #安装base源中执行即可cp xcache.ini /etc/php.d/ [root@centos7 ~]#systemctl restart httpd.service #测试性能,大概提升一倍速度 [root@centos8 ~]#ab -c10 -n 100 http://LAMP服务器/wordpress Requests per second: 7.26 [#/sec] (mean)
4.3 opcache加速php 7.X
[root@centos8 ~]#dnf install php-opcache
[root@centos8 ~]#cat /etc/php.ini
[opcache]
zend_extension=opcache.so
opcache.enable=1
[root@centos8 ~]#systemctl restart php-fpm
范例:CentOS 8 实现opache 加速
[root@centos8 ~]#dnf -y install httpd php php-mysqlnd mariadb-server php-opcache php-json [root@centos8 ~]#rpm -ql php-opcache /etc/php.d/10-opcache.ini /etc/php.d/opcache-default.blacklist /usr/lib/.build-id /usr/lib/.build-id/71 /usr/lib/.build-id/71/55ebb00f7ebcab9d708c1d5c7b7e634cce259c /usr/lib64/php/modules/opcache.so [root@centos8 ~]#grep opcache /etc/php.d/10-opcache.ini zend_extension=opcache opcache.enable=1 ...省略... #加速前,默认启用,先禁用加速 [root@centos8 ~]#vim /etc/php.d/10-opcache.ini opcache.enable=0 [root@centos8 ~]#systemctl restart php-fpm [root@centos7 ~]#ab -c 10 -n 100 http://10.0.0.8/wordpress/ ...... Requests per second: 32.21 [#/sec] (mean) ...... #启用加速 [root@centos8 ~]#vim /etc/php.d/10-opcache.ini opcache.enable=1 [root@centos8 ~]#systemctl restart php-fpm ##加速后 [root@centos7 ~]#ab -c 10 -n 100 http://10.0.0.8/wordpress/ ...... Requests per second: 105.53 [#/sec] (mean)......
5 php-fpm 模式实现LAMP
5.1 实现php-fpm(PHP FastCGI Process Manager)模式
对于php请求,httpd可以用模块和fastcgi两种方式实现动态程序的支持。
fastcgi模式:php处理请求,不再由http服务器自身进行管理,http服务器把http协议转化为factcgi协议,通过socket发送给fastcgi专用进程处理php程序
从稳定性上看,fastcgi是以独立的进程池运行来程序,如果单独一个进程死掉,系统可以很轻易的丢弃,然后重新分配新的进程来运行逻辑。从安全性上看,fastcgi和http的server完全独立, fastcgi怎么down也不会把server搞垮。
从性能上看,fastcgi把动态逻辑的处理从http server中分离出来,大负荷的IO处理还是留给宿主server,这样hpttd server可以一心一意作IO,对于一个普通的动态网页来说,逻辑处理可能只有一小部分,大量的图片等静态IO处理完全不需要逻辑程序的参与。从扩展性上讲,fastcgi是一个中立的技术标准,完全可以支持任何语言写的处理程序,如php,java,python等。而php-fpm就是用来支持php的fastcgi服务器。
各种OS版本对fastcgi的支持
CentOS 8: 默认使用fpm模式 httpd-2.4:默认rpm包支持fcgi模块 php包默认使用fpm模式 php-fpm包:专用于将php运行于fpm模式 CentOS 7: httpd-2.4:默认rpm包支持fcgi模块 php-fpm包:专用于将php运行于fpm模式 CentOS 6: PHP-5.3.2之前:默认不支持fpm机制;需要自行打补丁并编译安装 httpd-2.2:默认不支持fcgi协议,需要自行编译此模块 解决方案:编译安装httpd-2.4, php-5.3.3+
5.2 安装php-fpm
CentOS 8 安装php-fpm
dnf -y install php-fpm #或者 dnf -y install php
CentOS 7 安装php-fpm
BASE源安装PHP-FPM
yum install php-fpm
清华大学yum源安装较新版的PHP-FPM(依赖EPEL源)
#配置yum源 [root@centos7 ~]#yum install https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm #安装php-fpm5.6版 [root@centos7 ~]#yum install php56-php-fpm php56-php-mysql #安装php-fpm7.3版 [root@centos7 ~]#yum install php73-php-fpm php73-php-mysql
5.3 配置php-fpm
查看php-fpm所对应的配置文件
rpm -ql php-fpm /usr/lib/systemd/system/php-fpm.service /etc/logrotate.d/php-fpm /etc/php-fpm.conf /etc/php-fpm.d /etc/php-fpm.d/www.conf /etc/sysconfig/php-fpm /run/php-fpm
*php-fpm 主要配置文件*:
- /etc/php-fpm.conf
- /etc/php-fpm.d/*.conf
官方文档 :
http://php.net/manual/zh/install.fpm.configuration.php
PHP-FPM常见配置
- daemonize = no //是否将程序运行在后台
- listen = 127.0.0.1:9000 //FPM 监听地址
listen = /var/run/php.sock //UDF模式使用,指定生成的unix socket文件的路径
注意:Unix Domain Socket (UDS) support added in httpd-2.4.7
http://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypass
- listen.owner = apache //UDF模式使用,指定生成的unix socket文件的所有者
- listen.group = apache //UDF模式使用,指定生成的unix socket文件的所属组
- listen.mode= 0666 //UDF模式使用,,指定生成的unix socket文件的权限
- listen.acl_users = apache,nginx //指定用户访问unix socket文件,listen.owner 和listen.group将无效
- listen.backlog = -1 //等待队列的长度 -1表示无限制
- listen.allowed_clients = 127.0.0.1 //仅允许哪些WEB主机访问
- pm = dynamic|static //static 固定数量的子进程, //dynamic子进程数据以动态模式管理
- pm.max_childen //static 固定数量的子进程
- pm.start_servers
- pm.min_spare_servers
- pm.max_spare_servers
- pm.max_requests = 500
- php_value[session.save_handler] = files
- php_value[session.save_path] = /var/lib/php/session //设置session存放位置
session目录
确保运行php-fpm进程的用户对session目录有读写权限
mkdir /var/lib/php/session chown apache.apache /var/lib/php/session
启动PHP-FPM
systemctl start php-fpm
启用php-fpm的访问日志
[root@centos8 ~]#vim /etc/php-fpm.d/www.conf access.log = /var/log/php-fpm/access.log [root@centos8 ~]#systemctl restart php-fpm
范例:php-fpm配置生产案例
cat /etc/php-fpm.d/www.conf [www] listen = 127.0.0.1:9000 #监听地址及IP listen.allowed_clients = 127.0.0.1 #允许客户端从哪个源IP地址访问,要允许所有行首加 ;注释即可 user = apache #php-fpm启动的用户和组,会涉及到后期文件的权限问题 group = apache pm = dynamic #动态模式进程管理 pm.max_children = 500 #静态方式下开启的php-fpm进程数量,在动态方式下他限定php-fpm的最大进程数 pm.start_servers = 100 #动态模式下初始进程数,必须大于等于pm.min_spare_servers和小于等于pm.max_children的值。 pm.min_spare_servers = 100 #最小空闲进程数 pm.max_spare_servers = 200 #最大空闲进程数 pm.max_requests = 500000 #进程累计请求回收值,会重启 pm.status_path = /fpm_status #状态访问URL ping.path = /ping #ping访问动地址 ping.response = ping-pong #ping返回值 slowlog = /var/log/php-fpm/www-slow.log #慢日志路径 php_admin_value[error_log] = /var/log/php-fpm/www-error.log #错误日志 php_admin_flag[log_errors] = on php_value[session.save_handler] = files #phpsession保存方式及路径 php_value[session.save_path] = /var/lib/php/session #当时使用file保存session的文件路径
5.4 配置httpd 支持 fastcgi
注意:在HTTPD服务器上必须启用proxy_fcgi_module模块,才能充当php-fpm客户端
[root@centos8 ~]#dnf -y install httpd php-fpm [root@centos8 ~]#httpd -M |grep fcgi AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using centos8.localdomain. Set the 'ServerName' directive globally to suppress this message proxy_fcgi_module (shared) [root@centos8 ~]#cat /etc/httpd/conf.modules.d/00-proxy.conf # This file configures all the proxy modules: LoadModule proxy_module modules/mod_proxy.so LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so LoadModule proxy_balancer_module modules/mod_proxy_balancer.so LoadModule proxy_connect_module modules/mod_proxy_connect.so LoadModule proxy_express_module modules/mod_proxy_express.so LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so LoadModule proxy_ftp_module modules/mod_proxy_ftp.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so LoadModule proxy_scgi_module modules/mod_proxy_scgi.so LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
创建httpd的配置文件 /etc/httpd/conf.d/fcgi.conf ,内容如下
DirectoryIndex index.php ProxyRequests Off ProxyPassMatch ^/(.*\.php)$ fcgi://php-fpm服务器IP:9000/var/www/html/$1 ProxyPassMatch ^/(fpm_status|ping) fcgi://127.0.0.1:9000 #以上开启FCGI反向代理,“^/”这处的”/“相对于后面的/var/www/html而言,后面的$1是指前面的/(.*.php)
说明:
如果php-fpm和httpd在同一台主机,也可以用 UDS(unix domain socket)方式
ProxyPassMatch ^/(.*\.php)$ unix:/var/run/php.sock|fcgi://localhost/app/httpd24/htdocs/$1
5.4.1 实战案例:虚拟主机配置支持FCGI
vim /etc/httpd/conf.d/vhosts.conf DirectoryIndex index.php <VirtualHost *:80> ServerName www.cici.net DocumentRoot /apps/vhosts/cici.net ProxyRequests Off ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/apps/vhosts/cici.net/$1 ProxyPassMatch ^/(fpm_status|ping) fcgi://127.0.0.1:9000 <Directory "/apps/vhosts/cici.net"> Options None AllowOverride None Require all granted </Directory> </VirtualHost>
5.4.2 实战案例:CentOS 7 利用yum安装基于PHP-FPM模式的LAMP
#安装httpd和php-fpm包 [root@centos7 ~]#yum install httpd php-fpm #查看Httpd mod_fcgi模块是否加载 httpd -M | grep fcgi proxy_fcgi_module (shared) #添加FCGI的配置文件 DirectoryIndex index.php ProxyRequests off //是否开启正向代理 ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/html/$1 ProxyPassMatch ^/(fpm_status|ping) fcgi://127.0.0.1:9000 [root@centos7 ~]#systemctl start httpd php-fpm
5.4.3 实战案例:CentOS 7 利用清华yum源实现PHP-FPM的UDS模式
[root@centos7 ~]#yum install https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm [root@centos7 ~]#yum install httpd php74-php-fpm -y [root@centos7 ~]#vim /etc/opt/remi/php74/php-fpm.d/www.conf listen = /var/run/php.sock listen.owner = apache listen.group = apache listen.mode = 0660 pm.status_path = /fpm_status ping.path = /ping [root@centos7 ~]#vim /etc/httpd/conf.d/fcgi.conf DirectoryIndex index.php ProxyRequests Off #ProxyPassMatch ^/(.*\.php)$ fcgi://10.0.0.17:9000/data/html/$1 ProxyPassMatch ^/(.*\.php)$ unix:/var/run/php.sock|fcgi://localhost/var/www/html/$1 ProxyPassMatch ^/(fpm_status|ping) unix:/var/run/php.sock|fcgi://localhost [root@centos7 ~]#systemctl restart httpd php74-php-fpm.service [root@centos7 ~]#curl http://127.0.0.1/ping pong[root@centos7 ~]#curl http://127.0.0.1/fpm_status pool: www process manager: dynamic start time: 11/Mar/2020:11:43:56 +0800 start since: 488 accepted conn: 8 listen queue: 0 max listen queue: 0 listen queue len: 0 idle processes: 4 active processes: 1 total processes: 5 max active processes: 1 max children reached: 0 slow requests: 0
5.4.4 实战案例:CentOS 8上实现PHP-FPM状态页
[root@centos8 ~]#dnf -y install httpd php-fpm [root@centos8 ~]#vim /etc/php-fpm.d/www.conf pm.status_path = /fpm_status ping.path = /ping [root@centos8 ~]#vim /etc/httpd/conf.d/php.conf #增加#######之间内容 <IfModule !mod_php5.c> <IfModule !mod_php7.c> # Enable http authorization headers SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 <FilesMatch \.(php|phar)$> SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost" </FilesMatch> ####### <Locationmatch /(fpm_status|ping) > SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost" </locationmatch> ####### </IfModule> </IfModule>
5.5 综合实战案例
5.5.1 目标
利用清华yum源,安装php7.4+wordpress5.4.2+opcache+event模式
5.5.2 环境准备
两台主机
一台 apache + php7.4 b一台 mariadb
5.5.3 步骤
#安装httpd 2.4 和 php 7.4 相关包 yum install -y https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm yum install -y httpd php74-php-fpm php74-php-mysqlnd php74-php-opcache #配置php为UDS模式 vi /etc/opt/remi/php74/php-fpm.d/www.conf listen=/var/run/php.sock listen.owner = apache listen.group = apache listen.mode = 0660 #配置httpd 支持 php 的fastcgi模式 vim /etc/httpd/conf.d/test.conf DirectoryIndex index.php ProxyRequests Off ProxyPassMatch ^/(.*\.php)$ unix:/var/run/php.sock|fcgi://localhost/var/www/html/$1 systemctl start httpd php74-php-fpm.service #准备wordpress程序文件 mkdir /data/ unzip wordpress-5.4.2-zh_CN.zip mv wordpress/ /var/www/html/ setfacl –R –m u:apache:rwx /var/www/html/wordpress/ #或者chown –R apache.apache /var/www/html/wordpress #在另一台主机上安装mariadb yum install mariadb-server systemctl start mariadb mysql -uroot mysql> create database wordpress; mysql> grant all on wordpress.* to wpuser@'10.0.0.%' identified by "cici"; mysql> flush privileges; #打开浏览器访问 http://httpd服务器IP/wordpress,进行初始化和安装
6 编译安装php
6.1 编译安装 httpd 模块方式的php5.6
#安装相关包,依赖epel源 yum install gcc make libxml2-devel bzip2-devel libmcrypt-devel #编译安装php tar xvf php-5.6.30.tar.bz2 cd php-5.6.30 ./configure --prefix=/apps/php \ --with-mysql=/usr/local/mysql \ --with-openssl \ --with-mysqli=/usr/local/mysql/bin/mysql_config \ --enable-mbstring \ --with-png-dir \ --with-jpeg-dir \ --with-freetype-dir \ --with-zlib \ --with-libxml-dir=/usr \ --enable-xml \ --enable-sockets \ --with-apxs2=/app/httpd24/bin/apxs \ --with-mcrypt \ --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ --with-bz2 make -j 4 && make install #准备php的配置文件 cd php-5.6.30 cp php.ini-production /etc/php.ini #修改httpd配置文件支持php vim /etc/httpd24/conf/httpd.conf #下面加二行 AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps #定位至DirectoryIndex index.html, 修改为 DirectoryIndex index.php index.html apachectl restart
6.2 编译安装 httpd 模块方式的 php 7.3
#安装相关包, 依赖epel源 yum install gcc make libxml2-devel bzip2-devel libmcrypt-devel #编译安装php 7.3 tar xvf php-7.3.10.tar.xz cd php-7.3.10/ ./configure \ --prefix=/apps/php \ --enable-mysqlnd \ --with-mysqli=mysqlnd \ --with-openssl \ --with-pdo-mysql=mysqlnd \ --enable-mbstring \ --with-freetype-dir \ --with-jpeg-dir \ --with-png-dir \ --with-zlib \ --with-libxml-dir=/usr \ --enable-xml \ --enable-sockets \ --with-apxs2=/app/httpd24/bin/apxs \ --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ --enable-maintainer-zts \ --disable-fileinfo #说明: #--enable-maintainer-zts 仅针对mpm为event和worker的情况,编译成zts模块,如果是prefork则不需要 #php-7.0 以上版本使用--enable-mysqlnd --with-mysqli=mysqlnd ,原--with-mysql不再支持 make -j 4 && make install cp php.ini-production /etc/php.ini vim /etc/httpd24/httpd.conf 在文件尾部加两行 AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps 修改下面行 <IfModule dir_module> DirectoryIndex index.php index.html </IfModule>
6.3 编译安装 fastcgi 方式的php 7.4
#安装相关包,依赖EPEL源 yum install gcc libxml2-devel bzip2-devel libmcrypt-devel sqlite-devel oniguruma-devel tar xvf php-7.4.3.tar.xz cd php-7.4.3/ ./configure \ --prefix=/apps/php74 \ --enable-mysqlnd \ --with-mysqli=mysqlnd \ --with-pdo-mysql=mysqlnd \ --with-openssl \ --with-zlib \ --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ --enable-mbstring \ --enable-xml \ --enable-sockets \ --enable-fpm \ --enable-maintainer-zts \ --disable-fileinfo make && make install
6.4 编译安装 fastcgi 方式的php 7.3
#安装相关包,依赖EPEL源 yum install gcc make libxml2-devel bzip2-devel libmcrypt-devel #编译安装 php 7.3 tar xvf php-7.3.10.tar.bz2 cd php-7.3.10/ ./configure --prefix=/apps/php \ --enable-mysqlnd \ --with-mysqli=mysqlnd \ --with-pdo-mysql=mysqlnd \ --with-openssl \ --with-freetype-dir \ --with-jpeg-dir \ --with-png-dir \ --with-zlib \ --with-libxml-dir=/usr \ --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ --enable-mbstring \ --enable-xml \ --enable-sockets \ --enable-fpm \ --enable-maintainer-zts \ --disable-fileinfo make && make install #准备php的配置文件 cd php-7.3.10/ cp php.ini-production /etc/php.ini cd /apps/php/etc cp php-fpm.conf.default php-fpm.conf cp php-fpm.d/www.conf.default php-fpm.d/www.conf #准备php-fpm启动脚本或service unit文件 cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm chmod +x /etc/init.d/php-fpm chkconfig --add php-fpm chkconfig php-fpm on service php-fpm start #或者 cp sapi/fpm/php-fpm.service /usr/lib/systemd/system/ systemctl daemon-reload systemctl start php-fpm #配置httpd支持php-fpm vim /apps/httpd24/conf/httpd.conf #取消下面两行的注释 LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so #修改下面行 <IfModule dir_module> DirectoryIndex index.php index.html </IfModule> #加下面四行 AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps ProxyRequests Off ProxyPassMatch ^/(.*.php) fcgi://127.0.0.1:9000/var/www/html/$1 #支持opcache加速 vim /etc/php.ini [opcache] zend_extension=opcache.so opcache.enable=1
7 实战案例
7.1 实战案例1: 编译安装基于HTTPD模块的LAMP架构应用
7.1.1 目标
实现CentOS 7 编译安装基于httpd 模块方式的LAMP
7.1.2 环境准备
两台主机:
- 一台主机:httpd+php(模块方式)
- 一台主机:mariadb 服务器
软件版本:
- mariadb-10.2.27-linux-x86_64.tar.gz 通用二进制格式
- apr-1.7.0.tar.bz2
- apr-util-1.6.1.tar.bz2
- httpd-2.4.41.tar.gz
- php-7.3.10.tar.xz
- wordpress-5.2.3-zh_CN.zip
7.1.3 实现步骤
7.1.3.1 二进制安装mariadb
useradd -r -s /sbin/nologin mysql tar xvf mariadb-10.2.27-linux-x86_64.tar.gz -C /usr/local cd /usr/local ls -sv mariadb-10.2.27-linux-x86_64 mysql cd mysql chown -R root.root ./* mkdir /data/mysql -p chown -R mysql.mysql /data/mysql mkdir /etc/mysql cp support-files/my-huge.cnf /etc/mysql/my.cnf vim /etc/mysql/my.cnf [mysqld] #加三行 datadir =/data/mysql skip_name_resolve = ON #准备PATH变量 vim /etc/profile.d/lamp.sh PATH=/usr/local/mysql/bin/:$PATH . /etc/profile.d/lamp.sh cd /usr/local/mysql;scripts/mysql_install_db --user=mysql --datadir=/data/mysql cp support-files/mysql.server /etc/rc.d/init.d/mysqld chkconfig --add mysqld service mysqld start #为wordpress应用准备数据库和用户 mysql mysql> create database wordpress; mysql> grant all on wordpress.* to wpuser@'192.168.8.%' identified by "wppass";
7.1.3.2 编译安装httpd-2.4
useradd -r -s /sbin/nologin apache yum install gcc pcre-devel openssl-devel expat-devel tar xvf apr-1.7.0.tar.bz2 tar xvf apr-util-1.6.1.tar.bz2 tar xf httpd-2.4.41.tar.gz mv apr-1.7.0 httpd-2.4.41/srclib/apr mv apr-util-1.6.1 httpd-2.4.41/srclib/apr-uti cd httpd-2.4.41/ ./configure --prefix=/apps/httpd24 \ --enable-so \ --enable-ssl \ --enable-cgi \ --enable-rewrite \ --with-zlib \ --with-pcre \ --enable-modules=most \ --enable-mpms-shared=all \ --with-mpm=prefork \ --with-included-apr make -j 4 && make install #配置PATH变量 vim /etc/profile.d/lamp.sh PATH=/usr/local/mysql/bin/:/app/httpd24/bin:$PATH . /etc/profile.d/lamp.sh vim /app/httpd24/conf/httpd #修改下面两行 user apache group apache apachectl start
7.1.3.3 编译安装httpd模块方式 php-7.3
#安装相关包,依赖EPEL源 yum install gcc libxml2-devel bzip2-devel libmcrypt-devel #编译安装php tar xvf php-7.3.10.tar.xz cd php-7.3.10/ ./configure \ --prefix=/apps/php \ #安装路径 --enable-mysqlnd \ #启用连接数据库的模块 --with-mysqli=mysqlnd \ --with-openssl \ --with-pdo-mysql=mysqlnd \ --enable-mbstring \ --with-freetype-dir \ --with-jpeg-dir \ --with-png-dir \ --with-zlib \ --with-libxml-dir=/usr \ --enable-xml \ --enable-sockets \ --with-apxs2=/app/httpd24/bin/apxs \ #启用php的模块方式 --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ --enable-maintainer-zts \ --disable-fileinfo make -j 4 && make install #为php提供配置文件,php.ini-production是模板文件 cp php.ini-production /etc/php.ini
7.1.3.4 编辑apache配置文件支持php
vim /etc/httpd24/conf/httpd.conf #下面加二行,支持php后缀,.phps的后缀(不加也行) AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps #定位至DirectoryIndex index.html, 修改为 DirectoryIndex index.php index.html #index.php调到第一个 apachectl restart
7.1.3.6 部署wordpress
unzip wordpress-5.2.3-zh_CN.zip mv wordpress /var/www/html setfacl –R –m u:apache:rwx /var/www/html/wordpress/ #或者chown –R apache.apache /var/www/html/wordpress #打开http://LAMP服务器IP/wordpress进行页面安装
7.2 实战案例2: 编译安装基于 FASTCGI 模式LAMP架构应用(重点)
7.2.1 目标
实现CentOS 7 编译安装基于 fastcgi 模式的多虚拟主机的wordpress和discuz的LAMP架构
建议写成playbook
7.2.2 环境准备
两台主机:
- 一台主机:httpd+php(fastcgi模式)
- 一台主机:mariadb 服务器
软件版本:
- CentOS 7.8
- mariadb-10.2.27-linux-x86_64.tar.gz 通用二进制格式
- apr-1.7.0.tar.bz2
- apr-util-1.6.1.tar.bz2
- httpd-2.4.43.tar.gz
- php-7.4.7.tar.xz 或 php-7.3.10.tar.bz2
- wordpress-5.4.2-zh_CN.tar.gz
- Discuz_X3.4_SC_UTF8【20191201】.zip
7.2.3 实现步骤
7.2.3.1 二进制安装mariadb
useradd -r -s /sbin/nologin mysql tar xvf mariadb-10.2.27-linux-x86_64.tar.gz -C /usr/local cd /usr/local ln -sv mariadb-10.2.27-linux-x86_64 mysql cd mysql chown -R root.root ./* mkdir /data/mysql -p chown -R mysql.mysql /data/mysql mkdir /etc/mysql cp support-files/my-huge.cnf /etc/mysql/my.cnf vim /etc/mysql/my.cnf [mysqld] #加下面行 datadir =/data/mysql skip_name_resolve = ON #准备PATH变量 vim /etc/profile.d/lamp.sh PATH=/usr/local/mysql/bin/:$PATH . /etc/profile.d/lamp.sh yum install libaio -y cd /usr/local/mysql;scripts/mysql_install_db --user=mysql --datadir=/data/mysql cp support-files/mysql.server /etc/rc.d/init.d/mysqld chkconfig --add mysqld service mysqld start #为wordprss和discuz应用准备数据库和用户帐号 mysql -uroot mysql> create database wordpress; mysql> create database discuz; mysql> grant all on wordpress.* to wpuser@'10.0.0.%' identified by "wppass"; mysql> grant all on discuz.* to discuz@'10.0.0.%' identified by 'dispass';
注意:mysql数据库不能和mariadb一样同时创建用户和授权
7.2.3.2 编译安装 httpd 2.4
#安装相关包 yum install gcc pcre-devel openssl-devel expat-devel -y #编译安装httpd tar xvf apr-1.7.0.tar.bz2 tar xvf apr-util-1.6.1.tar.bz2 tar xf httpd-2.4.43.tar.gz mv apr-1.7.0 httpd-2.4.43/srclib/apr mv apr-util-1.6.1 httpd-2.4.43/srclib/apr-util cd httpd-2.4.43/ ./configure \ --prefix=/apps/httpd24 \ --enable-so \ --enable-ssl \ --enable-cgi \ --enable-rewrite \ --with-zlib \ --with-pcre \ --with-included-apr \ --enable-modules=most \ --enable-mpms-shared=all \ --with-mpm=event make && make install #准备PATH变量 vim /etc/profile.d/lamp.sh PATH=/apps/httpd24/bin:$PATH . /etc/profile.d/lamp.sh #创建和配置用户和组 useradd -s /sbin/nologin -r -u 88 apache vim /apps/httpd24/conf/httpd.conf user apache group apache #修改为event模式,编译时已指定,此项不再需修改,可选项 vim /apps/httpd24/conf/httpd.conf LoadModule mpm_event_module modules/mod_mpm_event.so #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so #LoadModule mpm_worker_module modules/mod_mpm_worker.so httpd -M |grep mpm mpm_event_module (shared) apachectl start [root@centos7 ~]#vim /usr/lib/systemd/system/httpd.service [Unit] Description=The Apache HTTP Server After=network.target remote-fs.target nss-lookup.target Documentation=man:httpd(8) Documentation=man:apachectl(8) [Service] Type=forking #EnvironmentFile=/etc/sysconfig/httpd ExecStart=/apps/httpd24/bin/apachectl start #ExecStart=/apps/httpd24/bin/httpd $OPTIONS -k start ExecReload=/apps/httpd24/bin/apachectl graceful #ExecReload=/apps/httpd24/bin/httpd $OPTIONS -k graceful ExecStop=/apps/httpd24/bin/apachectl stop KillSignal=SIGCONT PrivateTmp=true [Install] WantedBy=multi-user.target
7.2.3.3 编译安装 fastcgi 方式的 php 7.4
#安装相关包,依赖EPEL源 #php 7.4 相关包 yum -y install gcc libxml2-devel bzip2-devel libmcrypt-devel sqlite-devel oniguruma-devel #php 7.3 相关包 yum -y install gcc libxml2-devel bzip2-devel libmcrypt-devel #php7.4 编译 tar xvf php-7.4.7.tar.xz cd php-7.4.7/ ./configure \ --prefix=/apps/php74 \ --enable-mysqlnd \ --with-mysqli=mysqlnd \ --with-pdo-mysql=mysqlnd \ --with-openssl \ --with-zlib \ --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ --enable-mbstring \ --enable-xml \ --enable-sockets \ --enable-fpm \ --enable-maintainer-zts \ --disable-fileinfo #编译安装php 7.3 tar xvf php-7.3.10.tar.bz2 cd php-7.3.10 ./configure --prefix=/apps/php73 \ --enable-mysqlnd \ --with-mysqli=mysqlnd \ --with-pdo-mysql=mysqlnd \ --with-openssl \ --with-freetype-dir \ --with-jpeg-dir \ --with-png-dir \ --with-zlib \ --with-libxml-dir=/usr \ --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ --enable-mbstring \ --enable-xml \ --enable-sockets \ --enable-fpm \ --enable-maintainer-zts \ --disable-fileinfo make -j 4 && make install #准备PATH变量 #php7.4 vim /etc/profile.d/lamp.sh PATH=/apps/php74/bin:/apps/httpd24/bin:$PATH . /etc/profile.d/lamp.sh #php7.3 vim /etc/profile.d/lamp.sh PATH=/apps/php73/bin:/apps/httpd24/bin:$PATH . /etc/profile.d/lamp.sh [root@Centos7 ~]#php --version PHP 7.4.7 (cli) (built: Jul 2 2020 09:10:59) ( ZTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies [root@websrv ~]#/apps/php73/bin/php --version PHP 7.3.12 (cli) (built: Dec 14 2019 10:20:40) ( ZTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.12, Copyright (c) 1998-2018 Zend Technologies #准备php配置文件和启动文件 cp php.ini-production /etc/php.ini cp sapi/fpm/php-fpm.service /usr/lib/systemd/system/ #模板文件拷贝 cd /apps/php74/etc cp php-fpm.conf.default php-fpm.conf cd php-fpm.d/ cp www.conf.default www.conf #修改进程所有者 vim /apps/php74/etc/php-fpm.d/www.conf user apache group apache #支持status和ping页面(需要设置安全策略,不能让任何人都访问) pm.status_path = /fpm_status ping.path = /ping #支持opcache加速 mkdir /etc/php.d/ vim /etc/php.d/opcache.ini [opcache] zend_extension=opcache.so opcache.enable=1 systemctl daemon-reload systemctl status php-fpm.service systemctl enable --now php-fpm.service
7.2.3.4 修改配置httpd 支持php-fpm
vim /apps/httpd24/conf/httpd.conf #取消下面两行的注释(apache相当于反向代理) LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so #修改下面行 <IfModule dir_module> DirectoryIndex index.php index.html </IfModule> #加下面三行 AddType application/x-httpd-php .php #AddType application/x-httpd-php-source .phps ProxyRequests Off #实现第一个虚拟主机 <virtualhost *:80> servername blog.cici.org documentroot /data/wordpress <directory /data/wordpress> require all granted </directory> ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/data/wordpress/$1 #实现status和ping页面 ProxyPassMatch ^/(fpm_status|ping)$ fcgi://127.0.0.1:9000/$1 CustomLog "logs/access_wordpress_log" common </virtualhost> #第二个虚拟主机 <virtualhost *:80> servername forum.cici.org documentroot /data/discuz <directory /data/discuz/> require all granted </directory> ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/data/discuz/$1 CustomLog "logs/access_discuz_log" common </virtualhost> apachectl restart
7.2.3.5 准备wordpress和discuz! 相关文件
#准备wordpress程序文件 mkdir /data/ tar xvf wordpress-5.4.2-zh_CN.tar.gz mv wordpress/ /data setfacl –R –m u:apache:rwx /data/wordpress/ #或者chown –R apache.apache /data/wordpress #准备discuz!程序文件 unzip Discuz_X3.4_SC_UTF8【20191201】.zip mv DiscuzX/upload/ /data/discuz setfacl -R -m u:apache:rwx /data/discuz/
7.2.3.5 测试访问
vim /etc/hosts 10.0.0.7 blog.cici.org forum.cici.org
打开浏览器访问 http://wordpress.cici.net 和http://discuz.cici.net 分别进行初始化和安装
7.2.3.6 修改成UDS模式
vim /apps/php/etc/php-fpm.d/www.conf ;listen = 127.0.0.1:9000 listen = /run/php-fpm.sock listen.owner = apache listen.group = apache listen.mode = 0660 systemctl restart php-fpm ll /run/php-fpm.sock srw-rw---- 1 apache apache 0 Dec 14 11:11 /run/php-fpm.sock vim /apps/httpd24/conf/httpd.conf <virtualhost *:80> servername blog.cici.org documentroot /data/wordpress <directory /data/wordpress> require all granted </directory> #ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/data/wordpress/$1 ProxyPassMatch ^/(.*\.php)$ "unix:/run/php-fpm.sock|fcgi://localhost/data/wordpress/" #ProxyPassMatch ^/(status|ping)$ fcgi://127.0.0.1:9000/$1 ProxyPassMatch ^/(status|ping)$ "unix:/run/php-fpm.sock|fcgi://localhost/" CustomLog "logs/access_wordpress_log" common </virtualhost> <virtualhost *:80> servername forum.cici.org documentroot /data/wordpress <directory /data/wordpress> require all granted </directory> #ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/data/discuz/$1 ProxyPassMatch ^/(.*\.php)$ "unix:/run/php-fpm.sock|fcgi://localhost/data/discuz/" #ProxyPassMatch ^/(status|ping)$ fcgi://127.0.0.1:9000/$1 ProxyPassMatch ^/(status|ping)$ "unix:/run/php-fpm.sock|fcgi://localhost/" CustomLog "logs/access_discuz_log" common </virtualhost> systemctl restart httpd