一次浏览器http请求的过程

我们每天都打开网页,让我们来看看,一次典型的网页请求的整个过程:

1, 用户端:

1.1 用户打开一个浏览器,在地址栏输入一个http/https url(这里不涉及ftp,stmp等协议),点回车;

1.2 浏览器截取出域名,尝试读取本地hosts文件, 查找hostname对应的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 请求的参数根据method方式不一样,get通过url, post通过request body携带过去。

1.5 请求到达ip所指向的服务器,由监听80端口的web server进行处理,有可能通过负载均衡LB或者反向代理(upstream),指向到某台特定的服务器;

 

2 服务器上的过程

2.1 服务器上的web server,如nginx, Apache, tengine等,通过读取它的配置,如 /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_pass unix:/run/php/php5.6-fpm.sock; //系统本身的socket管道
            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的方式,抛给对应的进程管理器,比如fastcgi_pass,如下:

fastcgi_pass一般有两种模式:

一种是TCP/IP模式,如本机的9000端口监听,也就是127.0.0.1:9000,或者其他机器的9000端口。

另一种是socket模式,由本机的php的socket管道进行监听,比如unix:/run/php/php5.6-fpm.sock。

当web server和脚本应用在运行在同一台机器上时,由于socket管道之间之间连通,相对于nginx=>socket=>TCP/IP=>socket=>php这种方式来说,路径更短,速度更快,推荐使用socket方式。当然,如果不在同一台机器上,则需要使用TCP/IP模式。

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

如果通过TCP/IP协议,三次握手四次挥手,滑动窗口控制数据传输,标准输入,输出等。同时,nginx里面的proxy_connect_timeout, proxy_read_timeout, proxy_send_out等参数控制连接的时长,返回相应的http状态码。

而socket的方式,其实是对TCP/IP的抽象,通过内置的connect, listen, accept, send, read, write等方法来实现数据的传输。

2.3 fastcgi收到请求后,会wrap出php-fpm进程,然后通过master-worker方式抛给对应的php-fpm worker进行处理。而php-fpm启动的过程,则通过调用Zend engine内核中的SAPI模块进行处理,对php脚本文件进行解析(包括词法分析,语法规则等),将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,Opcode),如果开启了Opcache扩展,则会对解析后的操作码进行缓存。详细的php脚本命周期会另外写文章进行阐述。

2.4 请求携带的参数也通过fastcgi_params传递到php脚本。

2.5 php脚本返回数据,然后走一个反向的路径,一直将数据传输到浏览器客户端。进行页面的展示和渲染。

转载于:https://my.oschina.net/u/3412738/blog/2967117

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值