ウェブサービス設計基礎
Last renew: April 7, 2022 pm
How the Web Works?
注:本文仅为个人学习笔记,无任何版权。
平时在上网的时候,打开浏览器,输入网址,按下回车,显示想要的内容。这个过程电脑端与服务器端是怎样实现的呢?
对于普通的上网过程,系统是这样做的:浏览器是一个客户端(client-site),当你输入URL时,首先浏览器会请求DNS服务器,通过DNS服务器获取域名所对应的IP,然后通过IP地址找到Ip对应的服务器,要求建立TCP链接,等浏览器发送完HTTP Request(请求)包之后,服务器(server-site)接收到请求包,处理请求包,调用自身服务,返回HTTP Response(响应)包;客户端收到来自服务器的响应后开始渲染这个Response包中的主体(body),等收到全部的内容后端开与服务器之间的TCP链接。
一个web服务器也被称为HTTP服务器,它通过HTTP协议与客户端通信。这个客户端一般指的是web浏览器。
web服务器端的功能可以被总结为以下几点
- 客户端通过TCP/IP协议建立到服务器的TCP连接。
- 客户端向服务器发送HTTP协议请求包(HTTP Request),请求服务器里的资源文档。
- 服务器向客户端发送HTTP协议应答包(HTTP Response),如果请求的资源包含动态语言,服务器会调用动态语言的解释引擎处理“动态内容”,并将处理得到的数据返回给客户端。
- 客户端与服务器断开,由客户端解释HTML文档,在客户端屏幕上渲染图形结果。
注:客户端与服务器之间的通讯是非持久性的,服务器发送了应答之后就会与客户端断开连接,等待下一次请求。
URLとDNS
略,Computer Science:an Overview讲过
注:DNS使用的是递归查询过程+迭代查询过程,最后获取IP地址
HTTP Protocol
HTTP协议是web工作的核心。想要了解web的工作原理,就要了解HTTP是怎么工作的。
HTTP(Hyper Text Transfer Protocol) 超文本传输协议:客户端可能发送给服务器什么样的消息以及得到什么样的响应。
HTTP是一种让web服务器与浏览器(客户端)通过互联网(Internet)发送与接收数据的协议,它建立在TCP协议之上,一般采用TCP的80端口。它是一个请求与响应的协议:客户端发出请求,服务器响应请求。服务器不能主动联系客户端,也不能给客户端发出回调链接。客户端与服务器端都可以提前中断一个连接。
HTTP协议是无状态的,同一个客户端的这次请求和上次请求没有任何对应关系。服务器并不知道这两个请求是否来自同一个客户端。为了解决这个问题,web程序引入了cookie机制来维护连接的可持续状态。
HTTP Requests (Client Site)
对于客户端发出的HTTP请求包,其结构分为三部分。第一部分为Request line(请求行),第二部分叫request header(请求头),第三部分是body(主体)。header 和 body之间有个空行,如下所示。
1 |
|
HTTP协议定义了许多与服务器交互的请求方法,最基本的有4种,GET/ POST/ PUT/ DELETE。一个URL地址用于描述一个网络上的资源,而HTTP的四个基本操作对应着对这个资源的查,增,改,删。
GET一般用于获取/查询资源信息,POST一般用于更新资源信息。
GET与POST的区别如下:
- GET的请求body为空,而POST的body不为空
- GET提交的数据会放到URL之后,以
?
分割URL和传输数据,参数之间以&
相连,如EditPosts.aspx? name=test1&id=123456
POST方法则是把提交的数据放到HTTP包的body中。 - GET提交的数据大小有限制,POST无限制
- GET提交数据会带来安全问题(URL会显示账号密码,类似zoom的登陆URL)
HTTP Response (Server site)
HTTP的response包结构如下
1 |
|
其第一行叫做状态行,由HTTP协议版本号,状态码,状态消息三部分组成
状态码用来告诉HTTP客户端,HTTP服务器是否产生了预期的Response。对于HTTP/1.1版本来说,状态码情况如下:
- 1XX 提示信息 - 表示请求已被成功接收,继续处理
- 2XX 成功 - 表示请求已被成功接收,理解,接受
- 3XX 重定向 - 要完成请求必须进行更进一步的处理
- 4XX 客户端错误 - 请求有语法错误或请求无法实现
- 5XX 服务器端错误 - 服务器未能实现合法的请求
本质上还是被分为Header(包含状态行)与Body。
HTTP と Connection: keep-alive
从HTTP/1.1起,默认开启了Keep-Alive保持连接特性,其含义是当一个网页完成打开后,客户端与服务器之间用于传输的TCP连接不会被关闭。如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的TCP连接。
Keep-Alive不会永久保持,有一个保持时间,可以设定。
Goを使ってウェブサーバーをつくよう!
对于Go语言来说,其提供给了我们一个完整的net/http
包,这样可以很方便的搭建起一个可以运行的web服务。这个使用包也能很简单的对于web的router、静态文件、模版、cookie等数据进行操作和设置。
Use net/http Package to Create a Web Server
1 |
|
上面的代码,当我们build之后,就已经在9090端口监听http链接请求了。
可以在浏览器输入http://localhost:9090
进行实验。
Goがウェブを動かすの方法
我们可以看见简单应用net/http包就可以很轻松的用Go搭建起web服务。那么go在底层是怎么做的呢?
Several concepts of how the web works
Request:用户请求的信息,用来解析用户的请求信息,包括POST、GET、cookie、url等信息。
Response:服务器需要反馈给客户端的信息
Conn:用户的每次请求链接
Handler:处理请求和生成返回信息的处理逻辑
Analyze the http package operation mechanism
- 创建Listen Socket,监听指定的端口,等待客户端请求到来。(Socket是什么)
- Listen Socket接受客户端的请求,得到Client Socket,接下来通过Client Socket与客户端通信。
- 处理客户端的请求,首先从Client Socket读取HTTP请求的协议头,如果是POST方法,还需要读取客户端提交的数据,然后交给相应的handler处理请求,handler处理完毕准备好客户端需要的数据,通过Client Socket写给客户端。
在整个过程中,我们只需要了解三个问题,就可以明白Go是如何让Web运行起来的。
- 如何监听端口?
- 如何接收客户端请求?
- 如何分配handler?
How to Listen the Part
从前面小节的代码中我们可以看出,对于监听来说,net/http
包中有一个专用的APIListenAndServe
来进行处理。
1 |
|
ListenAndServe
会初始化一个sever
对象,然后调用了Server
对象的方法ListenAndServe
。其源码如下:
1 |
|
ListenAndServe
调用了net.Listen("tcp, addr")
,也就是底层用TCP协议搭建了一个服务,最后调用src.Serve
监控我们设置的端口。监控之后如何接受客户端的请求呢?
How to Accept the Request from client-side
Serve
的具体实现如下(仅包括关键代码),通过下面的分析源码我们可以看到客户端请求的具体处理过程:
1 |
|
这个函数利用了for循环,首先通过Listener接受请求l.Accept()
,其次创建一个Conn:c := srv.newConn(rw)
,最后单独开了一个goroutine,把这个请求的数据当成参数扔给这个conn去服务:go c.serve(connCtx)
。这个就是对于高并发的体现。用户的每一次请求都是在一个新的goroutine去服务,相互不影响。
How to distribute the function to solve request.
那么如何分配具体的函数来处理请求呢?我们继续分析conn的serve
方法,其源码如下(仅展示关键代码):
1 |
|