服务计算作业七——开发 web 服务程序

概述

开发简单 web 服务程序 cloudgo,了解 web 服务器工作原理。

任务目标
  1. 熟悉 go 服务器工作原理
  2. 基于现有 web 库,编写一个简单 web 应用类似 cloudgo。
  3. 使用 curl 工具访问 web 程序
  4. 对 web 执行压力测试

任务要求

基本要求
  1. 编程 web 服务程序 类似 cloudgo 应用。
    a. 支持静态文件服务
    b. 支持简单 js 访问
    c. 提交表单,并输出一个表格(必须使用模板)
  2. 使用 curl 测试,将测试结果写入 README.md
  3. 使用 ab 测试,将测试结果写入 README.md。并解释重要参数。
拓展要求

选择以下一个或多个任务,以博客的形式提交。

  1. 通过源码分析、解释一些关键功能实现
  2. 选择简单的库,如 mux 等,通过源码分析、解释它是如何实现扩展的原理,包括一些 golang 程序设计技巧。
实现

环境:Windows10 Go1.15

参考老师的课程文件中的内容
在这里插入图片描述
在这里插入图片描述

模仿写出了以下代码:
main.go:用于创建并启动一个服务器,通过run这个代码来开启服务器;

package main

import (
	"os"

	flag "github.com/spf13/pflag"
	"github.com/user/acloudgo/CloudGo/service"
)

const (
	PORT string = "8888"
)

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)
}

server.go中有多个函数,分别也都是模仿老师课程文件中完成的:
newServer、initRoutes函数:创建并返回了一个服务器;

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
}

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("/test", testHandler(formatter)).Methods("GET")
	mx.HandleFunc("/", homeHandler(formatter)).Methods("GET")
	mx.HandleFunc("/user", userHandler).Methods("POST")
	mx.PathPrefix("/").Handler(http.FileServer(http.Dir(webRoot + "/assets/")))
}

其中
mx.PathPrefix("/").Handler(http.FileServer(http.Dir(webRoot + "/assets/")))
这条语句是将/后带参数的url定位到webRoot+‘/assets’中,如localhost:8888/img就定位到assets/img文件夹中,从而实现了静态文件的访问。

testHandler函数:用于支持简单的js访问;

func testHandler(formatter *render.Render) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		formatter.JSON(w, http.StatusOK, struct {
			S_ID string `json:"s_id"`
			Name string `json:"name"`
		}{S_ID: "18342007", Name: "zengty"})
	}
}

对应的js代码:

$(document).ready(function() {
    $.ajax({
        url: "/test"
    }).then(function(data) {
       $('.Content').append(data.S_ID);
    });
});

homeHandler、userHandler函数:返回起始页面和用户登录之后的表格页面,这两个页面分别由templates中的page.html、user.html定义,都使用了模板,userHandler实现了提交表单返回表格的功能;

func homeHandler(formatter *render.Render) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		formatter.HTML(w, http.StatusOK, "page", struct {
			Content string `json:"content"`
		}{Content: "Input your name and S_ID."})
	}
}
func userHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	name := template.HTMLEscapeString(r.Form.Get("name"))
	s_id := template.HTMLEscapeString(r.Form.Get("s_id"))
	t := template.Must(template.New("user.html").ParseFiles("./templates/user.html"))
	err := t.Execute(w, struct {
		Name string
		S_ID string
	}{Name: name, S_ID: s_id})
	if err != nil {
		panic(err)
	}
}

可以看到homeHandler中模板参数是Content提示语,userHandler的参数是从page里的form得到的name和s_id,然后利用模板分别在page和html中显示出来,效果在后面统一列举。

page.html:

<html>

<head>
  <link rel="stylesheet" href="main.css" />
</head>

<body>
  <form class="box" action="./user" method="POST">
    <h1 class="Content">{{.Content}}</h1>
    <p>Name:<input type="text" name="name"></p>
    <p>S_ID:<input type="text" name="s_id"></p>
    <p><input type="submit" value="Register"></p>
  </form>
</body>

</html>

user.html:

<html>
    
<head>
    <link rel="stylesheet" href="main.css" />
</head>

<body>
    <table border="1">
        <tr>
            <td>Name</td>
            <td>{{.Name}}</td>
        </tr>
        <tr>
            <td>S_ID</td>
            <td>{{.S_ID}}</td>
        </tr>
    </table>
</body>

</html>
效果
  1. 静态文件访问:
    assets中文件结构如下:
    在这里插入图片描述
    访问结果:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. js访问:
    通过curl工具访问,可以看到返回的是一个JSON格式的数据,因此实现了js访问。
    在这里插入图片描述
  3. 提交表单返回表格
    开始的页面如下:
    在这里插入图片描述
    然后输入name和s_id提交之后能够跳转到/user界面:
    在这里插入图片描述
测试
curl测试

在win10中安装curl的教程如下 csdn
参数的含义可以在网上找到 curl命令详解
这里调试主要用到了-v参数(输出信息)。

  1. curl -v http://localhost:8888
    测试首页,成功
C:\Users\12586>curl -v http://localhost:8888
* Rebuilt URL to: http://localhost:8888/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8888 (#0)
> GET / HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Date: Tue, 24 Nov 2020 11:10:14 GMT
< Content-Length: 368
<
<html>

<head>
  <link rel="stylesheet" href="main.css" />
</head>

<body>
  <form class="box" action="./user" method="POST">
    <h1 class="Content">Input your name and S_ID.</h1>
    <p>Name:<input type="text" name="name"></p>
    <p>S_ID:<input type="text" name="s_id"></p>
    <p><input type="submit" value="Register"></p>
  </form>
</body>

</html>* Connection #0 to host localhost left intact
  1. curl -v http://localhost:8888/img/a.png
    测试静态文件,成功
C:\Users\12586>curl -v http://localhost:8888/img/a.png
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8888 (#0)
> GET /img/a.png HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Content-Length: 54600
< Content-Type: image/png
< Last-Modified: Mon, 23 Nov 2020 14:13:22 GMT
< Date: Tue, 24 Nov 2020 11:14:37 GMT
<
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
* Failed writing body (0 != 3924)
* Closing connection 0
  1. curl -v http://localhost:8888/test
    测试 返回json,成功
C:\Users\12586>curl -v http://localhost:8888/test
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8888 (#0)
> GET /test HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=UTF-8
< Date: Tue, 24 Nov 2020 11:15:29 GMT
< Content-Length: 45
<
{
  "s_id": "18342007",
  "name": "zengty"
}
* Connection #0 to host localhost left intact
  1. curl
    测试提交表单后的页面,但是由于没有提交表单,因此失败;
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8888 (#0)
> GET /user HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Tue, 24 Nov 2020 11:18:29 GMT
< Content-Length: 19
<
404 page not found
* Connection #0 to host localhost left intact
ab压力测试

安装教程也能在网上找到:Windows下ab的安装和压测
在根目录下,输入ab -help可以看到各个参数的含义

Usage: ab [options] [http://]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 benchmarking
                    This implies -n 50000
    -s timeout      Seconds to max. wait for each response
                    Default 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 attributes
                    are a colon separated username and password.
    -P attribute    Add Basic Proxy Authentication, the attributes
                    are 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
    -l              Accept variable document length (use this for dynamic pages)
    -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.
    -m method       Method name
    -h              Display usage information (this message)

大致含义是:

-n		测试中请求总数
-c		一次产生的请求个数(并发数)
-t		测试持续的最长时间
-s		每次请求的最长等待时间
-b		TCP连接中buffer的长度
-B		进行连接使用的地址
-p		需要post的文件
-u		需要put的文件
-T		post/put数据的类型头文件
-v		显示信息的详细程度
-w		输出结果到html表中
-i		使用head替代get
……(后面的用的比较少,而且这次也没有用到就不继续往下列了)

这次测试中,主要使用的参数是-n、-c和-p。

  1. ab -n8888 -c10 http://localhost:8888/
    结果:
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
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 888 requests
Completed 1776 requests
Completed 2664 requests
Completed 3552 requests
Completed 4440 requests
Completed 5328 requests
Completed 6216 requests
Completed 7104 requests
Completed 7992 requests
Completed 8880 requests
Finished 8888 requests


Server Software:
Server Hostname:        localhost
Server Port:            8888

Document Path:          /
Document Length:        368 bytes

Concurrency Level:      10
Time taken for tests:   2.528 seconds
Complete requests:      8888
Failed requests:        0
Total transferred:      4310680 bytes
HTML transferred:       3270784 bytes
Requests per second:    3516.03 [#/sec] (mean)
Time per request:       2.844 [ms] (mean)
Time per request:       0.284 [ms] (mean, across all concurrent requests)
Transfer rate:          1665.31 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.4      0       1
Processing:     1    3   0.6      3       5
Waiting:        0    2   0.7      2       5
Total:          1    3   0.5      3       5

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      3
  75%      3
  80%      3
  90%      3
  95%      4
  98%      4
  99%      4
 100%      5 (longest request)
  1. ab -n8888 -c10 http://localhost:8888/css/a1.css/
    结果:
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
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 888 requests
Completed 1776 requests
Completed 2664 requests
Completed 3552 requests
Completed 4440 requests
Completed 5328 requests
Completed 6216 requests
Completed 7104 requests
Completed 7992 requests
Completed 8880 requests
Finished 8888 requests


Server Software:
Server Hostname:        localhost
Server Port:            8888

Document Path:          /css/a1.css/
Document Length:        0 bytes

Concurrency Level:      10
Time taken for tests:   2.596 seconds
Complete requests:      8888
Failed requests:        0
Non-2xx responses:      8888
Total transferred:      986568 bytes
HTML transferred:       0 bytes
Requests per second:    3423.72 [#/sec] (mean)
Time per request:       2.921 [ms] (mean)
Time per request:       0.292 [ms] (mean, across all concurrent requests)
Transfer rate:          371.13 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.4      0       1
Processing:     1    3   0.5      3       5
Waiting:        0    2   0.7      2       5
Total:          1    3   0.5      3       5

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      3
  75%      3
  80%      3
  90%      3
  95%      4
  98%      4
  99%      4
 100%      5 (longest request)
  1. ab -n8888 -c10 -p test.txt http://localhost:8888/
    其中test.txt存放在根目录下,内容:
    在这里插入图片描述
    实现了对post的压力测试,结果:
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
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 888 requests
Completed 1776 requests
Completed 2664 requests
Completed 3552 requests
Completed 4440 requests
Completed 5328 requests
Completed 6216 requests
Completed 7104 requests
Completed 7992 requests
Completed 8880 requests
Finished 8888 requests


Server Software:
Server Hostname:        localhost
Server Port:            8888

Document Path:          /
Document Length:        83 bytes

Concurrency Level:      10
Time taken for tests:   2.648 seconds
Complete requests:      8888
Failed requests:        0
Total transferred:      2177560 bytes
Total body sent:        1297648
HTML transferred:       737704 bytes
Requests per second:    3356.58 [#/sec] (mean)
Time per request:       2.979 [ms] (mean)
Time per request:       0.298 [ms] (mean, across all concurrent requests)
Transfer rate:          803.09 [Kbytes/sec] received
                        478.58 kb/s sent
                        1281.66 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.4      0       2
Processing:     1    3   0.6      3      10
Waiting:        0    2   0.8      2      10
Total:          1    3   0.6      3      10

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      3
  75%      3
  80%      3
  90%      3
  95%      4
  98%      4
  99%      5
 100%     10 (longest request)
拓展要求

服务计算作业七——mux包源码分析,从与DefaultServeMux对比入手

源代码:

GitHub

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值