我们每天都打开网页,让我们来看看,一次典型的网页请求的整个过程:
1, 用户端:
1.1 用户打开一个浏览器,在地址栏输入一个http/https url(这里不涉及ftp,stmp等协议),点回车;
1.2 读取本地hosts文件, 查找url对应的ip服务器地址;
1.3 如果找不到,则从dns中查找,先从本机获取,如linux下
cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.1.1
这个看起来像localhost的地址究竟是什么意思?
因为 ubuntu下有一个本地的dns服务叫做dnsmasq,它是由NetworkManager控制的
ps -ef | grep dnsmasq
nobody 2111 1165 0 11月09 ? 00:00:08 /usr/sbin/dnsmasq --no-resolv --keep-in-foreground --no-hosts --bind-interfaces --pid-file=/var/run/NetworkManager/dnsmasq.pid --listen-address=127.0.1.1 --cache-size=0 --conf-file=/dev/null --proxy-dnssec --enable-dbus=org.freedesktop.NetworkManager.dnsmasq --conf-dir=/etc/NetworkManager/dnsmasq.d
c80k2 29357 28457 0 22:23 pts/54 00:00:00 grep --color=auto dnsmasq
你就可以看到它监听的本地地址,--listen-address=127.0.1.1 (ubuntu12.04及之前的版本 是 127.0.0.1), 这个地址是一个本地回环地址
而你真实的dns服务器地址,是被这个服务管理维护着的
local process -> local dnsmasq -> router -> ISP dns
dns域名解析过程一般分为递归查询recursive query和迭代查询iterative query,获取到所输url的根域名和服务器ip;
1.4 将请求指向到该服务器ip,通过负载均衡,指向到某台特定的服务器;
2 服务器上的过程
2.1 服务器上的web server,如nginx, Apache等,通过读取它的配置,如 /etc/nginx/sites-available/default 或者 apache的httpd.conf配置,这里以nginx为例
#loaclhost
server {
listen 80;
server_name localhost;
root /opt/wwwroot/;
index index.html index.htm index.php;
location @rewrite {
rewrite ^/(.*)$ /index.php?_url=/$1;
}
location / {
allow all;
}
location ~ ^(.+\.php)(.*)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $DOCUMENT_ROOT$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $DOCUMENT_ROOT/$fastcgi_script_name;
include fastcgi_params;
}
}
我们一行一行来看看
server { ->表示这是一个server,可对外提供服务
listen 80; //该server监控的服务器端口,这里默认是80
server_name localhost; //server_name,就是url解析之后的根地址
root /opt/wwwroot/; //指向到的根目录
index index.html index.htm index.php; //指向到根目录下的任意文件
location @rewrite { //重写:
rewrite ^/(.*)$ /index.php?_url=/$1;
}
location / { //对url进行匹配
allow all;
}
location ~ ^(.+\.php)(.*)$ {
fastcgi_pass 127.0.0.1:9000; //后面的address为后端的fastcgi server的地址
fastcgi_index index.php; // fastcgi默认的主页资源
fastcgi_split_path_info ^(.+\.php)(.*)$; //这里通过新版的nginx的fastcgi_split_path_info将请求的url后半部分进行split操作
fastcgi_param PATH_INFO $fastcgi_path_info; //参见以下示例
fastcgi_param PATH_TRANSLATED $DOCUMENT_ROOT$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $DOCUMENT_ROOT/$fastcgi_script_name;
include fastcgi_params;
}
}
示例:
请求的网址是/abc/index.php/def
DOCUMENT_ROOT的值是项目的根目录
PATH_INFO的值是/abc
SCRIPT_FILENAME的值是$doucment_root/abc/index.php
SCRIPT_NAME /abc/index.php
具体的location匹配信息可参见: https://segmentfault.com/a/1190000002797606
2.2 web服务器将请求通过master-worker的方式,抛给对应的进程管理器,比如cgi,php-fpm,如下:
nginx进程
ps -aux | grep nginx
root 1646 0.0 0.0 123396 236 ? Ss 11月30 0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data 1649 0.0 0.0 123788 684 ? S 11月30 0:13 nginx: worker process
www-data 1651 0.0 0.0 123788 604 ? S 11月30 0:18 nginx: worker process
www-data 1652 0.0 0.0 123788 1236 ? S 11月30 0:05 nginx: worker process
www-data 1653 0.0 0.0 123788 1040 ? S 11月30 0:19 nginx: worker process
root 11563 0.0 0.0 4512 0 pts/0 Ss 11月30 0:00 /bin/sh -c service nginx start && service php7.0-fpm start && /bin/bash /bin/bash
root 11649 0.0 0.0 125120 32 ? Ss 11月30 0:00 nginx: master process /usr/sbin/nginx
www-data 11650 0.0 0.0 125444 88 ? S 11月30 0:02 nginx: worker process
www-data 11651 0.0 0.0 125444 0 ? S 11月30 0:21 nginx: worker process
www-data 11652 0.0 0.0 125444 8 ? S 11月30 0:18 nginx: worker process
www-data 11653 0.0 0.0 125444 0 ? S 11月30 0:21 nginx: worker process
php进程
ps -aux | grep php
root 1338 0.0 0.1 399000 9268 ? Ss 11月30 0:13 php-fpm: master process (/etc/php/5.6/fpm/php-fpm.conf)
www-data 1771 0.0 0.2 403764 23084 ? S 11月30 0:00 php-fpm: pool www
www-data 1773 0.0 0.1 405616 15748 ? S 11月30 0:00 php-fpm: pool www
c80k2 7137 0.0 0.0 9776 1644 ? S 11月30 0:18 /opt/phpstorm/bin/fsnotifier64
root 11563 0.0 0.0 4512 0 pts/0 Ss 11月30 0:00 /bin/sh -c service nginx start && service php7.0-fpm start && /bin/bash /bin/bash
root 11791 0.0 0.0 366700 96 ? Ss 11月30 0:10 php-fpm: master process (/etc/php/7.1/fpm/php-fpm.conf)
www-data 11792 0.0 0.0 374524 1584 ? S 11月30 0:03 php-fpm: pool www
www-data 11793 0.0 0.0 374504 1880 ? S 11月30 0:02 php-fpm: pool www
然后通过http/tcp-ip协议,nginx和php直接按照标准进行连接,如三次握手四次挥手(ACK?),滑动窗口控制数据传输,标准输入,输出等。同时,nginx里面的proxy_connect_timeout, proxy_read_timeout, proxy_send_out等参数控制连接的时长,返回相应的http状态码
2.3 php收到请求后,根据不同的进程管理器的方式,决定如何解析php文件,最后执行php代码
2.4 将数据返回给前端,进行页面渲染。