作业内容
GitHub传送门
实验内容
概述
开发简单 web 服务程序 cloudgo,了解 web 服务器工作原理。
任务目标
- 熟悉 go 服务器工作原理
- 基于现有 web 库,编写一个简单 web 应用类似 cloudgo。
- 使用 curl 工具访问 web 程序
- 对 web 执行压力测试
相关知识
实验过程
实验环境
Ubuntu
安装所需框架
执行命令
go get github.com/go-martini/martini
go get github.com/martini-contrib/render
go get github.com/martini-contrib/binding
进行安装
基本用法可以查阅官方文档:
martini文档
render文档
binding文档
开发Cloudgo简单程序
首先看下目录结构:
assets文件夹放渲染HTML使用的资源,server下的server.go用来启动服务器,执行GET请求和POST请求,templates下的tmpl文件是用于被render.Renderer来渲染(tmpl文件其实就相对于HTML文件)。main.go主要作用是从参数中获取指定端口。
首先看一下如何从用户输入的参数中获取指定端口,这里用到之前用过的pflag包:
//从命令行中获取指定的监听端口
curPort := pflag.StringP("port", "p", "4869", "Port for listening")
pflag.Parse()
第一个参数是参数名字,第二个参数是参数名字的简写,第三个参数是默认参数的值,第四个参数为解释此参数的作用。
server.go
定义了一个Post的结构体
type Post struct {
Username string `form:"username" binding:"required"`
Password string `form:"password" binding:"required"`
}
这里使用到了bind包,这个包可以自动把POST的数据从JSON格式自动转化为go中自己定义的数据结构,非常地便捷。
GET请求:
defaultConfig.Get("/", func(r render.Render) {
//获取当前系统时间
curTime:=time.Now().Format("2006-01-02 15:04:05")
//渲染index模板,将时间传过去
r.HTML(200, "index", map[string]interface{}{"Time":curTime})
})
首先获取了系统当前时间,然后得到index模板,并把模板中的Time填充为curTime的值,最后渲染。
index模板中,这里可以接受传过来的时间:
<p class="time">Now is {{.Time}}</p>
而下面则是用于接收用户POST的表单:
<form method="post" action="/">
<p>Username:</p>
<input type="text" name="username"><br />
<p>Password:</p>
<input type="password" name="password"><br />
<input type="submit" value="登录" id="submit">
</form>
POST请求:
defaultConfig.Post("/", binding.Bind(Post{}), func(post Post, r render.Render) {
curTime:=time.Now().Format("2006-01-02 15:04:05")
p := Post{Username: post.Username, Password: post.Password}
//渲染index模板,将用户信息和时间传过去
r.HTML(200, "info", map[string]interface{}{"post": p, "Time":curTime})
})
首先在index界面由用户POST得到的数据转换成我们定义的数据结构,然后再将它和当前时间传到info的模板中,用于显示。
实验结果
使用 curl 工具访问 web 程序
使用-v命令来显示客户端与服务器交互的详细信息,其中Content显示的就是当前显示页面的HTML代码:
对 web 执行压力测试
首先终端执行命令sudo apt install apache2-utils
安装测试工具。
然后执行命令ab -n 10000 -c 1000 http://localhost:4869/
来进行压力测试, -n表示请求数,-c表示并发数,可以看到,在10000个请求,1000个并发的情况下,总共使用了8.5秒左右时间来完成处理。
重要参数解释:
- Concurrency Level:并发数
- Time taken for tests:完成所有请求总共花费的时间
- Complete requests:成功请求的次数
- Failed requests:失败请求的次数
- Total transferred:总共传输的字节数
- HTML transferred:实际页面传输的字节数
- Requests per second:每秒请求数
- Time per request: [ms] (mean): 平均每个用户等待的时间
- Time per request: [ms] (mean, across all concurrent requests) :服务器处理的平均时间
- Transfer rate:传输速率