服务计算 第十一周
开发 web 服务程序 信息查询小程序
1 主要内容
在老师原有的博客基础上,添加了新的功能,做成了一个信息查询系统,由于时间比较紧,所以比较粗糙,但是大致框架已经构建好了。
这里是github链接。
2 程序介绍
2.1 功能介绍
2.1.1 注册信息
介绍:当您需要在网上注册自己的信息,只需要登陆网站输入相关信息即可。
需要指令:regist
输入格式:curl -v http://localhost:9090/regist:[name]:[email]:[phone]
例如:curl -v http://localhost:9090/regist:wyj:180@163.com:122
如果成功,会有如下显示:
{
"RESULT": "Success! Have regist!"
}
否则即为失败,即您已经注册过。
注:如哦您只想分享一部分信息,只要在不想分享的部分以empty替代即可,例如,若您不想分享你的电话,只需输入:
curl -v http://localhost:9090/regist:wyj:180@163.com:empty
2.1.2 更新信息
介绍:当您需要在网上更新自己的信息,只需要登陆网站输入相关信息即可。
需要指令:update
输入格式:curl -v http://localhost:9090/update:[name]:[email]:[phone]
例如:curl -v http://localhost:9090/check:wyj:1:1curl -v http://localhost:9090/update:wyj:122@1.com:999
如果成功,会有如下显示:
{
"RESULT": "Update Success!"
}
否则即为失败,即您尚未注册。
注:如哦您只想更新一部分信息,只要在不想分享的部分以原有信息替代即可。
2.1.3 查询信息
介绍:当您需要在网上查询信息,只需要登陆网站输入相关信息即可。
需要指令:check
输入格式:curl -v http://localhost:9090/check:[name]:[0]:[0]
例如:curl -v http://localhost:9090/check:wyj:0:0
如果成功,会有如下显示:
{
"RESULT": "Name: wyj Email: 1122@1.com Phone: 999"
}
否则即为失败,即该用户尚未注册,请您耐心等待!
2.2 实现原理
服务器的建立,客户端的请求思路及代码都非常清晰了,也没有什么好扩展的了。因此,我在此基础上增加了一些参数,并在服务器端建立了本地服务器,实现了一个简单的信息查询系统。
C-S之间原理就不讲了,老师博客已经讲得很清楚了,讲一下做了那些改动。
2.2.1 通过分割获得更多的指令参数
在之前的输入解析的部分,是这样的:
mx.HandleFunc("/hello/{id}", testHandler(formatter)).Methods("GET")
而实际上,我们至少需要四个参数,因此,我们使用
:
分割,得到四个不同的段,如下:
mx.HandleFunc("/{command}:{name}:{email}:{phone}", testHandler(formatter)).Methods("GET")
并解析:
command := vars["command"]
name := vars["name"]
email := vars["email"]
phone := vars["phone"]
2.2.2 在本地处理所有的信息
当有了参数之后,很自然的事情就是如何根据这些参数得到信息,为了达到
数据分离
,将数据库处理部分(信息)与服务器端分离为两个文件。在服务器端,通过调用函数
Manager(command string, name string, email string, phone string) string
来传递参数,并获得反馈信息。
而在数据处理模块,共有3个功能。
实现功能的部分由于很小,因此集成在了Manager
中,(当然,后面功能多了肯定是要单独拿出来的):
/*Manager 处理指令
regist 注册,需要信息:名字 Email 电话
chcek 查询,需要信息:查询名字
update 更新数据,需要信息:名字 Email 电话
接收参数:指令 名字 email 电话
返回参数:
regist 注册成功/失败
check 查询结果
update 更新成功/失败
*/
func Manager(command string, name string, email string, phone string) string {
users := READUSERS()
switch command {
case "regist" : {
//遍历查询,没有找到才可以注册
for _, user := range users {
if user.Name == name {
return "This name has been regist!"
}
}
newUser := User{Name: name, Email: email, Phone: phone}
users = append(users, newUser)
WRITEUSER(users)
return "Success! Have regist!"
}
case "check" : {
//遍历查询,找到名字就返回结果
for _, user := range users {
if user.Name == name {
return "Name: " + user.Name + " Email: " + user.Email + " Phone: " + user.Phone
}
}
return "Not regist!"
}
case "update" : {
//遍历查询,找到名字就更新信息
for i, user := range users {
if user.Name == name {
users[i].Email = email
users[i].Phone = phone
WRITEUSER(users)
return "Update Success!"
}
return "Wrong Name!"
}
return "Not regist!"
}
default : return " "
}
}
2.2.3 每次操作读写
每次处理时,先读取所有的数据。每次操作完了,如果数据更改,则调用函数写回文件。
实现实际上非常简单,就是在调用Manager
时读入,只在注册成功
及更新信息成功
之后写回。
文件读写使用的是io/ioutil
以及json
/*READUSERS 读取用户*/
func READUSERS() (user []User) {
_, err := os.Getwd()
checkerr(err)
b, err := ioutil.ReadFile("Database/Users.txt")
checkerr(err)
//json转变为对象
var users []User
json.Unmarshal(b, &users)
return users
}
/*WRITEUSER 写回用户*/
func WRITEUSER(users []User) {
_, err := os.Getwd()
checkerr(err)
data, err := json.Marshal(users)
checkerr(err)
b := []byte(data)
err = ioutil.WriteFile("Database/Users.txt", b, 0777)
checkerr(err)
}
3 测试
先登陆系统,在
cloudgo
文件夹下运行。
go run main.go -p9090
3.1 注册
客户端:
服务器端:
3.2 更新信息
客户端:
服务器端:
3.3 查询
此时查询到新的信息
客户端:
服务器端:
4 压力测试
安装工具并检测。此处使用查询指令来检测。
yum -y install httpd-tools
ab -n 1000 -c 100 http://localhost:9090/check:wyj:0:0
结果显示:
分析结果,完成一半的时候只用了52ms,而全部完成则用了131ms,说明中间有很长的处理时间。观察发现,还是有很长的等待时间。