复现一个分布式对象存储 01 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的第1天
介绍
本系列是我对书籍《分布式对象存储——原理、架构及Go语言实现》的复现和思考以及踩坑经验,动机是在第四届青训营大数据专场选择的作业三《简易分布式存储系统实现》,打算提前看一些存储相关的书,正好这本书与作业三比较相关,所以看一下先练练手
环境准备
系统:ubuntu20.04,Go版本:go1.18,代码编辑器:Goland
目标
实现一个简单的单机版对象存储,通过REST接口上传和下载一个对象。
架构和接口
单机版对象存储架构如下图所示
REST接口实现两个put、get方法,put将对象的名字和数据上传,get从服务器下载一个对象。
实现
文件结构
├── 第一章笔记.md
├── objects
│ ├── get.go
│ ├── handler.go
│ └── put.go
└── server.go
首先看一下server.go文件
package main
import (
"book-object-storage/01/objects"
"log"
"net/http"
"os"
)
func main() {
http.HandleFunc("/objects/", objects.Handler)
// LISTEN_ADDRESS是我们自己设置的ip地址,这里为本地ip地址127.0.0.1
log.Fatal(http.ListenAndServe(os.Getenv("LISTEN_ADDRESS"), nil))
}
main函数大概意思就是我们启动一个http服务,处理函数为我们自己定义的objects.Handler
接着看一下objects包里的三个文件
handler.go
package objects
import "net/http"
func Handler(w http.ResponseWriter, r *http.Request) {
m := r.Method
if m == http.MethodPut {
put(w, r)
return
}
if m == http.MethodGet {
get(w, r)
return
}
w.WriteHeader(http.StatusMethodNotAllowed)
}
这个文件也很简单,就是根据请求的Method来判断是采用put还是get方法
put.go
package objects
import (
"io"
"log"
"net/http"
"os"
"strings"
)
func put(w http.ResponseWriter, r *http.Request) {
f, err := os.Create(os.Getenv("STORAGE_ROOT") + "/objects/" + strings.Split(r.URL.EscapedPath(), "/")[2])
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
defer f.Close()
io.Copy(f, r.Body)
}
strings.Split(r.URL.EscapedPath(), "/")[2] 从请求中拿到我们要上传的文件的名字,通过os.Creat创建一个文件f,将请求的r.Body拷贝至f
get.go
package objects
import (
"io"
"log"
"net/http"
"os"
"strings"
)
func get(w http.ResponseWriter, r *http.Request) {
f, err := os.Open(os.Getenv("STORAGE_ROOT") + "/objects/" + strings.Split(r.URL.EscapedPath(), "/")[2])
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusNotFound)
return
}
defer f.Close()
io.Copy(w, f)
}
STORAGE_ROOT是我们测试时候自己设置的,strings.Split(r.URL.EscapedPath(), "/")[2] 是从请求中拿到我们要下载的文件的名字,然后和前面的文件前缀拼接成一个在磁盘可以找到的文件地址。然后通过io.Copy方法将读到的文件f复制到返回的w中
测试
提前创建好目录
mkdir /tmp/objects/
在项目文件server.go的目录下
在命令行输入下面指令 设置LISTEN_ADDRESS和 STORAGE_ROOT 以及运行server.go
LISTEN_ADDRESS=127.0.0.1:12345 STORAGE_ROOT=/tmp go run server.go
使用curl命令作为客户端来访问服务器 试图 Get一个test的对象
由于是本地测试 将ip地址改成本地
curl -v 127.0.0.1:12345/objects/test
PUT一个test对象
curl -v 127.0.0.1:12345/objects/test -XPUT -d"this is a test objects"
创建好tmp下的objects目录后,
再启动一个终端
此时由于我们还没上传文件,所以get不到文件,出现404 NOT Found,我们接下来通过curl上传一个test文件,内容为this is a test objects
上传成功后 我们继续get这个test,发现成功
我的代码地址如下
参考
新手写东西,感谢观看