golang基于trie树实现的高性能HTTP路由插件库goblin的使用
Golang基于Trie树实现的高性能HTTP路由插件库goblin的使用
goblin是一个基于Trie树实现的Golang HTTP路由器,具有高性能和轻量级的特点。
特性
- 支持Go 1.16及以上版本
- 基于Trie树的简单数据结构
- 轻量级
- 代码行数:2428
- 包大小:140K
- 除了标准包外没有其他依赖
- 兼容net/http
- 比net/http的ServeMux更高级
- 基于方法的路由
- 命名参数路由
- 基于正则表达式的路由
- 中间件支持
- 可定制的错误处理程序
- 默认OPTIONS处理程序
- 0分配
- 静态路由实现0分配
- 命名路由约3分配
安装
go get -u github.com/bmf-san/goblin
使用示例
基于方法的路由
r := goblin.NewRouter()
r.Methods(http.MethodGet).Handler(`/`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "/")
}))
r.Methods(http.MethodGet, http.MethodPost).Handler(`/methods`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet {
fmt.Fprintf(w, "GET")
}
if r.Method == http.MethodPost {
fmt.Fprintf(w, "POST")
}
}))
http.ListenAndServe(":9999", r)
命名参数路由
r := goblin.NewRouter()
r.Methods(http.MethodGet).Handler(`/foo/:id`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := goblin.GetParam(r.Context(), "id")
fmt.Fprintf(w, "/foo/%v", id)
}))
r.Methods(http.MethodGet).Handler(`/foo/:name`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
name := goblin.GetParam(r.Context(), "name")
fmt.Fprintf(w, "/foo/%v", name)
}))
http.ListenAndServe(":9999", r)
基于正则表达式的路由
r.Methods(http.MethodGet).Handler(`/foo/:id[^\d+$]`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := goblin.GetParam(r.Context(), "id")
fmt.Fprintf(w, "/foo/%v", id)
}))
中间件
// 实现返回http.Handler的中间件函数
func global(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "global: before\n")
next.ServeHTTP(w, r)
fmt.Fprintf(w, "global: after\n")
})
}
func first(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "first: before\n")
next.ServeHTTP(w, r)
fmt.Fprintf(w, "first: after\n")
})
}
func second(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "second: before\n")
next.ServeHTTP(w, r)
fmt.Fprintf(w, "second: after\n")
})
}
func third(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "third: before\n")
next.ServeHTTP(w, r)
fmt.Fprintf(w, "third: after\n")
})
}
r := goblin.NewRouter()
// 设置全局中间件
r.UseGlobal(global)
r.Methods(http.MethodGet).Handler(`/globalmiddleware`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "/globalmiddleware\n")
}))
// 使用Use方法应用中间件
r.Methods(http.MethodGet).Use(first).Handler(`/middleware`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "middleware\n")
}))
// 可以配置多个中间件
r.Methods(http.MethodGet).Use(second, third).Handler(`/middlewares`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "middlewares\n")
}))
http.ListenAndServe(":9999", r)
请求/globalmiddleware
会得到以下结果:
global: before
/globalmiddleware
global: after
请求/middleware
会得到以下结果:
global: before
first: before
middleware
first: after
global: after
请求/middlewares
会得到以下结果:
global: before
second: before
third: before
middlewares
third: after
second: after
global: after
自定义错误处理程序
func customMethodNotFound() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "customMethodNotFound")
})
}
func customMethodAllowed() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "customMethodNotAllowed")
})
}
r := goblin.NewRouter()
r.NotFoundHandler = customMethodNotFound()
r.MethodNotAllowedHandler = customMethodAllowed()
http.ListenAndServe(":9999", r)
默认OPTIONS处理程序
func DefaultOPTIONSHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
})
}
r := goblin.NewRouter()
r.DefaultOPTIONSHandler = DefaultOPTIONSHandler()
http.ListenAndServe(":9999", r)
默认的OPTIONS处理程序在处理CORS OPTIONS请求(预检请求)时非常有用。
设计
goblin内部使用Trie树数据结构,相比基数树(Radix Tree),Trie树虽然性能稍逊,但算法更简单,更易于理解和维护。
路由定义在内部表示为树结构,每个HTTP方法都有自己的树,每个节点包含处理程序和中间件定义等数据。
完整示例
package main
import (
"fmt"
"net/http"
"github.com/bmf-san/goblin"
)
func main() {
r := goblin.NewRouter()
// 简单路由
r.Methods(http.MethodGet).Handler("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to goblin!")
}))
// 命名参数路由
r.Methods(http.MethodGet).Handler("/user/:name", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
name := goblin.GetParam(r.Context(), "name")
fmt.Fprintf(w, "Hello, %s!", name)
}))
// 正则表达式路由
r.Methods(http.MethodGet).Handler("/post/:id[^\\d+$]", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := goblin.GetParam(r.Context(), "id")
fmt.Fprintf(w, "Post ID: %s", id)
}))
// 中间件示例
authMiddleware := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Auth middleware - before")
next.ServeHTTP(w, r)
fmt.Println("Auth middleware - after")
})
}
r.Methods(http.MethodGet).Use(authMiddleware).Handler("/private", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Private area")
}))
fmt.Println("Server started at :8080")
http.ListenAndServe(":8080", r)
}
goblin是一个简单、高效且功能丰富的HTTP路由器,适合需要高性能路由的各种Golang web应用场景。
更多关于golang基于trie树实现的高性能HTTP路由插件库goblin的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于trie树实现的高性能HTTP路由插件库goblin的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用Goblin实现高性能HTTP路由
Goblin是一个基于Trie树实现的高性能HTTP路由库,专为Go语言设计。它通过Trie树的数据结构优化了路由匹配性能,特别适合需要处理大量路由规则的场景。
Goblin核心特性
- 基于Trie树的路由匹配:高效的路由查找算法
- 高性能:比标准库和许多流行路由库更快
- 支持参数路由:如
/user/:id
- 通配符支持:如
/static/*filepath
- 中间件支持:灵活的中间件机制
基本使用示例
首先安装Goblin:
go get github.com/bmf-san/goblin
1. 基本路由
package main
import (
"fmt"
"net/http"
"github.com/bmf-san/goblin"
)
func main() {
r := goblin.NewRouter()
// 注册路由
r.Methods(http.MethodGet).Handler("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, Goblin!")
}))
http.ListenAndServe(":8080", r)
}
2. 参数路由
r.Methods(http.MethodGet).Handler("/user/:id", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
params := goblin.GetParams(r.Context())
id := params["id"]
fmt.Fprintf(w, "User ID: %s", id)
}))
3. 通配符路由
r.Methods(http.MethodGet).Handler("/static/*filepath", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
params := goblin.GetParams(r.Context())
filepath := params["filepath"]
fmt.Fprintf(w, "Requested file: %s", filepath)
}))
4. 中间件支持
func logger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%s %s\n", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
})
}
func main() {
r := goblin.NewRouter()
r.Use(logger) // 全局中间件
// 路由特定的中间件
r.Methods(http.MethodGet).Handler("/admin", logger(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Admin page")
})))
http.ListenAndServe(":8080", r)
}
性能优化技巧
- 路由顺序:将最频繁访问的路由放在前面
- 减少通配符:过度使用通配符会影响性能
- 合理使用中间件:避免在中间件中进行耗时操作
- 路由分组:对相关路由进行分组管理
高级功能
路由分组
api := r.Group("/api")
api.Methods(http.MethodGet).Handler("/users", http.HandlerFunc(listUsers))
api.Methods(http.MethodPost).Handler("/users", http.HandlerFunc(createUser))
自定义404处理
r.NotFoundHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Custom 404 page")
}))
方法链式调用
r.Methods(http.MethodGet, http.MethodPost).
Handler("/multi", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
fmt.Fprintf(w, "GET request")
case http.MethodPost:
fmt.Fprintf(w, "POST request")
}
}))
基准测试
Goblin在路由匹配性能上表现优异,特别是在路由数量较多时,Trie树的优势更加明显。以下是一个简单的基准测试比较:
func BenchmarkGoblin(b *testing.B) {
r := goblin.NewRouter()
r.Methods(http.MethodGet).Handler("/user/:id", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
req, _ := http.NewRequest(http.MethodGet, "/user/123", nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.ServeHTTP(nil, req)
}
}
在实际测试中,Goblin通常比标准库的http.ServeMux
和其他一些流行路由库有更好的性能表现,特别是在路由规则复杂且数量大的情况下。
总结
Goblin是一个轻量级但功能强大的HTTP路由库,它通过Trie树数据结构实现了高效的路由匹配。对于需要高性能路由的项目,特别是那些有大量路由规则或对性能要求严格的场景,Goblin是一个值得考虑的选择。
它的API设计简洁,学习曲线平缓,同时提供了足够的功能满足大多数Web应用的需求。通过合理使用路由分组、中间件等特性,可以构建出结构清晰、性能优异的Web应用。