动,静资源:
静态资源:客户端从服务器获得的资源表现形式与原文件相同
动态资源:通常是程序文件,需要在服务器执行之后,将执行的结果返回给客户端。
我们还可以这样理解静态资源:服务器端接入到客户端的请求之后就是把客户端要请求的内容返回给客户端,其它的事情都没有做,只是做了I/0,内容没有发生改变。
apache与php之间的关系
当apache收到用户的请求之后,通过apache的过滤功能(通过后缀扩展名)可以区分出客户端请求的是静态资源还是动态资源,如果客户端请求的是静态资源的话(比如是html结尾的文件),apache自己就可以发起系统调用完成响应;如果httpd识别出客户端请求的资源是一个以php或者.sh结尾的文件呢?httpd本身是无能无力的,它总不能把这个php结尾的源码文件发送给客户端吧,但是apache程序自己又不能执行php的文件,所以httpd需要与php解释器进行联动让php解释器把客户请求的程序执行一次,然后把结果返回给httpd进程,然后httpd进程再封装返回给客户端。那么httpd与php解释器是两个程序,那么怎样联动呢?
httpd与php解释器是两个不同的程序,就像两个说不同语言的人,相互谁也不理解谁,它们两个要想联动的话,就必须有统一的“交流语言”,这种情况在计算机的领域是非常常见的,都是使用协议来解决的,httpd与php之间都运行cgi协议,所谓的cgi协议就是“通用网关接口”,httpd可以通过加载一个模块来支持此协议,而php也是基于此协议来开发的,所以它们之间是可以相互交流的。
httpd与php在交流时的过程是这样的:
- httpd把客户端发过来动态资源请求通过cgi协议封装成请求包发送给php解释器
- php解释器收到之后会通过系统调用,然后IO,运行并处理引用户的动态资源,并通过数据流把结果发送给httpd程序,在这里需要注意,httpd加载静态资源的时候虽然加载的也是一个文件,但是实际就是一段数据流而已,当httpd收到来自php的响应报文时,收到的实际上也中是一段数据流,文件只是我们凭空想像出来的。
- httpd程序然后进行封装之后响应给客户端
总结:
httpd像是客户端向php(服务器)发送请求,php做为服务器进行回应,httpd活生生像一个客户端!
换个角度再看,httpd就像是一个代理,对于动态资源的请求仅做一个转转发作用,httpd活生生像一个代理!
httpd与php的分离& httpd调用php的三种方式
如果httpd与php都在一台主机的时候,httpd可以使用三种方式调用php.
第一种是httpd通过php模块调用php,实际上php也正是基于httpd的模块来开发的,这样的话php的功能就集成到了httpd当中了,也不用什么调用,不用cgi,也不用请求
[root@www init.d]# httpd -M | grep cgi cgi_module (shared) #httpd内部集成了cgi模块,httpd使用cgi时相当于客户端。
当使用第一种方式的时候,不用消息队列,也不用文件系统,更用不上套接字,所以效率很高,很常用.
第二种方式就是基于cgi协议的方式,这一种方式可能会用到消息队列和文件系统的方式,这种方式不如上一种方式,所以很少使用.
第三种方式就是当httpd与php进行分离的时候,假如说分离成两成主机,分离成两台主机的话,就得tcp/ip的套接字方式,再加上cgi这两种方式进行通信,tcp/ip是为两台主机能够通信,而cgi是为了进程与进程之前能够通信,而cgi与tcp/ip结合起来的方式就叫做fast cgi.
cgi不仅仅可以实现将httpd做为客户端,php做为服务器的功能, 这只是很小的功能。我们想一下,如果客户端请求的是一个shell脚本的话,那么httpd是否还要通过cgi协议做为客户端向后端的php程序发请求?虽然shell程序有解释器,但是bash并不支持cgi协议呀!bash没有办法与httpd进行通信,那么这个问题怎么解决呢?httpd程序这时会用到cgi协议当中另一部分功能,httpd可以通过cgi协议将bash解释器做为自己的子进程运行,httpd把数据直接交给自己的子进程,当子进程处理完毕之后再把结果交给httpd进程。
数据库系统:
在大多数的情况下,仅仅靠php调用硬盘上的资源是无法完全完成客户端的请求的,多数情况下,服务器的内容并不是存放在磁盘当中的,而是存放在数据库系统当中,为什么要存放在数据库当中呢?存放在硬盘当中不行吗?原因如下:
当我们在硬盘调用一个文件时候,都是把这个文件直接整个调用到内存当中,比如我想查看某一个大文件的某一点内容,但是内核会把所有文件所有的内容都调用到内存当中,如果一个日志文件长达好几个G,如果都调用到内存当中的话那得占用多少内存呀!这种方法太占用内存空间了,有没有其它的办法呢?有的,就是存放在数据库当中,难道存放在数据库系统当中就没有这种问题的出现吗?是的,没有,下面就让我们来看一下数据库系统是怎样调用数据的。
假设我们有一个数据库文件长达20个G,里面存放的是用户在我们这个网站上注册的账户信息。现在有用户想要登录我们的网站了,当用户输入一个用户名和密码之后登录时,数据库是怎么做的呢?数据库系统并不是把整个文件都调用到内存当中,而是在调用发起之前,数据库系统就对这个20G的文件做了一定的优化,优化后又生成了一个文件,它是怎样优化的呢?数据库系统仅把姓名那一列拿出来并在每个姓名之后都记录了与之相对应后续内容的数据块地址,这个文件比较小,只有5个G左右,当用户调用时仅仅加载这个5个G的文件,找到匹配的姓名之后再根据其后面记录的数据块地址调用余下的数据块内容,这样就不用加载整个表了,节省内存,这仅仅是一次的优化,其实还可以再次优化,把所有姓相同的用户放在一起,,把相同姓的用户只用姓来记录,并在姓的后面记录该姓对应的用户组,这样的话又生成了一个文件,整体来看就是三层结构了,这个文件可能只有2个G大小,内存的占用量更小了。这种不断抽象优化的功能只有数据库系统。
php与数据库系统进行联动
php与数据库也是八竿子打不着的两个程序,它们怎样才一起联动呢?在这里并没有使用协议来解决这个问题,而是使用库调用来解决这个问题的。假设以php与mysql进行联动来说明吧!
php程序本身的确无法与mysql进行联动,php还需要加载一个驱动模板,这个驱动模块可能叫做php-mysql,如果数据库是甲骨文数据库,那么php要调用 php-甲骨文模块进行调用才与与甲骨文进行联动,因为php只有通过这个模块向相应的数据库系统发送的数据相应的数据库才能看懂,所以在安装php的时候,不要忘记安装这样一个驱动模块。
[root@www init.d]# yum list all | grep php-mysql php-mysql.x86_64 #这个就是php与mysql交互的驱动模块
它们之间的关系也类似于客户端与服务器的关系,php向mysql请求,而mysql对php进行回应。
当客户端通过http协议向apache发来请求,如果是静态资源,直接发起系统调用;如果是动态资源,通过php模块/cgi/fastcgi任意一种方式发请求包交给php
当php收到之后apache的请求之后,如果所请求的资源都存储在硬盘上,那么php直接发起系统调用,将文件调用到内存并执行,执行完成之后把结果通过数据流交给apache,然后apache再回复客户端;如果所请求的资源有程序硬盘上,还有一部分数据在数据库当中,如下。
当php发的请求数据到达mysql,mysql会通过各级索引找到数据,通过响应包回复给php,php通过在磁盘当中调用一部分程序,加上从mqsql回复的这部分数据,结合结合起来之后就可以运行,运行完成之后把结果交给apache