博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一次浏览器http请求的过程
阅读量:6854 次
发布时间:2019-06-26

本文共 6092 字,大约阅读时间需要 20 分钟。

hot3.png

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

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 OVERWRITTENnameserver 127.0.1.1

这个看起来像localhost的地址究竟是什么意思?

因为 ubuntu下有一个本地的dns服务叫做dnsmasq,它是由NetworkManager控制的

ps -ef | grep dnsmasqnobody    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.dc80k2    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 ^/(.*)$ /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 nginxroot      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 processwww-data  1651  0.0  0.0 123788   604 ?        S    11月30   0:18 nginx: worker processwww-data  1652  0.0  0.0 123788  1236 ?        S    11月30   0:05 nginx: worker processwww-data  1653  0.0  0.0 123788  1040 ?        S    11月30   0:19 nginx: worker processroot     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/bashroot     11649  0.0  0.0 125120    32 ?        Ss   11月30   0:00 nginx: master process /usr/sbin/nginxwww-data 11650  0.0  0.0 125444    88 ?        S    11月30   0:02 nginx: worker processwww-data 11651  0.0  0.0 125444     0 ?        S    11月30   0:21 nginx: worker processwww-data 11652  0.0  0.0 125444     8 ?        S    11月30   0:18 nginx: worker processwww-data 11653  0.0  0.0 125444     0 ?        S    11月30   0:21 nginx: worker process

php进程

ps -aux | grep phproot      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 wwwwww-data  1773  0.0  0.1 405616 15748 ?        S    11月30   0:00 php-fpm: pool wwwc80k2     7137  0.0  0.0   9776  1644 ?        S    11月30   0:18 /opt/phpstorm/bin/fsnotifier64root     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/bashroot     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 wwwwww-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

你可能感兴趣的文章
查询Oracle正在执行和执行过的SQL语句
查看>>
MyBatis学习总结(10)——批量操作
查看>>
Linux的shell脚本打印图形和主机监控脚本练习
查看>>
storm流处理的简单例子的一些问题
查看>>
我的友情链接
查看>>
php5.2.5安装xcache-2.0.0
查看>>
varnish缓存四:性能调优
查看>>
关于顽固进程scclient.exe、scguardc.exe、sccltui.exe和系统服务scclient、scguardc
查看>>
什么是事务型的存储引擎
查看>>
unity 生命周期
查看>>
一次观影经验看互联网的赚钱之道
查看>>
硬链接与符号链接的区别.
查看>>
手机自适应web
查看>>
第 6 章 存储 - 042 - 用 volume container 共享数据
查看>>
linux学习指南
查看>>
牛逼的vscode的设置
查看>>
DP 恢复命令omnir
查看>>
nagios
查看>>
3.文件属性,权限,正则表达式
查看>>
大数据从小数据开始
查看>>