从0到1手写分布式对象存储系统-01单机版存储模型

背景

笔者将以 go 语言去实现一个分布式对象存储系统,将最开始的单机版模型慢慢扩展为分布式模型。

参考资料

《分布式对象存储——原理、架构及Go语言实现》,胡世杰 著

架构

在服务器端,我们提供一个 REST 接口,PUT 请求时在服务器本地磁盘创建存储对象,GET 请求时在服务器本地磁盘获取存储对象,服务与数据都在同一台服务器上,没有解耦,仅实现了最简单的存储功能。

业务处理函数

由 PUT 方法创建或者替换一个文件对象,由 GET 方法获取一个文件对象,因此定义一个处理业务的函数用于绑定 URL 。

package objects

import (
	"io"
	"log"
	"net/http"
	"os"
	"strings"
)

/*
PUT/GET 业务处理函数
*/
func Handler(w http.ResponseWriter, r *http.Request) {
	m := r.Method

	// PUT 方法时,创建或者替换资源
	if m == http.MethodPut {
		log.Println("PUT 方法")
		put(w, r)
		return
	}

	// GET 方法时,获取资源
	if m == http.MethodGet {
		log.Println("GET 方法")
		get(w, r)
		return
	}

	// 其他方式时,返回状态码,方法不允许
	w.WriteHeader(http.StatusMethodNotAllowed)
}

func put(w http.ResponseWriter, r *http.Request) {

	// 处理文件路径,将文件保存在 D:/uploadFile 目录下,文件名为客户端 PUT 请求时的名字,文件名应为转义后的名字
	// 文件路径可以使用 os.Getenv(var) 通过环境变量来指定会更加灵活
	log.Println(r.URL.EscapedPath())
	fileName := "D:/uploadFiles/" + strings.Split(r.URL.EscapedPath(), "/")[2]
	// 创建文件
	f, e := os.Create(fileName)
	if e != nil {
		log.Println(e)
		// 返回服务器错误状态码
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	// 将客户端 PUT 请求的文件数据保存到服务端创建的文件 f 中
	io.Copy(f, r.Body)
	// 关闭文件
	defer f.Close()
}

func get(w http.ResponseWriter, r *http.Request) {
	// 处理文件路径,从 D:/uploadFile 目录下获取文件,文件名为客户端 GET 请求时的名字,文件名应为转义后的名字
	// 文件路径可以使用 os.Getenv(var) 通过环境变量来指定会更加灵活
	log.Println(r.URL.EscapedPath())
	fileName := "D:/uploadFiles/" + strings.Split(r.URL.EscapedPath(), "/")[2]
	// 创建文件
	f, e := os.Open(fileName)
	if e != nil {
		log.Println(e)
		// 返回文件未找到状态码
		w.WriteHeader(http.StatusNotFound)
		return
	}
	// 将服务端的文件 f 复制到响应体 w 中
	io.Copy(w, f)
	// 关闭文件
	defer f.Close()
}

/*
注意:
f 本身类型是 *os.File,它是一个指向 os.File 结构体的指针,而 os.File 结构体同时实现了 io.Writer 和 io.Reader 两个接口,
因此它既是一个 io.Writer 又是 一个 io.Reader,可以在 io.Copy 中作为不同的参数使用。
*/

main 入口

将业务路由 URL 与业务处理函数绑定,启动服务。

package main

import (
	"demo/objects"
	"net/http"
)

func main() {
	http.HandleFunc("/handleObjs/", objects.Handler)
	// 使用 os.Getenv(var) 更加灵活
	http.ListenAndServe(":8080", nil)
}

测试

客户端 PUT 请求

文件创建成功。

客户端 GET 请求

获取文件成功。

使用 POST 方法

方法错误。

获取不存在的文件

文件未找到。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

余衫马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值