基于Golang的简单web服务程序开发——CloudGo
基于Golang的简单web服务程序开发——CloudGo【阅读时间:约10分钟】
- 一、概述
- 二、系统环境&项目介绍
- 1.系统环境
- 2.项目的任务要求
- (1)基本要求
- (2)扩展要求
- 三、具体程序设计及Golang代码实现
- 1.预先准备
- 2.CloudGoClient.go的main函数
- 3.CloudServer.go的NewServer函数
- 4.CloudServer.go的initRoutes函数
- 5.CloudServer.go的apiTestHandler函数
- 6.CloudServer.go的homeHandler函数
- 7.CloudServer.go的userHandler函数
- 四、程序使用与测试
- 1.封装并使用程序包
- 2.功能测试
- 3.curl连接测试
- 4.ab压力测试,并解释重要参数
- 五、完整代码
- 六、扩展博客
- 七、References
一、概述
开发简单 web 服务程序 cloudgo,了解 web 服务器工作原理。
任务目标
- 熟悉 go 服务器工作原理
- 基于现有 web 库,编写一个简单 web 应用类似 cloudgo。
- 使用 curl 工具访问 web 程序
- 对 web 执行压力测试
二、系统环境&项目介绍
1.系统环境
操作系统:CentOS7
硬件信息:使用virtual box配置虚拟机(内存3G、磁盘30G)
编程语言:GO 1.15.2
2.项目的任务要求
(1)基本要求
- 编程 web 服务程序 类似 cloudgo 应用。
- 支持静态文件服务
- 支持简单 js 访问
- 提交表单,并输出一个表格(必须使用模板)
- 使用 curl 测试,将测试结果写入 README.md
- 使用 ab 测试,将测试结果写入 README.md。并解释重要参数。
(2)扩展要求
选择以下一个或多个任务,以博客的形式提交。
- 通过源码分析、解释一些关键功能实现
- 选择简单的库,如 mux 等,通过源码分析、解释它是如何实现扩展的原理,包括一些 golang 程序设计技巧。
三、具体程序设计及Golang代码实现
1.预先准备
首先需要安装以下三个程序包:
[henryhzy@localhost ~]$ go get github.com/codegangsta/negroni
[henryhzy@localhost ~]$ go get github.com/gorilla/mux
[henryhzy@localhost ~]$ go get github.com/unrolled/render
下面我按照以下顺序来介绍简单web服务程序——CloudGo的程序设计:
①CloudGoClient.go的main函数
②CloudServer.go的NewServer函数
③CloudServer.go的initRoutes函数
④CloudServer.go的apiTestHandler函数
⑤CloudServer.go的homeHandler函数
⑥CloudServer.go的userHandler函数
2.CloudGoClient.go的main函数
借鉴课程博客1,编写CloudGoClient.go的main函数如下:
package mainimport ("os"flag "github.com/spf13/pflag""github.com/user/CloudGo/service"
)const (PORT string = "2026"
)func main() {port := os.Getenv("PORT")if len(port) == 0 {port = PORT}pPort := flag.StringP("port", "p", PORT, "PORT for httpd listening")flag.Parse()if len(*pPort) != 0 {port = *pPort}server := service.NewServer()server.Run(":" + port)
}
3.CloudServer.go的NewServer函数
借鉴课程博客2,编写CloudServer.go的NewServer函数如下:
// NewServer configures and returns a Server.
func NewServer() *negroni.Negroni {formatter := render.New(render.Options{Directory: "templates",Extensions: []string{".html"},IndentJSON: true,})n := negroni.Classic()mx := mux.NewRouter()initRoutes(mx, formatter)n.UseHandler(mx)return n
}
4.CloudServer.go的initRoutes函数
借鉴课程博客2,编写CloudServer.go的initRoutes函数如下:
func initRoutes(mx *mux.Router, formatter *render.Render) {webRoot := os.Getenv("WEBROOT")if len(webRoot) == 0 {if root, err := os.Getwd(); err != nil {panic("Could not retrive working directory")} else {webRoot = root//fmt.Println(root)}}mx.HandleFunc("/api/test", apiTestHandler(formatter)).Methods("GET")mx.HandleFunc("/", homeHandler(formatter)).Methods("GET")mx.HandleFunc("/user", userHandler).Methods("POST")mx.PathPrefix("/").Handler(http.FileServer(http.Dir(webRoot + "/assets/")))
}
5.CloudServer.go的apiTestHandler函数
借鉴课程博客2,编写CloudServer.go的apiTestHandler函数如下:
//mx.HandleFunc("/api/test", apiTestHandler(formatter)).Methods("GET")func apiTestHandler(formatter *render.Render) http.HandlerFunc {return func(w http.ResponseWriter, req *http.Request) {formatter.JSON(w, http.StatusOK, struct {ID string `json:"id"`Content string `json:"content"`}{ID: "18342026", Content: "Hello from Go!"})}
}
其对应的js文件为apitest.js,内容如下:
$(document).ready(function() {$.ajax({url: "/api/test"}).then(function(data) {$('.ID').append(data.ID);$('.Content').append(data.Content);});
});
6.CloudServer.go的homeHandler函数
借鉴课程博客2,编写CloudServer.go的homeHandler函数如下:
//main
//mx.HandleFunc("/", homeHandler(formatter)).Methods("GET")func homeHandler(formatter *render.Render) http.HandlerFunc {return func(w http.ResponseWriter, req *http.Request) {template := template.Must(template.New("home.html").ParseFiles("./templates/home.html"))_ = template.Execute(w, struct {ID stringContent string}{ID: "18342026", Content: "Welcome to CloudGo!!"})}
}
home对应的是网页的初始页面,需要再编写相对应的home.html和home.css,这里为了符合课程博客的“提交表单”要求,我将其设置为登录页面:
<html><head><link rel="stylesheet" href="css/home.css" />
</head><body><form class="box" action="./user" method="POST"><h1 class="Content">{{.Content}}</h1><input type="text" name="username" placeholder="Username"><input type="password" name="password" placeholder="Password"><input type="submit" value="Sign In"><h4 class="Content">{{"Designed By HenryHZY, 18342026."}}</h4><img src="files/nice picture.png" height="400" width="400"/></form>
</body></html>
7.CloudServer.go的userHandler函数
借鉴课程博客2,编写CloudServer.go的userHandler函数如下:
func userHandler(w http.ResponseWriter, r *http.Request) {r.ParseForm()username := template.HTMLEscapeString(r.Form.Get("username"))password := template.HTMLEscapeString(r.Form.Get("password"))t := template.Must(template.New("user.html").ParseFiles("./templates/user.html"))err := t.Execute(w, struct {Username stringPassword stringID stringMotto string}{Username: username, Password: password, ID: "18342026", Motto: "Stay hungry, stay foolish."})if err != nil {panic(err)}
}
user对应的是登录后跳转的页面,需要再编写相对应的user.html和user.css,这里为了符合课程博客的“输出一个表格”要求,我将其设置为对应的登录用户的个人信息:
<html><head><link rel="stylesheet" href="css/user.css" />
</head><body><table class="box" border="4"><tr><td>Username</td><td>{{.Username}}</td></tr><tr><td>Password</td><td>{{.Password}}</td></tr><tr><td>ID</td><td>{{.ID}}</td></tr><tr><td>Motto</td><td>{{.Motto}}</td></tr></table>
</body></html>
四、程序使用与测试
1.封装并使用程序包
在项目CloudGo的目录下,执行如下指令:
go install
在其他路径下建立main.go,并调用CloudGo库即可。
2.功能测试
功能测试主要从用户角度测试程序包的功能,在【三、具体程序设计及Golang代码实现】已设计了main函数,直接通过以下指令运行即可:
[henryhzy@localhost CloudGo]$ go run CloudGoClient.go
然后在浏览器中进入http://localhost:2026浏览即可,下面以项目的要求来演示功能测试结果。
编程 web 服务程序 类似 cloudgo 应用。
①支持静态文件服务
②支持简单 js 访问
③提交表单,并输出一个表格(必须使用模板)
①支持静态文件服务
进入http://localhost:2026/files:
访问图片文件:
访问文本文件:
②支持简单 js (JavaScript )访问
上文我借鉴课程博客2,设计了apiTestHandler函数。
这段代码非常简单,输出了一个 匿名结构,并 JSON (JavaScript Object Notation) 序列化输出。
进入http://localhost:2026/api/test:
可以使用其来进行筛选和查看原始数据等操作:
③提交表单,并输出一个表格(必须使用模板)
为了符合课程博客的要求,我将网页的初始页面设置为登录页面,需要输入username和password,再点击sign in按钮来实现“提交表单”;将登录后跳转的页面设置为显示对应的登录用户的个人信息表格,来实现“输出一个表格”。
此外根据博客要求,使用模板即使用html+css,此处已在【三、具体程序设计及Golang代码实现】中给出。
访问http://localhost:2026/:
3.curl连接测试
①curl -v http://localhost:2026/files
[henryhzy@localhost ~]$ curl -v http://localhost:2026/files
* About to connect() to localhost port 2026 (#0)
* Trying ::1...
* Connected to localhost (::1) port 2026 (#0)
> GET /files HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:2026
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Location: files/
< Date: Sun, 22 Nov 2020 12:37:50 GMT
< Content-Length: 0
<
* Connection #0 to host localhost left intact
②curl -v http://localhost:2026/files/nice_text.txt
[henryhzy@localhost ~]$ curl -v http://localhost:2026/files/nice_text.txt
* About to connect() to localhost port 2026 (#0)
* Trying ::1...
* Connected to localhost (::1) port 2026 (#0)
> GET /files/nice_text.txt HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:2026
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Content-Length: 21
< Content-Type: text/plain; charset=utf-8
< Last-Modified: Sun, 22 Nov 2020 12:36:41 GMT
< Date: Sun, 22 Nov 2020 12:38:37 GMT
<
* Connection #0 to host localhost left intact
③curl -v http://localhost:2026/api/test
[henryhzy@localhost ~]$ curl -v http://localhost:2026/api/test
* About to connect() to localhost port 2026 (#0)
* Trying ::1...
* Connected to localhost (::1) port 2026 (#0)
> GET /api/test HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:2026
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=UTF-8
< Date: Sun, 22 Nov 2020 12:39:01 GMT
< Content-Length: 54
<
{"id": "18342026","content": "Hello from Go!"
}
* Connection #0 to host localhost left intact
④curl -v http://localhost:2026
[henryhzy@localhost ~]$ curl -v http://localhost:2026
* About to connect() to localhost port 2026 (#0)
* Trying ::1...
* Connected to localhost (::1) port 2026 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:2026
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 22 Nov 2020 12:39:26 GMT
< Content-Length: 504
< Content-Type: text/html; charset=utf-8
<
<html><head><link rel="stylesheet" href="css/home.css" />
</head><body><form class="box" action="./user" method="POST"><h1 class="Content">Welcome to CloudGo!!</h1><input type="text" name="username" placeholder="Username"><input type="password" name="password" placeholder="Password"><input type="submit" value="Sign In"><h4 class="Content">Designed By HenryHZY, 18342026.</h4><img src="files/nice picture.png" height="400" width="400"/></form>
</body>* Connection #0 to host localhost left intact
⑤curl -v http://localhost:2026/errorTest
此处是进行错误测试,当对应的网页不存在,便会返回404 NOT FOUND的错误信息。
[henryhzy@localhost ~]$ curl -v http://localhost:2026/errorTest
* About to connect() to localhost port 2026 (#0)
* Trying ::1...
* Connected to localhost (::1) port 2026 (#0)
> GET /errorTest HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:2026
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Sun, 22 Nov 2020 12:40:20 GMT
< Content-Length: 19
<
404 page not found
* Connection #0 to host localhost left intact
4.ab压力测试,并解释重要参数
①首先安装压力测试需要的软件:
[henryhzy@localhost ~]$ sudo yum -y install httpd-tools
②参数解释
输入ab -help:
[henryhzy@localhost ~]$ ab -help
Usage: ab [options] [http[s]://]hostname[:port]/path
Options are:-n requests Number of requests to perform-c concurrency Number of multiple requests to make at a time-t timelimit Seconds to max. to spend on benchmarkingThis implies -n 50000-s timeout Seconds to max. wait for each responseDefault is 30 seconds-b windowsize Size of TCP send/receive buffer, in bytes-B address Address to bind to when making outgoing connections-p postfile File containing data to POST. Remember also to set -T-u putfile File containing data to PUT. Remember also to set -T-T content-type Content-type header to use for POST/PUT data, eg.'application/x-www-form-urlencoded'Default is 'text/plain'-v verbosity How much troubleshooting info to print-w Print out results in HTML tables-i Use HEAD instead of GET-x attributes String to insert as table attributes-y attributes String to insert as tr attributes-z attributes String to insert as td or th attributes-C attribute Add cookie, eg. 'Apache=1234'. (repeatable)-H attribute Add Arbitrary header line, eg. 'Accept-Encoding: gzip'Inserted after all normal header lines. (repeatable)-A attribute Add Basic WWW Authentication, the attributesare a colon separated username and password.-P attribute Add Basic Proxy Authentication, the attributesare a colon separated username and password.-X proxy:port Proxyserver and port number to use-V Print version number and exit-k Use HTTP KeepAlive feature-d Do not show percentiles served table.-S Do not show confidence estimators and warnings.-q Do not show progress when doing more than 150 requests-g filename Output collected data to gnuplot format file.-e filename Output CSV file with percentages served-r Don't exit on socket receive errors.-h Display usage information (this message)-Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)-f protocol Specify SSL/TLS protocol(SSL3, TLS1, TLS1.1, TLS1.2 or ALL)
由上可知,ab压力测试指令的格式为:ab [options] url
其中url为要进行压力测试的连接,option为输入参数,具体如下:
-n 即requests,用于指定压力测试总共的执行次数。
-c 即concurrency,用于指定的并发数。
-t 即timelimit,等待响应的最大时间(单位:秒)。
-b 即windowsize,TCP发送/接收的缓冲大小(单位:字节)。
-p 即postfile,发送POST请求时需要上传的文件,此外还必须设置-T参数。
-u 即putfile,发送PUT请求时需要上传的文件,此外还必须设置-T参数。
-T 即content-type,用于设置Content-Type请求头信息,例如:application/x-www-form-urlencoded,默认值为text/plain。
-v 即verbosity,指定打印帮助信息的冗余级别。
-w 以HTML表格形式打印结果。
-i 使用HEAD请求代替GET请求。
-x 插入字符串作为table标签的属性。
-y 插入字符串作为tr标签的属性。
-z 插入字符串作为td标签的属性。
-C 添加cookie信息,例如:"Apache=1234"(可以重复该参数选项以添加多个)。
-H 添加任意的请求头,例如:"Accept-Encoding: gzip",请求头将会添加在现有的多个请求头之后(可以重复该参数选项以添加多个)。
-A 添加一个基本的网络认证信息,用户名和密码之间用英文冒号隔开。
-P 添加一个基本的代理认证信息,用户名和密码之间用英文冒号隔开。
-X 指定使用的和端口号,例如:"126.10.10.3:88"。
-V 打印版本号并退出。
-k 使用HTTP的KeepAlive特性。
-d 不显示百分比。
-S 不显示预估和警告信息。
-g 输出结果信息到gnuplot格式的文件中。
-e 输出结果信息到CSV格式的文件中。
-r 指定接收到错误信息时不退出程序。
-h 显示用法信息,其实就是ab -help。
此外,输出参数如下:
Server Software: nginx/1.10.2 (服务器软件名称及版本信息)
Server Hostname: 192.168.1.106(服务器主机名)
Server Port: 80 (服务器端口)
Document Path: /index1.html. (供测试的URL路径)
Document Length: 3721 bytes (供测试的URL返回的文档大小)
Concurrency Level: 1000 (并发数)
Time taken for tests: 2.327 seconds (压力测试消耗的总时间)
Complete requests: 5000 (的总次数)
Failed requests: 688 (失败的请求数)
Write errors: 0 (网络连接写入错误数)
Total transferred: 17402975 bytes (传输的总数据量)
HTML transferred: 16275725 bytes (HTML文档的总数据量)
Requests per second: 2148.98 [#/sec] (mean) (平均每秒的请求数) 这个是非常重要的参数数值,服务器的吞吐量
Time per request: 465.338 [ms] (mean) (所有并发用户(这里是1000)都请求一次的平均时间)
Time request: 0.247 [ms] (mean, across all concurrent requests) (单个用户请求一次的平均时间)
Transfer rate: 7304.41 [Kbytes/sec] received 每秒获取的数据长度 (传输速率,单位:KB/s)
...
Percentage of the requests served within a certain time (ms)50% 347 ## 50%的请求在347ms内返回 66% 401 ## 60%的请求在401ms内返回 75% 43180% 51690% 60095% 84698% 157199% 1593100% 1619 (longest request)
③简单的压力测试
此处我主要使用-n和-c参数,即”用于指定压力测试总共的执行次数“和”用于指定的并发数“。另外,我们需要注意-c的数值需要小于或等于-n的数值。
(1)ab -n 2026 -c 10 http://localhost:2026/files
[henryhzy@localhost ~]$ ab -n 2026 -c 10 http://localhost:2026/files
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking localhost (be patient)
Completed 202 requests
Completed 404 requests
Completed 606 requests
Completed 808 requests
Completed 1010 requests
Completed 1212 requests
Completed 1414 requests
Completed 1616 requests
Completed 1818 requests
Completed 2020 requests
Finished 2026 requestsServer Software:
Server Hostname: localhost
Server Port: 2026Document Path: /files
Document Length: 0 bytesConcurrency Level: 10
Time taken for tests: 0.729 seconds
Complete requests: 2026
Failed requests: 0
Write errors: 0
Non-2xx responses: 2026
Total transferred: 218808 bytes
HTML transferred: 0 bytes
Requests per second: 2780.91 [#/sec] (mean)
Time per request: 3.596 [ms] (mean)
Time per request: 0.360 [ms] (mean, across all concurrent requests)
Transfer rate: 293.30 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 0 0.1 0 2
Processing: 1 3 4.0 1 24
Waiting: 0 3 4.0 1 23
Total: 1 4 4.0 2 24Percentage of the requests served within a certain time (ms)50% 266% 275% 380% 590% 795% 1498% 1899% 19100% 24 (longest request)
(2)ab -n 2026 -c 10 http://localhost:2026/files/nice_text.txt
[henryhzy@localhost ~]$ ab -n 2026 -c 10 http://localhost:2026/files/nice_text.txt
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking localhost (be patient)
Completed 202 requests
Completed 404 requests
Completed 606 requests
Completed 808 requests
Completed 1010 requests
Completed 1212 requests
Completed 1414 requests
Completed 1616 requests
Completed 1818 requests
Completed 2020 requests
Finished 2026 requestsServer Software:
Server Hostname: localhost
Server Port: 2026Document Path: /files/nice_text.txt
Document Length: 21 bytesConcurrency Level: 10
Time taken for tests: 0.725 seconds
Complete requests: 2026
Failed requests: 0
Write errors: 0
Total transferred: 417356 bytes
HTML transferred: 42546 bytes
Requests per second: 2793.84 [#/sec] (mean)
Time per request: 3.579 [ms] (mean)
Time per request: 0.358 [ms] (mean, across all concurrent requests)
Transfer rate: 562.04 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 1 3 4.1 2 23
Waiting: 0 3 4.1 1 23
Total: 1 4 4.2 2 23Percentage of the requests served within a certain time (ms)50% 266% 275% 380% 490% 895% 1698% 1899% 19100% 23 (longest request)
(3)ab -n 2026 -c 10 http://localhost:2026/api/test
[henryhzy@localhost ~]$ ab -n 2026 -c 10 http://localhost:2026/api/test
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking localhost (be patient)
Completed 202 requests
Completed 404 requests
Completed 606 requests
Completed 808 requests
Completed 1010 requests
Completed 1212 requests
Completed 1414 requests
Completed 1616 requests
Completed 1818 requests
Completed 2020 requests
Finished 2026 requestsServer Software:
Server Hostname: localhost
Server Port: 2026Document Path: /api/test
Document Length: 54 bytesConcurrency Level: 10
Time taken for tests: 0.642 seconds
Complete requests: 2026
Failed requests: 0
Write errors: 0
Total transferred: 358602 bytes
HTML transferred: 109404 bytes
Requests per second: 3157.84 [#/sec] (mean)
Time per request: 3.167 [ms] (mean)
Time per request: 0.317 [ms] (mean, across all concurrent requests)
Transfer rate: 545.84 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 0 0.4 0 9
Processing: 1 3 3.4 1 18
Waiting: 0 3 3.4 1 18
Total: 1 3 3.5 2 22Percentage of the requests served within a certain time (ms)50% 266% 275% 380% 490% 795% 1398% 1799% 18100% 22 (longest request)
(4)ab -n 2026 -c 10 http://localhost:2026/
[henryhzy@localhost ~]$ ab -n 2026 -c 10 http://localhost:2026/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking localhost (be patient)
Completed 202 requests
Completed 404 requests
Completed 606 requests
Completed 808 requests
Completed 1010 requests
Completed 1212 requests
Completed 1414 requests
Completed 1616 requests
Completed 1818 requests
Completed 2020 requests
Finished 2026 requestsServer Software:
Server Hostname: localhost
Server Port: 2026Document Path: /
Document Length: 504 bytesConcurrency Level: 10
Time taken for tests: 1.064 seconds
Complete requests: 2026
Failed requests: 0
Write errors: 0
Total transferred: 1258146 bytes
HTML transferred: 1021104 bytes
Requests per second: 1903.61 [#/sec] (mean)
Time per request: 5.253 [ms] (mean)
Time per request: 0.525 [ms] (mean, across all concurrent requests)
Transfer rate: 1154.44 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 1 5 5.1 3 25
Waiting: 0 5 5.1 2 25
Total: 1 5 5.1 3 26Percentage of the requests served within a certain time (ms)50% 366% 475% 580% 890% 1195% 1898% 2399% 24100% 26 (longest request)
(5)ab -n 2026 -c 10 http://localhost:2026/errorTest
Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking localhost (be patient)
Completed 202 requests
Completed 404 requests
Completed 606 requests
Completed 808 requests
Completed 1010 requests
Completed 1212 requests
Completed 1414 requests
Completed 1616 requests
Completed 1818 requests
Completed 2020 requests
Finished 2026 requestsServer Software:
Server Hostname: localhost
Server Port: 2026Document Path: /errorTest
Document Length: 19 bytesConcurrency Level: 10
Time taken for tests: 0.669 seconds
Complete requests: 2026
Failed requests: 0
Write errors: 0
Non-2xx responses: 2026
Total transferred: 356576 bytes
HTML transferred: 38494 bytes
Requests per second: 3028.19 [#/sec] (mean)
Time per request: 3.302 [ms] (mean)
Time per request: 0.330 [ms] (mean, across all concurrent requests)
Transfer rate: 520.47 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 1 3 3.6 1 19
Waiting: 0 3 3.5 1 18
Total: 1 3 3.6 2 19Percentage of the requests served within a certain time (ms)50% 266% 275% 380% 490% 795% 1398% 1799% 18100% 19 (longest request)
五、完整代码
具体代码可见gitee仓库:gitee
六、扩展博客
(2)扩展要求选择以下一个或多个任务,以博客的形式提交。1. 通过源码分析、解释一些关键功能实现
2. 选择简单的库,如 mux 等,通过源码分析、解释它是如何实现扩展的原理,包括一些 golang 程序设计技巧。
扩展博客:【Golang源码分析】Go Web常用程序包gorilla/mux的源码剖析
七、References
- 课程博客1
- 课程博客2
- ab压力测试安装与解释
相关文章:

Android Studio创建项目
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010046908/article/details/47000873 创建项目 首先,先指出Android Studio中的两个概念。 Project和 Module。在Android Studio中, Project的真实含义…
Weiss的数据结构与算法分析(C++版)源码编译说明
最近尝试编译Weiss的那本数据结构与算法分析(C版)提供的源代码时,遇到一些问题,特记录如下:考虑到该书提供的代码是使用模板技术较多,这在提供简洁代码的同时,也给源码的编译带来了一些问题。因…

latex 中文_【小白向】LaTeX 中文入门
注:本文尚未撰写完毕,先暂存一下~(2020/06/27)参考学习路线[1]如何从零开始,入门 LaTeX? 孟晨 1. 卸载 CTeX 套装,安装 TeX Live原因及教程见:TeX Live 下载及安装说明2. 看完:一份其实很短的 L…

物联网兴起 嵌入式系统安全日益受关注
随着越来越多设备连接到互联网,专家们担心嵌入式系统将给企业带来严重安全风险,而很多企业还没有意识到这种风险或者无法缓解这种风险…… 随着越来越多设备连接到互联网,专家们担心嵌入式系统将给企业带来严重安全风险,而很多企业…

【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析
目录【阅读时间:约10分钟】一.概述二.对比: gorilla/mux与net/http DefaultServeMux三.简单使用四.源码简析1.NewRouter函数2.HandleFunc函数设置路由的HTTP方法设置路由的域名限制HTTP 方案设置路径前缀和子路由3.PathPrefix函数五.References一.概述 gorilla/mux…

FileMaker中的腳本觸發器學習筆記
脚本触发器 **脚本触发器是始终绑定到用户布局接口。对于数据表或者字段。只有在而已接口才能触发。**如果某一个布局或者对象上包含触发器,则其右下角会有触发器图标**当触发一个事件时,有且仅有一个触发器会被执行.布局级别的触发器**ONRECORDLOAD :加…

vim学习笔记(四)
下面是我的最近更新,差点删除。 下面的笔记摘自vimtutor。<CR>表示回车 删除命令 在normal模式下: de 删除一个单词,不包含空格 dw 删除一个单词,包含空格 dd 删除当前行 1,10d 删除指定行,第1到10行 ndd…

文件和缓存项目依赖
文件和缓存项目依赖 要创建缓存依赖,你需要创建一个 CacheDependency 对象并在添加依赖的缓存项目时使用它。例如,下面的代码创建一个缓存项目,它在一个 XML 文件被修改、删除、覆盖时自动从缓存中移除: CacheDependency prodDepe…

python函数的基础知识_Python入门基础知识点(函数进阶)
动态参数: 动态接收位置参数: def eat(*args): #在形参位置,*叫做聚合 print(我想吃,args) eat(大米饭,中米饭,小米饭) #收到的结果是一个tuple元祖 动态接收参数的时候要注意: 动态参数必须在位置参数后面,否则: def …

【CentOS】利用Kubeadm部署Kubernetes (K8s)
【CentOS】利用Kubeadm部署Kubernetes (K8s)【阅读时间:约10分钟】一、概述二、系统环境&项目介绍1.系统环境2.项目的任务要求三、具体实验流程1 系统准备2 安装常用包3 使用aliyun源安装docker-ce4 安装kubectl、kubelet、kubeadm5 初始…
HttpClient4.4 登录知乎(详细过程)
引言 HttpClient是java语言下一个支持http协议的客户端编程工具包,它实现了HTTP协议的所有方法,但是不支持JS渲染。我们在做一些小玩意时,有可能需要登录某些网站获取信息,那么HttpClient就是你的好帮手,废话不多说&am…

vim学习笔记(一)
:vertical sfind 垂直分隔窗口(vsf),但是两个窗口的内容完全相同。在编辑的时候,内容也完全相同,如果要关闭一个窗口,输入:exit即可:buffers 显示整个缓冲区列表ndG 删除从当前行到指定n行中的…

Retrofit源码研究
2016-05-06 15:35:27 最近抽空研究了一下Retrofit源码,包括API使用、源码结构、使用到的设计模式、SDK的架构设计、作者设计/实现思路等,会形成一系列文章。 以前Retrofit还是1.9的时候,简单的写过一篇文章,简单研究下Retrofit&am…

wpf窗口向左向上_PaperWM:GNOME 下的平铺窗口管理
我使用 Gnome 已有很长时间了,但是我仍然有点想念平铺窗口管理器。六个月前,一个朋友告诉我有关 PaperWM 的消息,它使你可以在 Gnome 中平铺窗口!我立即安装了它,并从那时起我一直在使用它。-- Julia Evans(作者)当我开…

Docker的安装、镜像源更换与简单应用
Docker的安装、镜像源更换与简单应用【阅读时间:约20分钟】一、概述二、系统环境&项目介绍1.系统环境2.项目的任务要求三、Docker的安装四、Docker的简单应用1. 运行第一个容器2. Docker基本操作3. MySQL与容器化3.1 拉取MySQL镜像3.2 构建docker镜像3.3 MySQL容…

vim学习笔记(三)
1.vim的配置文件在哪里?在normal模式下输入:echo $VIMVim的主配置文件为vimrc文件,它分为两个版本:global和personal,其中前者一般在/usr/share/vim/vimrc,后者一般在~/.vimrc,它是一个隐藏文件找到home目录的方法:ech…

python 学术_Python
前几天实验室一个师兄给我一个质谱结果,让帮忙做下go的功能富集,数据格式大概是这样的:由于之前做go和kegg时都是跑流程,像这种针对性的go富集还没做过,说到底,还是由于自己手上缺少数据,没有属…

Hive的Security配置
为了更好地使用好Hive,我将《Programming Hive》的Security章节取出来,翻译了一下。 Hive还是支持相当多的权限管理功能,满足一般数据仓库的使用。 Hive由一个默认的设置来配置新建文件的默认权限。 Xml代码 <property> <name>…

Docker安装Apache与运行简单的web服务——httpd helloworld
Docker运行简单的web服务——httpd helloworld目录【阅读时间:约5分钟】一、Docker简介二、Docker的安装与配置【CentOS环境】三、Docker运行简单的web服务——httpd helloworld四、References一、Docker简介 Docker 是一个开源的应用容器引擎,让开发者…

在CentOS 6.2上搭建vim开发环境
在CentOS 6.2上搭建vim开发环境最后更新日期:2013-07-051.首先使用Ubuntu(所在ip为192.168.16.230)翻墙登陆http://www.vim.org/,下载其上面的vim相关插件到Ubuntu的下载目录下:cd ~/下载/http://ctags.sourceforge.ne…

python基础(三元运算+深浅拷贝+函数参数)
三元运算 三元运算,又称三目运算,主要作用是减少代码量,是对简单的条件语句的缩写。 1 书写格式: 2 result 值1 if 条件 else 值2 3 即如果条件成立,则将值1赋给result变量,如果不成立,将值2赋…

pythonapi是什么_python接口自动化(一)--什么是接口、接口优势、类型(详解)...
简介经常听别人说接口测试,接口测试自动化,但是你对接口,有多少了解和认识,知道什么是接口吗?它是用来做什么的,测试时候要注意什么?坦白的说,笔者之前也不是很清楚。接下来先看一下…

【阶段小结】协同开发——这学期的Git使用小结
【阶段小结】协同开发——这学期的Git使用小结一、Git简介1. Git简单介绍2. Git工作流程以及各个区域3. Git文件状态变化二、Git安装&Git基本配置三、个人踩坑1. xcode project“抽风式”问题2. 如何拯救git仓库一、Git简介 1. Git简单介绍 Git是一个分布式版本控制软件&…

PHP函数printf()、sprintf()的用法
printf()函数优点在于可以格式化输出 格式: %[padding_character][-][width][.precision]type 所有的转换说明都是以%开始,如果想打印一个%符号,必须用%% ; 参数“padding_character”是可选,它将被用来填充变量直至所指定的宽度,该参数的作用…

20150411--Dede二次开发-01
20150411--Dede二次开发-01 目录 一、目前市场流行的电子商城系统 1 二、ecshop的介绍 1 三、安装 2 四、echsop 的目录结构 5 五、分析ecshop里面程序的架构 5 六、小试牛刀把面包屑导航改成两个大于号 6 1、根据php页面找出该页面对应的模板。 6 2、找到category.dwt模板文件…

修改cpu型号重启不变_猫头鹰展示D系列新款140毫米CPU散热器:更大散热片,能压400瓦...
猫头鹰一直以超强的CPU风冷散热器在电脑配件市场闻名遐迩,在台北电脑展期间,除了展出了概念性的无风扇CPU散热器,还宣布了发布D系列新款CPU散热器的计划。新的未命名的散热器相比与目前的NH-D15和NH-D15S型号要多一根热管,性能进一…

管理虚拟机的艺术——有备无患
随心前言:求求你们多多给虚拟机做一下备份~~ 超前预告:下一次分享一下linux/window to go的小玩意(把系统安装到U盘,即插即用) 接下来的博客尝试一下用随笔的形式,来写写自己感兴趣的一些玩意,比…

coreseek最大检索数只有1000的问题!
在 测试中发现,综艺视频只能看33页,每页10条,始终不得其解。经仔细分析,是csft.conf中的配置,下面修改说明如下:先将csft.conf中的searchd部分,将1000默认值改为10000max_matches 10000然后在调…

iframe怎么用_怎么样减少无效URL的爬行和索引
少年老成的云晨守望同学(题外话:少年老成是好事哈。我20多岁时人家说我像40岁,我40多岁时好多人说我像30多,男人20到50岁可以做到基本一个样子)在网络营销实战密码网站贴了个帖子:《透过京东商城看国内一线B2C网站SEO通病》。建议…

502 Server dropped connection
在本地电脑上开启了,全局VPN代理后,出现 502 报错。 502 Server dropped connection The following error occurred while trying to access http://localhost/invo/:502 Server dropped connection. 出现这种情况的原因是,vpn 链接挂了&…