开发 web 服务程序——cloudgo

开发 web 服务程序——cloudgo

gitee仓库

一、功能介绍

  • 编程 web 服务程序 类似 cloudgo 应用
    • 支持静态文件服务
    • 简单js访问
    • 提交表单,并输出一个表格(必须使用模板)
    • 支持文件上传(拓展
    • 实现文件下载(拓展

二、Web框架选择

本次作业中选用beego来搭建web服务,因为beego有比较好的中文文档(便于理解),而且自带bee工具比较实用

2.1 安装beego:

go get github.com/astaxie/beego

2.2 安装bee工具:

go get github.com/beego/bee
  • 安装完成后输入bee version来检测是否安装成功,正确反馈如下:

在这里插入图片描述

  • bee工具非常实用,我们只需要在$GOPATH/src目录下使用bee new <项目名>即可新建项目:
  • 进入对应项目文件目录后,使用bee run命令即可运行程序
  • 之后便可在beego框架上进行程序实现

2.3 Beego/Bee工具安装排坑

  • 解决安装Beego/Bee过程中可能遇到一些问题,版本不匹配等,详情见我的另一篇博客
  • 连接Beego/Bee工具安装排坑

三、程序实现:

  • 目录结构:
    • conf:存储配置信息:端口号,name等
    • controllers:存储控制器设置,在路由设置中调用对应的控制器
    • routers:路由设置,设置对应的url调用的控制器等
    • static:静态文件目录,存储文件的静态文件访问和本次实现的文件上传下载的文件存储
    • test:bee新建项目后,自带的测试程序(不用管它
    • views:存放模板文件
    • main:实现服务的运行等设置
.
├── cloudgo
├── conf
│   └── app.conf
├── controllers
│   ├── default.go
│   ├── file.go
│   ├── loadfile.go
│   ├── login.go
│   └── user.go
├── go.mod
├── go.sum
├── lastupdate.tmp
├── main.go
├── models
├── routers
│   └── router.go
├── static
│   ├── css
│   ├── img
│   │   ├── img0.jpg
│   │   ├── img1.jpeg
│   │   └── img2.jpeg
│   └── js
│       └── reload.min.js
├── tests
│   └── default_test.go
└── views
    ├── hello.js
    ├── index.html
    ├── index.tpl
    ├── login.tpl
    ├── table.html
    └── upload.tpl

10 directories, 23 files

3.1 实现简单的js访问

实现js数据的Get请求:并通过该请求来进行网页的更新(实现原理仿照课件案例),同时我们简单试用了一下json的tag功能,写自闭了,随手加的

  • controller:user.go
    • Get:首先我们自定义一个结构体用于存储数据,之后当收到请求后,返回一个结构体转换的json数据c.Data["json"] = rejs,这里还可以进行是否是ajax的判断,但是作业要求没有就emmm当作一个debug用途把
package controllers

import (
	"fmt"

	beego "github.com/astaxie/beego/server/web"
)

type UserController struct {
	beego.Controller
}

type JSONStruct struct {
	ID      string `json:"id"`
	Content string `json:"content"`
}

func (c *UserController) Get() {
	fmt.Println("是否为ajax请求", c.IsAjax())
	var rejs JSONStruct
	rejs.Content = "hello"
	rejs.ID = "111"
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*") //允许跨域
	c.Data["json"] = rejs
	c.ServeJSON()
	return
}

  • 路由配置:router.go
    • 为json访问配置对应的url路径
beego.Router("/user", &controllers.UserController{})
  • 查验是否正确返回json数据:(这里使用接口测试工具,之后下面有详细的curl测试)
    在这里插入图片描述

之后为了实现要求的通过返回的json数据来进行网页数据的更新,我们要在另一个界面上搭建网页,并向该接口发送get请求

  • 我们这里使用初始页面来进行,首先更改控制器controller:
    • 控制器中只要设定tplname为我们的html界面即可(这里的网页界面由一个div和两个input、一个button组成)
package controllers

import (
	beego "github.com/astaxie/beego/server/web"
)

type MainController struct {
	beego.Controller
}

func (c *MainController) Get() {
	c.Data["Website"] = "beego.me"
	c.Data["Email"] = "astaxie@gmail.com"
	c.TplName = "index.html"
}

  • 网页文件为:
    • 在ajax中对对应的url及逆行发送请求,并在success的回调函数中,通过get到的数据对页面进行更新,即可实现要求功能,在这里实现我们js访问功能的查验
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>json_visit</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function(){
	$("button").click(function(){
		$.ajax({url:"http://localhost:8080/user",success:function(result){
            $("#div1").html(result);
            document.getElementById("field1").value=result.id;
            document.getElementById("field2").value=result.content;
		}});
	});
});
</script>
</head>
<body>
    Field1: <input type="text" id="field1" value=""><br>
    Field2: <input type="text" id="field2" value=" "><br><br>
<div id="div1"><h2>ajax get server message</h2></div>
<button>Got</button>

</body>
</html>
  • 路由设置:
	beego.Router("/", &controllers.MainController{})

运行结果:

  • 初始界面:
    在这里插入图片描述
  • 点击按钮后访问服务端数据:
    在这里插入图片描述
  • 同时因为我们加了一个输出,我们可以在命令行查看服务端的响应情况:可以看到是由服务端响应了ajax请求,更新了网页
    在这里插入图片描述

3.2 实现静态文件访问

实现静态文件的url访问方式,这里由于使用了beego的框架,所以实现起来很简单,只要在对应目录下设置静态路劲,即可在网页上进行访问

  • 由于是静态路径访问在beego中只需要设定对应的目录,所以不需要设置路由和控制器,只要在main.go文件中加入:
  • 第一个参数是对应的url,也就是访问路径,第二个参数为本地目录的相对地址
func main() {
	beego.SetStaticPath("/static", "static")
	beego.Run()
}
  • 结果验证:
    • 我们在static中加入几张照片,之后通过路径来访问它:

在这里插入图片描述

在这里插入图片描述

3.3 提交表单,并输出一个表格(使用模板

通过form的表单的自带的action 请求功能,在对应的controller中进行处理

  • 控制器controller实现:login.go
    • 首先在controller中定义表单数据对应的结构体(这里也随手试了下tag,不影响结果删了即可
    • 在get方法中设定对应的url的模板(因为要使用模板
    • 之后通过模板文件中的表单提交,来进行post方法的访问,用提交数据输出一个表格,这里用到了beego的动态模板的数据传输方法
    • 再beego中使用动态模板对属性赋值需要再模板中将参数设置为{{.Name}},之后再控制器中设置this.Data["Name"] = 参数,然后设置对应的模板即可this.Tplname
package controllers

import (
	beego "github.com/astaxie/beego/server/web"
)

type RegController struct {
	beego.Controller
}

type LoginStruct struct {
	NAme string `form:"Name"`
	Pwd  string
	Age  int
	Sex  string
}

func (this *RegController) Get() {
	this.TplName = "login.tpl"
}

func (this *RegController) Post() {
	var regmessage LoginStruct

	if error := this.ParseForm(&regmessage); error != nil { //传入user指针
		this.Ctx.WriteString("出错了!")
	} else {
		this.Data["Name"] = regmessage.NAme
		this.Data["Age"] = regmessage.Age
		this.Data["Password"] = regmessage.Pwd
		this.Data["Sex"] = regmessage.Sex
		this.TplName = "table.html"
	}
}
  • 登录模板
    • 模板中我们要关注的是action和method,这里我们设定action为我们的处理数据的url,method为我们的方法名Post
    • 之后我们的每个数据项要与控制器中的对应
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
<form action="/register" method="post">
    <table>
        <tbody>
        <tr>
            <td>用户名</td>
            <td>
                <input type="text" name ="Name" value="">
            </td>
        </tr>
        <tr>
            <td>密码</td>
            <td>
                <input type="password" name ="Pwd" value="">
            </td>
        </tr>
        <tr>
            <td>性别</td>
            <td>
                <input type="radio" name ="Sex" value="man"checked="checked">男
                <input type="radio" name ="Sex" value="woman">女
            </td>
        </tr>
        <tr>
            <td>年龄</td>
            <td>
                <input type="text" name ="Age" value="">
            </td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="确认">
            </td>
            <td>
                <input type="reset" value="重置">
            </td>
        </tr>
        </tbody>
    </table>
</form>
</body>
</html>
  • 表格模板:
    • 表格模板中要设定对应的动态模板来获得数据,对应控制器中的Data
<!DOCTYPE html>
<html>
<head> 
<meta charset="utf-8"> 
<title>Table</title> 
</head>
<body>

<h4>table:</h4>
<table border="1">
<tr>
  <td>Name</td>
  <td>{{.Name}}</td>
</tr>
<tr>
  <td>Password</td>
  <td>{{.Password}}</td>
</tr>
<tr>
    <td>Sex</td>
    <td>{{.Sex}}</td>
  </tr>

  <tr>
    <td>Age</td>
    <td>{{.Age}}</td>
  </tr>
</table>

</body>
</html>
  • 路由设置:将控制器绑定到对应的url
beego.Router("/register", &controllers.RegController{})
  • 实现结果:

  • 初始界面:
    在这里插入图片描述

  • 表单提交:

在这里插入图片描述

3.4 文件下载功能

这里使用beego的download功能实现

  • 控制器:loadfile.go
    • 我们设置get方法为下载一个我们的服务端的文件,第一个参数是本地的相对地址,第二个为在网页上显示的文件名
type FileOptDownloadController struct {
	beego.Controller
}

func (this *FileOptDownloadController) Get() {
	this.Ctx.Output.Download("static/img/img0.jpg", "lufei.jpg")
}
  • 路由配置:router
beego.Router("/downloadfile", &controllers.FileOptDownloadController{})
  • 运行结果:

在这里插入图片描述

3.5 文件上传功能

通过beego的getfile和savetofile实现,使用post请求来实现

  • 控制器:file.go
    • 设定对应的模板,在模板中执行对应的请求
    • 在post方法中实现文件的读取
type UploadController struct {
	beego.Controller
}

func (this *UploadController) Get() {

	this.TplName = "upload.tpl"
}

func (this *UploadController) Post() {
	file, head, err := this.GetFile("file")
	if err != nil {
		this.Ctx.WriteString("获取文件失败")
		return
	}
	defer file.Close()

	filename := head.Filename
	err = this.SaveToFile("file", "static/"+filename)
	if err != nil {
		this.Ctx.WriteString("上传失败1")
	} else {
		this.Ctx.WriteString("上传成功")
	}
}

  • 模板:比较简单,只要用一个表单来进行设定的action和method即可发送请求
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/uploadfile"  enctype="multipart/form-data"  method="post">
    <input type="file" name ="file">
    <input type="submit" value="上传">
</form>
</body>
</html>

  • 路由设定:
beego.Router("/uploadfile", &controllers.UploadController{})
  • 实现结果:

  • 初始界面:

在这里插入图片描述

  • 选择文件后:

在这里插入图片描述

  • 上传后

在这里插入图片描述

  • 在本地查看上传结果:
    可以看到成功上传到static目录下
    在这里插入图片描述

四、Curl测试

  • 首页测试
curl -v http://localhost:8080

这是一个get方法请求返回了对应的tpl界面

* Rebuilt URL to: http://localhost:8080/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Length: 724
< Content-Type: text/html; charset=utf-8
< Server: beegoServer:2.0.0-alpha
< Set-Cookie: beegosessionID=c256d6a926ffec9b2e8fcf23b29b24e4; Path=/; HttpOnly
< Date: Sun, 22 Nov 2020 13:32:48 GMT
< 







<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>json_visit</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function(){
        $("button").click(function(){
                $.ajax({url:"http://localhost:8080/user",success:function(result){
            $("#div1").html(result);
            document.getElementById("field1").value=result.id;
            document.getElementById("field2").value=result.content;
                }});
        });
});
</script>
</head>
<body>
    Field1: <input type="text" id="field1" value=""><br>
    Field2: <input type="text" id="field2" value=" "><br><br>
<div id="div1"><h2>ajax get server message</h2></div>
<button>Got</button>

</body>
* Connection #0 to host localhost left intact
  • json页user
curl -v http://localhost:8080/user

由上买你可知,这个页面的get请求返回的是json数据,所以本次curl也成功返回

*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /user HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Content-Length: 39
< Content-Type: application/json; charset=utf-8
< Server: beegoServer:2.0.0-alpha
< Set-Cookie: beegosessionID=25bf566d28cbb7a4042f6b9453e29636; Path=/; HttpOnly
< Date: Sun, 22 Nov 2020 13:33:51 GMT
< 
{
  "id": "111",
  "content": "hello"
* Connection #0 to host localhost left intact
  • login 页
curl -v http://localhost:8080/register

也是返回对应的tpl页面数据

*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /register HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Length: 1119
< Content-Type: text/html; charset=utf-8
< Server: beegoServer:2.0.0-alpha
< Set-Cookie: beegosessionID=ee35b3fa267c4835a0739b127b724f51; Path=/; HttpOnly
< Date: Sun, 22 Nov 2020 13:35:51 GMT
< 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
<form action="/register" method="post">
    <table>
        <tbody>
        <tr>
            <td>用户名</td>
            <td>
                <input type="text" name ="Name" value="">
            </td>
        </tr>
        <tr>
            <td>密码</td>
            <td>
                <input type="password" name ="Pwd" value="">
            </td>
        </tr>
        <tr>
            <td>性别</td>
            <td>
                <input type="radio" name ="Sex" value="man"checked="checked">男
                <input type="radio" name ="Sex" value="woman">女
            </td>
        </tr>
        <tr>
            <td>年龄</td>
            <td>
                <input type="text" name ="Age" value="">
            </td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="确认">
            </td>
            <td>
                <input type="reset" value="重置">
            </td>
        </tr>
        </tbody>
    </table>
</form>
</body>
</html>
* Connection #0 to host localhost left intact

五、 ab测试

结果重要参数解释:
Server Software: 测试服务器的Web服务器软件名字
Server Hostname: 请求的域名
Server Port: 测试的访问端口
Document Path: 请求URL的绝问文件路径
Document Length: 表示HTTP相应的正文的长度
Concurrency Level: 标识并发的用户数(-c属性来设置)
Time taken for tests: 执行完所有的请求所花费的时间
Complete requests: 表示测试的总请求数
Failed requests: 失败的请求
Total transferred: 表示所有请求的响应数据的总和,包含头信息和正文长度.
HTML transferred: 表示所有请求中响应数据的正文长度 (不包含头信息的长度)
Requests per second: 这个就是我们要的吞吐率,表示每秒处理的请求数
Time per request: 表示每个用户平均等待的时间. 等于 Time taken for tests / (Complete requests / Concurrency Level)
Time per request:(mean, across all concurrent requests) 服务器平均请求处理的时间. 正是吞详细地址的倒数,为:Time per request / Concurrency Level 每个请求花费了多少秒
Transfer rate: 这些请求在单位内,从服务器获取的数据长度. 等于: Total transferred / Time taken for tests
Percentage of the requests served within a certain time (ms): 这部分数据用于描述每个请求处理时间的分页情况,百分之五十不超过183毫秒,. 百分之九十不超过249毫秒,百分百不超过374毫秒.

  • test1:
ab -n 1000 -c 100 http://localhost:8080/
  • -n <请求数量> -c <并发请求数量>
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
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 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        beegoServer:2.0.0-alpha
Server Hostname:        localhost
Server Port:            8080

Document Path:          /
Document Length:        724 bytes

Concurrency Level:      100
Time taken for tests:   1.251 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      953000 bytes
HTML transferred:       724000 bytes
Requests per second:    799.68 [#/sec] (mean)
Time per request:       125.051 [ms] (mean)
Time per request:       1.251 [ms] (mean, across all concurrent requests)
Transfer rate:          744.23 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   1.7      0       8
Processing:     4  123  60.2    105     327
Waiting:        0  118  63.7    103     327
Total:          4  123  60.2    105     327

Percentage of the requests served within a certain time (ms)
  50%    105
  66%    146
  75%    159
  80%    168
  90%    209
  95%    220
  98%    291
  99%    310
 100%    327 (longest request)
  • test2
ab -n 10000 -c 1000 http://localhost:8080/
  • -n <请求数量> -c <并发请求数量>
  • 这次加大测试之后,并发1000发现连接崩掉了,发现只进行了1948次测试
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
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 1000 requests
apr_socket_recv: Connection reset by peer (104)
Total of 1948 requests completed
  • 本地的服务端返回信息为1s中太多的请求导致失败,并且之后再进行任何测试都会失败,(本地服务搞炸了?

  • 重启bee run 网页服务后回复正常

  • 以下是重启后的结果:

sunhaonan@sunhaonan-VirtualBox:~/gopath/src/cloudgo$ ab -n 1000 -c 100 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
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 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        beegoServer:2.0.0-alpha
Server Hostname:        localhost
Server Port:            8080

Document Path:          /
Document Length:        724 bytes

Concurrency Level:      100
Time taken for tests:   1.304 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      953000 bytes
HTML transferred:       724000 bytes
Requests per second:    766.81 [#/sec] (mean)
Time per request:       130.411 [ms] (mean)
Time per request:       1.304 [ms] (mean, across all concurrent requests)
Transfer rate:          713.64 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   2.5      0      12
Processing:     2  127  51.1    122     357
Waiting:        0  119  58.7    122     357
Total:          2  128  51.4    122     357

Percentage of the requests served within a certain time (ms)
  50%    122
  66%    143
  75%    155
  80%    162
  90%    194
  95%    220
  98%    244
  99%    279
 100%    357 (longest request)

源码分析和库学习

beego源码分析

七、个人总结

本次实验主要了解了使用go来搭建web服务,同时了解了beego等的go语言web服务框架,尝试进行了get,post等请求的操作,和文件的处理操作,主要花费时间的是框架的搭建和使用方法的学习,花费了较多时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值