本文作为解决如何通过 Golang 来编写 Web 应用这个问题的前瞻,对 Golang 中的 Web 基础部分进行一个简单的介绍。目前 Go 拥有成熟的 Http 处理包,所以我们去编写一个做任何事情的动态 Web 程序应该是很轻松的,接下来我们就去学习了解一些关于 Web 的相关基础,了解一些概念,以及 Golang 是如何运行一个 Web 程序的。
文章预计分为四个部分逐步更新
2023-04-13 星期四 一更 全文共计约 3800 字 阅读大约花费 5 分钟
其实当你输入网址(URL)并按下回车之后,你的浏览器相当于扮演了 客户端 的角色,首先你的浏览器会去请求 DNS 服务器进行域名解析,将你输入的 URL 地址 转化为对应的 ip 地址,通过 ip 地址 我们就可以找到对应的服务器位置,从而进行 TCP 连接。
连接之后,你的浏览器会发送 HTTP 请求 (Request)包,服务区收到请求包之后开始从响应处理请求包,调用自身的服务,并返回 HTTP 响应 (Response)包。
客户端收到了来自服务端的响应之后开始渲染这个响应包里的主体(body),等收到了全部的内容应答后,就会断开与服务器的 TCP 连接 (这里先讨论一般情况)
如图👇
而一个 Web 服务器也被称作 HTTP 服务器, 它通过 http 协议与客户端通信。这个客户端通常是指 Web 浏览器
所以 Web 服务器的工作原理可以简单的总结为:
以上步骤实现了一个 最简单的 HTTP 事务,在上述情况中,客户端与服务端的通信非持久连接,发送接收应答后就断开(这里暂时不讨论 http 1.1 之后的持久连接、后文会有专门说明)
URL 是 Uniform Resource Locator“统一资源定位符” 的英文缩写
基本格式如下图👇
而 DNS 则是 Domain Name System “域名系统” 的英文缩写,它是一种组织成 域层次结构的计算机和网络服务命名系统,它用于 TCP/IP 网络,它从事 将主机名 或者 域名转换为实际 IP 地址的工作。可以把他理解成 URL 的“翻译官”
工作原理如下图👇
我们来详细地解释一下 关于 DNS 的工作原理:
无论是转发模式还是非转发模式,是转发给上一级还是直接找根 DNS ,最后都是把 结果返回给 本地 DNS 服务器,由此 DNS服务器再返回给 我们的浏览器(客户端)
流程图如下👇
基于上面的步骤,浏览器最终通过 DNS 服务器获得的是 IP 地址,所以浏览器(客户端)发起请求的时候是通过 IP 地址 来和 服务器 进行信息通信的
HTTP 协议当然是 Web 服务器工作的核心,所以我们接下来具体详细地了解清楚一下 HTTP 协议是怎么发挥作用的
HTTP 协议 是一种能让 Web 服务器与浏览器(客户端)通过 Internet 进行发送和接受数据 动作 的一个协议,它建立在 TCP 协议之上,一般会采用 TCP 的 80 端口。它是一个标准的 “请求-响应协议” 即 客户端发出请求,服务端收到请求返回响应。
在 HTTP 协议中,客户端总是要通过建立一个连接与发送一个 HTTP 请求来发起一个事务。而服务器不能主动去与客户端联系,也不能给客户端发出一个回调连接,只能被动监听。
客户端与服务端都可以自行提前中断一个连接,例如,当浏览器下载一个文件时,你可以随时通过点击“暂停”按钮来中断文件的下载,关闭与服务器的 HTTP 连接。
HTTP 协议是无状态的,同一个客户端的这一次请求与上次请求之间没有对应关系,对 HTTP 服务器来说,它并不知道这两个请求是否来自同一个客户端。当然对于需要解决这个问题的情况我们可以使用 "Cookie"机制来维护连接的可持续状态
正因为 HTTP 协议是建立在 TCP 协议之上的,所以 TCP 攻击一样会影响 HTTP 的通信,例如常见的针对 TCP 的攻击:SYN Flood (比较流行的一种 Dos 拒绝服务攻击 和 Ddos 分布式拒绝服务攻击)就是通过利用 TCP 协议的缺陷,发送了大量的伪造 TCP 连接请求从而使得被攻击的服务器资源耗尽(CPU 满负荷或者内存不足)
接下来我们分别看看 HTTP 协议的 请求包和响应包
我们可以使用 F12 查看一些内容,例如 Request 包的结构:
Request 包分为三部分,第一部分叫 Request line (请求行),第二部分是 Request header (请求头),第三部分是 body(主体),header 和 body 之间会有个空行隔开
请求包的实例图👇
HTTP 协议定义了很多与服务器交互的请求方法,最基础的四种是:GET\POST\PUT\DELETE,一个 URL 地址用于描述一个网络上的请求资源,而 HTTP 中的这四个操作就分别对应对这个资源的查改增删4个操作
这四个操作中最熟悉和常用的是 GET 和 POST 。
GET 一般用于获取/查询资源信息
POST 一般用于更新资源信息
GET 与 POST 的区别:
关于 GET 与 POST 之间更详细的比较可参考我的另一篇 blog👇
GET 和 POST 到底有什么区别?
HTTP 的 response 包的结构如下图👇
和上面看到的请求包类似,response 响应包的第一行叫做 ”状态行“,由 HTTP 协议版本号、状态码、状态消息 三部分组成
状态码的作用是告诉 HTTP 客户端(浏览器),HTTP 服务器是否产生了预期的 Response。
在 HTTP 1.1 协议中定义了 5 类 状态码,每个状态码由三位数字组成,首位表示类别:
常见的状态有:200 :正常信息、302:跳转、404 not found 等等
无状态是指协议对于事物处理没有记忆能力,服务器不知道客户端是什么状态,体现在打开一个服务器的网页和你之前打开这个服务器的网页之间没有任何联系
HTTP 协议就是典型的无状态的面向连接的协议,虽然是无状态但是它是面向连接的协议,所以千万不要说 HTTP 使用的是 UDP (面向无连接)的协议了!!!
无状态不代表不能保持TCP连接(只要不断开连接我就不管你什么状态不状态的)
从 HTTP 1.1 开始,默认都开启了 叫做 Keep-Alive 的保持连接的特性,也就是当一个网页打开完成之后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的 TCP 连接
当然 Keep-ALive 不会永久保持连接,它会有一个保持时间上限,你可以自行设置
如果你尝试去检查(F12)访问任意一个网址
通过分析整个 URL 请求的通信过程,你会发现:
在所有的请求中不止一个 URL 请求,还会有很多其他的如静态文件的资源请求
这其实是浏览器自带的功能之一,第一次请求 url ,服务器端返回的是 HTML 页面,然后浏览器会开始渲染这个页面,但是当解析到 HTML DOM里面的图片连接、css脚本和js脚本的连接的时候,浏览器就会自动地发起一个请求静态资源的 HTTP 请求,去获取相应的资源并渲染,最终将所有资源整合完整地展现出来
在网页优化中就会有一项措施,就是利用减少 HTTP 请求次数(把尽量多的css 和 js 资源合并)减少网页请求静态资源的次数,来提高网页的加载速度,减轻服务器的压力
关于 Golang 基础部分 以及 计算机网络部分读者可以参阅我的往期 blog👇
Goalng:基础复习一遍过
漫谈计算机网络:网络层 ------ 重点:IP协议与互联网路由选择协议
以上
看完记得留下一个👍