cache教程 3.HTTP服务器

上一节我们实现了单机版的缓存服务,但是我们的目标是分布式缓存。那么,我们就需要把缓存服务部署到多态机器节点上,对外提供访问接口。客户端就可以通过这些接口去实现缓存的增删改查。

分布式缓存需要实现节点间通信,而通信方法常见的有HTTP和RPC。建立基于 HTTP 的通信机制是比较常见和简单的做法。

所以,我们基于 Go 语言标准库 http 搭建 HTTP Server。

net/http标准库

简单实现一个http服务端例子。

type server int

func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello World!"))
}

func main() {
	var s server
	http.ListenAndServe("localhost:9999", &s)
}

//下面的是http源码
type Handler interface {
    ServeHTTP(w ResponseWriter, r *Request)
}

在该代码中,创建任意类型 server,并实现 ServeHTTP 方法。

http.ListenAndServe 接收 2 个参数,第一个参数是服务启动的地址,第二个参数是 Handler,实现了 ServeHTTP 方法的对象都可以作为 HTTP 的 Handler。

Cache HTTP 服务端

我们需要创建一个结构体去实现Handler接口,而该结构体应该是有些属性变量来支撑我们做一些事情的。

  • HTTPPool 有 2 个参数,一个是 addr,用来记录自己的地址,包括主机名/IP 和端口。
  • 另一个是 basePath,作为节点间通讯地址的前缀,默认是 /geecache/。比如http://example.com/geecache/开头的请求,就用于节点间的访问。因为一个主机上还可能承载其他的服务,加一段 Path 是一个好习惯。比如,大部分网站的 API 接口,一般以 /api 作为前缀。

HTTPPool实现了ServeHTTP方法,即是Handler接口。 

const defaultBasePath = "/geecache/"

type HTTPPool struct {
	addr     string    //本地IP端口, 比如:"localhost:10000"
	basePath string
}

func (pool *HTTPPool) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//处理请求和响应,后面会实现的
}

//创建HTTPPool方法
func NewHTTPPool(addr string, basePath string) *HTTPPool {
	return &HTTPPool{
		addr:     addr,
		basePath: basePath,
	}
}

接下来实现最为核心的ServeHTTP方法。

func (pool *HTTPPool) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !strings.HasPrefix(r.URL.Path, pool.basePath) {
		panic("HTTPPool serving unexpected path: " + r.URL.Path)
	}

	parts := strings.SplitN(r.URL.Path[len(pool.basePath):], "/", 2)

	if len(parts) != 2 {
		http.Error(w, "bad request", http.StatusBadRequest)
		return
	}

	groupName := parts[0]

	group := GetGroup(groupName)
	if group == nil {
		http.Error(w, "no such group: "+groupName, http.StatusNotFound)
		return
	}

	view, err := group.Get(parts[1])
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/octet-stream")
	w.Write(view.ByteSlice())
}

该方法是先判断前缀是否相等,若不相等,返回错误,之后再判断分组名字,再判断key。

url.Path的格式是/<basepath>/<groupname>/<key>。举个例子,r.URL.Path是/geecache/scores/tom,那r.URL.Path[len(pool.basePath):]即是scores/tom,接着就是使用strings.SplitN函数进行分割来获取分组名字和key。

测试

// 缓存中没有的话,就从该db中查找
var db = map[string]string{
	"tom":  "100",
	"jack": "200",
	"sam":  "444",
}

func main() {
	//传函数入参
	cache.NewGroup("scores", 2<<10, cache.GetterFunc(funcCbGet))
	//传结构体入参,也可以
	// cbGet := &search{}
	// cache.NewGroup("scores", 2<<10, cbGet)

	addr := "localhost:10000"
	peers := cache.NewHTTPPool(addr, cache.DefaultBasePath)
	log.Fatal(http.ListenAndServe(addr, peers))
}

// 函数的
func funcCbGet(key string) ([]byte, error) {
	fmt.Println("callback search key: ", key)
	if v, ok := db[key]; ok {

		return []byte(v), nil
	}
	return nil, fmt.Errorf("%s not exit", key)
}

// 结构体,实现了Getter接口的Get方法,
type search struct {
}

func (s *search) Get(key string) ([]byte, error) {
	fmt.Println("struct callback search key: ", key)
	if v, ok := db[key]; ok {
		return []byte(v), nil
	}
	return nil, fmt.Errorf("%s not exit", key)
}

执行 go run main.go,查看效果

完整代码:https://github.com/liwook/Go-projects/tree/main/go-cache/3-httpServer

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/232398.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

m_map导入本地地形数据

m_map绘制地形图时&#xff0c;虽然自带有1的地形图以及从NOAA下载的1分的地形图&#xff08;详见&#xff1a;Matlab下地形图绘图包m_map安装与使用&#xff09;&#xff0c;但有时需要对地形图分辨率的要求更高&#xff0c;便无法满足。 此时&#xff0c;需要导入本地地形数…

LeetCode题:11. 盛最多水的容器

目录 一、题目要求 二、解题思路 三、代码 一、题目要求 11. 盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多…

《师兄啊师兄》第二季来了!它凭什么成为修仙流里第一档?

沉寂大半年&#xff0c;修仙喜剧动画《师兄啊师兄》第二季终于“千呼万唤始出来”&#xff0c;即将在12月14日上线。作为优酷动漫本年度的当家之作&#xff0c;这部可谓是热度口碑双丰收&#xff0c;截至第一季收官&#xff0c;相关话题在短视频平台的累计播放量更是高达43亿&a…

软件设计师——法律法规(二)

&#x1f4d1;前言 本文主要是【法律法规】——软件设计师——法律法规的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304…

延时消息+递归导致重复消费爆炸问题

背景 公司所用消息队列为RoucketMQ&#xff0c;版本为4.x。最近公司有业务需要&#xff0c;将某个处理延迟到第二天的白天再进行。由于4.x版本队列&#xff0c;默认延时时间是按等级来延时的&#xff0c;默认有18个等级&#xff0c;如下图&#xff1a; 默认的延时等级&#xff…

eve-ng山石网科HillStone镜像部署

HillStone 部署 author&#xff1a;leadlife data&#xff1a;2023/12/4 mains&#xff1a;EVE-ng HillStone 镜像部署 - use hillstone-sg6000 default&#xff1a;hillstone/hillstone 传输 scp hillstone-sg6000.zip root192.168.3.130:/opt/unetlab/addons/qemu/部署 cd …

12.4每日一题(备战蓝桥杯顺序结构程序设计)

12.4每日一题&#xff08;备战蓝桥杯顺序结构程序设计&#xff09; 题目1000: 【入门】AB Problem题目描述输入输出样例输入样例输出来源/分类 题解 1000: 【入门】AB Problem题目 2124: 计算(ab)c的值题目描述输入输出样例输入样例输出来源/分类 题解 2124: 计算(ab)c的值题目…

C语言-字符串操作函数-附加使用方式

文章目录 前言字符串复制-strcpy字符串复制&#xff08;按照位数&#xff09;-strncpy字符串比较-strcmp字符串比较(按照位数)-strncmp不区分大小写的字符串比较-strcasecmp不区分大小写的比较(前n位)-strncasecmp字符串按照格式写入-sprintf字符串按照格式和个数写入-snprintf…

使用贝叶斯网络检测因果关系,提升模型效果更科学(附Python代码)

虽然机器学习技术可以实现良好的性能&#xff0c;但提取与目标变量的因果关系并不直观。换句话说&#xff0c;就是&#xff1a;哪些变量对目标变量有直接的因果影响&#xff1f; 机器学习的一个分支是贝叶斯概率图模型(Bayesian probabilistic graphical models)&#xff0c;也…

SpringCloud网关介绍

一、Gateway简介 1、官网 上一代zuul 1.X&#xff1a;https://github.com/Netflix/zuul/wiki 当前gateway&#xff1a;https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/ 2、是什么 SpringCloud Gateway是SpringCloud的一个全…

2023 CCF中国软件大会(CCF ChinaSoft)“软件工程教育”论坛 成功召开

2023年12月1日&#xff0c;2023年度CCF中国软件大会“软件工程教育”论坛成功召开。 ✦ 自去年来大模型技术的出现以及在各个领域的应用&#xff0c;对相关的学科和行业产生了深刻的影响。软件工程首当其冲&#xff0c;以ChatGpt和CopilotX等为代表的智能化开发工具可以帮助软…

Spring Boot 3 集成 Druid 连接池详解

在现代的Java应用中&#xff0c;使用一个高效可靠的数据源是至关重要的。Druid连接池作为一款强大的数据库连接池&#xff0c;提供了丰富的监控和管理功能&#xff0c;成为很多Java项目的首选。本文将详细介绍如何在Spring Boot 3项目中配置数据源&#xff0c;集成Druid连接池&…

我对迁移学习的一点理解(系列2)

文章目录 我对迁移学习的一点理解 我对迁移学习的一点理解 源域和目标域是相对的概念&#xff0c;指的是在迁移学习任务中涉及到的两个不同的数据集或领域。 源域&#xff08;Source Domain&#xff09;通常指的是已经进行过训练和学习的数据集&#xff0c;它被用来提取特征、…

2023-12-09 LeetCode每日一题(下一个更大的数值平衡数)

2023-12-09每日一题 一、题目编号 2048. 下一个更大的数值平衡数二、题目链接 点击跳转到题目位置 三、题目描述 如果整数 x 满足&#xff1a;对于每个数位 d &#xff0c;这个数位 恰好 在 x 中出现 d 次。那么整数 x 就是一个 数值平衡数 。 给你一个整数 n &#xff0…

Temu卖家如何获取流量?Temu新手卖家流量来源哪里?——站斧浏览器

流量对于每个平台来说都是很重要的&#xff0c;那么Temu卖家如何获取流量&#xff1f;流量来源哪里&#xff1f; Temu卖家如何获取流量&#xff1f; 1、优化产品标题和描述&#xff1a;在Temu平台上&#xff0c;买家通常通过搜索关键词来寻找他们感兴趣的产品。因此&#xff…

Axios 拦截器实战教程:简单易懂

Axios 提供了一种称为 “拦截器&#xff08;interceptors&#xff09;” 的功能&#xff0c;使我们能够在请求或响应被发送或处理之前对它们进行全局处理。拦截器为我们提供了一种简洁而强大的方式来转换请求和响应、进行错误处理、添加认证信息等操作。在本文中&#xff0c;我…

P10 Linux进程编程 fork创建子进程

目录 前言 01 fork()创建子进程 示例 1使用 fork()创建子进程。 02 fork创建新进程时发生了什么事&#xff1f; 2.1 父、子进程中对应的文件描述符指向了相同的文件表 前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《Linux C应用编程&#xf…

[Linux] yum安装分布式LNMP架构

1. 在一台主机安装nginx&#xff08;192.168.136.120&#xff09; 1.1 搭建nginx相关的yum源 cd /yum.repos.d mkdir bak mv *.repo bak vim /etc/yum.repos.d/nginx.repo [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/centos/7/$basearch/ gpgche…

题解:CF1902A. Binary Imbalance

题解&#xff1a;CF1902A. Binary Imbalance 先给个题目链接。 题目翻译&#xff08;由“CodeForces Better&#xff01;”和“DeepL 翻译”提供&#xff09;&#xff1a; 我们知道&#xff0c;如果初始字符串中“0”的个数就大于“1”的个数&#xff0c;答案肯定是YES&…

【二分答案法】Leetcode相关题目解析

题目&#xff1a;162. 寻找峰值 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 题目分析&#xff1a; &#xff08;1&#xff09;据题知&#xff0c;索引-1、索引n&#xff08;n为数组长度&#xff09;处的元素都默认为无穷小&#xff0c;我们可以在一开始特判…
最新文章