0. http包使用
因为后面的项目基本要从tcp或者http开始,所以这里先介绍其机制
http.HandleFunc("/hello", helloHandler) #注册默认服务逻辑上的路由请求
http.ListenAndServe(":8080", nil) #监听指定端口,并使用默认服务
http.ListenAndServe(":8080", r) #监听指定端口,并使用指定服务,也就是r结构需要实现相应函数以适应该接口
一. geeweb
首先是总的框架架构,复用net/http包,也就是基于http实现,不从底层报文协议上开始,而是业务开发框架
模块名称 |
功能 |
main |
配置基础路由和服务、注册中间注册分组路由函数、启动对应端口服务 |
Engine |
服务实体,嵌套分组根节点,记录路由根节点,记录所有分组 |
RouterGroup |
分组实体、分组中间件、父分组、服务实体 |
Context |
请求和响应的实体,记录上下文、该次请求中间件、解析和生成报文 |
router |
管理路由树实体、用于注册路由函数、最终执行实体 |
主体运行框架首先是初始化服务,以及注册分组上的中间件、路由处理函数、接着监听端口
全局一个engine实例,若干group实例,前者管理监听路口和所有分组以及路由树根节点,后者用来注册中间件和路由函数
使用http.ListenAndServe(addr, engine)
监听端口,当请求到达,自动为请求创建新的http连接实体,
然后执行ServeHTTP(w http.ResponseWriter, req *http.Request)
,这里都是使用新的协程接管,服务只需面向新协程处理完整的http报文
结构体 Engine
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
Engine |
结构体 |
*RouterGroup, *router, []*RouterGroup, *template.Template, template.FuncMap |
- |
Web 服务的核心引擎结构体,处理路由和模板 |
New() |
构造函数 |
- |
*Engine |
构造 Engine 实例 |
Default() |
构造函数 |
- |
*Engine |
创建默认的 Engine ,并注册中间件 |
SetFuncMap() |
结构体函数 |
funcMap template.FuncMap |
- |
自定义模板渲染函数的映射 |
LoadHTMLGlob() |
结构体函数 |
pattern string |
- |
加载并解析指定的 HTML 模板文件 |
Run() |
结构体函数 |
addr string |
error |
启动 HTTP 服务器,并监听指定地址 |
ServeHTTP() |
结构体函数 |
w http.ResponseWriter, req *http.Request |
- |
实现 HTTP 请求的处理,应用中间件和路由 |
结构体 RouterGroup
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
RouterGroup |
结构体 |
prefix string, middlewares []HandlerFunc, parent *RouterGroup, engine *Engine |
- |
路由组,支持路由分组和中间件功能 |
Group() |
结构体函数 |
prefix string |
*RouterGroup |
创建新的路由组,所有组共享同一 Engine 实例 |
Use() |
结构体函数 |
middlewares ...HandlerFunc |
- |
向当前路由组添加中间件 |
addRoute() |
结构体函数 |
method, comp string, handler HandlerFunc |
- |
为当前路由组添加新的路由规则 |
GET() |
结构体函数 |
pattern string, handler HandlerFunc |
- |
添加 GET 请求的路由处理 |
POST() |
结构体函数 |
pattern string, handler HandlerFunc |
- |
添加 POST 请求的路由处理 |
createStaticHandler() |
结构体函数 |
relativePath string, fs http.FileSystem |
HandlerFunc |
创建处理静态文件请求的处理函数 |
Static() |
结构体函数 |
relativePath, root string |
- |
为静态文件创建路由 |
这里将http的请求报文和响应报文封装context实体,也就是一次请求对应一个context实体,context记录这个报文需要使用的中间件(因为是嵌套分组所以要根据前缀遍历一遍获取所有中间件)
结构体 Context
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
Context |
结构体 |
Writer http.ResponseWriter, Req *http.Request, Path, Method string, Params map[string]string, StatusCode int, handlers []HandlerFunc, index int, engine *Engine |
- |
保存 HTTP 请求上下文,包含请求信息、响应信息以及处理流程 |
newContext() |
构造函数 |
w http.ResponseWriter, req *http.Request |
*Context |
创建并初始化 Context 实例 |
Next() |
结构体函数 |
- |
- |
调用下一个中间件或处理器函数 |
Fail() |
结构体函数 |
code int, err string |
- |
设置失败状态码并返回错误信息的 JSON 响应 |
Param() |
结构体函数 |
key string |
string |
获取 URL 中的参数值 |
PostForm() |
结构体函数 |
key string |
string |
获取 POST 表单中的参数 |
Query() |
结构体函数 |
key string |
string |
获取 URL 查询字符串中的参数 |
Status() |
结构体函数 |
code int |
- |
设置 HTTP 响应状态码 |
SetHeader() |
结构体函数 |
key, value string |
- |
设置 HTTP 响应头 |
String() |
结构体函数 |
code int, format string, values ...interface{} |
- |
返回文本响应 |
JSON() |
结构体函数 |
code int, obj interface{} |
- |
返回 JSON 格式的响应 |
Data() |
结构体函数 |
code int, data []byte |
- |
返回原始字节数据 |
HTML() |
结构体函数 |
code int, name string, data interface{} |
- |
返回 HTML 响应,使用模板渲染 |
router管理路由树,路由函数的注册以及最终的链式执行
结构体 router
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
router |
结构体 |
roots map[string]*node, handlers map[string]HandlerFunc |
- |
路由结构,存储不同 HTTP 方法的路由树和处理函数 |
newRouter() |
构造函数 |
- |
*router |
构造 router 实例 |
parsePattern() |
函数 |
pattern string |
[]string |
将路由路径分割为部分,解析路径中的参数和通配符 |
addRoute() |
结构体函数 |
method, pattern string, handler HandlerFunc |
- |
向路由树中添加新的路由及其处理函数 |
getRoute() |
结构体函数 |
method, path string |
*node, map[string]string |
根据请求的方法和路径,匹配对应的路由节点和参数 |
getRoutes() |
结构体函数 |
method string |
[]*node |
获取某一 HTTP 方法下的所有路由节点 |
handle() |
结构体函数 |
c *Context |
- |
处理 HTTP 请求,根据路由匹配并执行相应处理函数 |
router采用的前缀树结构
结构体 node
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
node |
结构体 |
pattern string, part string, children []*node, isWild bool |
- |
路由树节点,用于表示路由规则中的某一部分 |
String() |
结构体函数 |
- |
string |
返回当前节点的字符串表示形式 |
insert() |
结构体函数 |
pattern string, parts []string, height int |
- |
向路由树中插入一个新节点 |
search() |
结构体函数 |
parts []string, height int |
*node |
在路由树中搜索与给定路径匹配的节点 |
travel() |
结构体函数 |
list *([]*node) |
- |
遍历当前节点及其子节点,并将匹配的节点添加到列表中 |
matchChild() |
结构体函数 |
part string |
*node |
查找匹配当前部分的子节点 |
matchChildren() |
结构体函数 |
part string |
[]*node |
查找匹配当前部分的所有子节点 |
二. gee-cache
首先还是从主函数看起,启动三个分布式缓存服务进程(各自会在进程内新建一个group管理缓存),以及一个对外的http服务测试线程
当http请求到达,也就是查询一个key值,调用对应group的查询值函数
模块名称 |
功能 |
main |
初始化监听、初始化三个缓存实体和三个分布式缓存监听服务 |
Group |
单个缓存实体,用于管理LRU缓存结构和注册默认硬盘查询函数 |
Map |
一致性哈希,用于注册获取远程服务 |
HTTPPool |
缓存服务监听和请求实体,服务远程请求和申请远程请求 |
cache |
缓存结构实体 |
group查询值的时候,首先查找本地LRU缓存,如果有直接返回
如果没有,先根据key找一个远程服务节点
结构体 Group
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
Group |
结构体 |
name string, getter Getter, mainCache cache, peers PeerPicker, loader *singleflight.Group |
- |
缓存命名空间及其关联数据,负责管理本地缓存和远程节点交互 |
NewGroup() |
构造函数 |
name string, cacheBytes int64, getter Getter |
*Group |
创建一个新的 Group 实例,用于管理缓存数据 |
GetGroup() |
函数 |
name string |
*Group |
根据名称返回已创建的 Group 实例,如果没有则返回 nil |
Get() |
结构体函数 |
key string |
ByteView, error |
根据键值从缓存中获取数据,如果缓存不存在则加载数据 |
RegisterPeers() |
结构体函数 |
peers PeerPicker |
- |
注册远程节点选择器,用于分布式缓存的节点选择 |
load() |
结构体函数 |
key string |
ByteView, error |
加载指定键的缓存数据,支持远程节点获取或本地加载 |
populateCache() |
结构体函数 |
key string, value ByteView |
- |
将加载的值添加到本地缓存中 |
getLocally() |
结构体函数 |
key string |
ByteView, error |
从本地获取数据,通过 getter 加载并缓存 |
getFromPeer() |
结构体函数 |
peer PeerGetter, key string |
ByteView, error |
从远程节点获取数据,并返回对应的缓存值 |
这里是使用一致性哈希获取对应的远程服务地址,同时对于大量相同的key的调用,会使用map映射一个call进行阻塞,其它相同key请求等待第一个call完毕
执行一个集成的http远程请求,获取得到值
结构体 Map
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
Map |
结构体 |
hash Hash, replicas int, keys []int, hashMap map[int]string |
- |
用于一致性哈希存储的结构体,管理哈希环上的所有键 |
New() |
构造函数 |
replicas int, fn Hash |
*Map |
创建一个 Map 实例,用于一致性哈希 |
Add() |
结构体函数 |
keys ...string |
- |
向哈希环中添加节点,并生成副本 |
Get() |
结构体函数 |
key string |
string |
根据提供的键值查找哈希环上最接近的节点 |
使用远程请求key的方法,会自动根据注册的远程服务地址以及对应的方法获取远程地址,同时调用http远程请求直到获取返回值
结构体 HTTPPool
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
HTTPPool |
结构体 |
self string, basePath string, mu sync.Mutex, peers *consistenthash.Map, httpGetters map[string]*httpGetter |
- |
管理 HTTP 节点的连接池,用于与分布式缓存中的其他节点交互 |
NewHTTPPool() |
构造函数 |
self string |
*HTTPPool |
初始化一个新的 HTTPPool ,用于管理节点间的通信 |
Log() |
结构体函数 |
format string, v ...interface{} |
- |
打印日志信息,包含节点名 |
ServeHTTP() |
结构体函数 |
w http.ResponseWriter, r *http.Request |
- |
处理 HTTP 请求,并根据路径获取缓存数据 |
Set() |
结构体函数 |
peers ...string |
- |
更新节点池中的 peers 列表,并为每个节点初始化 httpGetter |
PickPeer() |
结构体函数 |
key string |
PeerGetter, bool |
根据键值选择适合的节点进行请求 |
结构体 httpGetter
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
httpGetter |
结构体 |
baseURL string |
- |
HTTP 客户端,用于从远程节点获取缓存数据 |
Get() |
结构体函数 |
in *pb.Request, out *pb.Response |
error |
从远程节点获取缓存数据,并将其解码为响应 |
结构体 Cache
及其关联函数
结构体/函数名 |
类型 |
参数 |
返回值 |
功能描述 |
Cache |
结构体 |
maxBytes int64, nbytes int64, ll *list.List, cache map[string]*list.Element, OnEvicted func(key string, value Value) |
- |
LRU 缓存的主要结构体,管理缓存项、容量、元素淘汰等功能 |
New() |
构造函数 |
maxBytes int64, onEvicted func(string, Value) |
*Cache |
创建一个 Cache 实例,初始化缓存参数和淘汰函数 |
Add() |
结构体函数 |
key string, value Value |
- |
添加或更新缓存项,并根据缓存大小判断是否淘汰最旧的元素 |
Get() |
结构体函数 |
key string |
Value, bool |
根据键值查找缓存项,如果存在则返回,并将该项移动到最前面 |
RemoveOldest() |
结构体函数 |
- |
- |
移除缓存中最旧的元素(LRU 策略),并调用淘汰函数 |
Len() |
结构体函数 |
- |
int |
返回缓存中当前存储的条目数量 |
三. gee-rpc
从main视角,首先初始化服务注册中心
注册中心监听服务请求端口,基于http进行响应,对请求方GET返回服务实例,对服务端POST的心跳机制进行更新