golang高性能HTTP路由插件库fasthttprouter的使用

golang高性能HTTP路由插件库fasthttprouter的使用

FastHttpRouter简介

FastHttpRouter是从httprouter fork而来,是一个轻量级高性能的HTTP请求路由器(也称为多路复用器或简称mux),专为fasthttp设计。

该路由器针对高性能和小内存占用进行了优化,即使在非常长的路径和大量路由情况下也能很好地扩展。它使用了压缩的动态trie(基数树)结构来实现高效匹配。

性能优势

FastHttpRouter是go-web-framework-benchmark中最快的Go web框架之一,甚至比httprouter本身更快。

性能测试结果

并发测试结果

主要特性

  1. 最佳性能:在各种基准测试中表现优异
  2. 明确匹配:请求路径只能精确匹配一个路由
  3. 自动处理斜杠:自动重定向缺失或多余的斜杠
  4. 路径自动修正:可修正大小写错误和多余路径元素
  5. 路径参数:轻松获取动态路径参数
  6. 零垃圾:匹配和调度过程几乎不产生垃圾
  7. 崩溃恢复:可设置Panic handler处理请求中的panic
  8. API友好:内置支持OPTIONS请求和405方法不允许响应

使用示例

下面是一个完整的FastHttpRouter使用示例:

package main

import (
	"fmt"
	"log"

	"github.com/buaazp/fasthttprouter"
	"github.com/valyala/fasthttp"
)

// 首页处理函数
func Index(ctx *fasthttp.RequestCtx) {
	fmt.Fprint(ctx, "Welcome!\n")
}

// 带参数的hello处理函数
func Hello(ctx *fasthttp.RequestCtx) {
	fmt.Fprintf(ctx, "hello, %s!\n", ctx.UserValue("name"))
}

func main() {
	// 创建新的路由器
	router := fasthttprouter.New()
	
	// 注册路由和处理函数
	router.GET("/", Index)
	router.GET("/hello/:name", Hello)

	// 启动服务器
	log.Fatal(fasthttp.ListenAndServe(":8080", router.Handler))
}

命名参数

:name是一个命名参数,可以通过ctx.UserValue("name")获取其值。命名参数只匹配单个路径段:

Pattern: /user/:user

/user/gordon              match
/user/you                 match
/user/gordon/profile      no match
/user/                    no match

通配参数

第二种参数类型是通配参数,形式为*name。它们必须始终位于模式末尾:

Pattern: /src/*filepath

/src/                     match
/src/somefile.go          match
/src/subdir/somefile.go   match

静态文件服务

可以使用NotFound handler来服务静态文件:

// 从./public目录提供静态文件
router.NotFound = fasthttp.FSHandler("./public", 0)

中间件

FastHttpRouter只是一个高效的请求路由器,你可以链式添加任何兼容fasthttp.RequestHandler的中间件。

工作原理

路由器依赖于大量使用公共前缀的树结构,本质上是一个紧凑的前缀树(或基数树)。每个请求方法都有单独的路由树,节点按优先级排序(子节点中注册的handler数量)。

许可证

FastHttpRouter基于httprouter,保留了原项目的许可证。它主要用于适配fasthttp,已在生产环境中处理每天1700万次请求,证明其快速稳定。


更多关于golang高性能HTTP路由插件库fasthttprouter的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能HTTP路由插件库fasthttprouter的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


FasthttpRouter - 高性能Golang HTTP路由库

FasthttpRouter是基于fasthttp的高性能HTTP请求路由器,它比标准库的net/http路由性能更高,内存分配更少。下面我将详细介绍它的使用方法和最佳实践。

基本特性

  1. 高性能:基于fasthttp,比标准库快很多
  2. 零内存分配:路由匹配过程几乎不分配内存
  3. 支持路径参数:可以轻松提取URL中的参数
  4. 轻量级:代码简洁,依赖少

安装

go get github.com/fasthttp/router
go get github.com/valyala/fasthttp

基本使用

package main

import (
	"fmt"
	"log"

	"github.com/fasthttp/router"
	"github.com/valyala/fasthttp"
)

func main() {
	r := router.New()

	// 注册路由
	r.GET("/", Index)
	r.GET("/hello/{name}", Hello)
	r.POST("/user", CreateUser)

	// 启动服务器
	log.Fatal(fasthttp.ListenAndServe(":8080", r.Handler))
}

func Index(ctx *fasthttp.RequestCtx) {
	fmt.Fprint(ctx, "Welcome!\n")
}

func Hello(ctx *fasthttp.RequestCtx) {
	name := ctx.UserValue("name").(string)
	fmt.Fprintf(ctx, "Hello, %s!\n", name)
}

func CreateUser(ctx *fasthttp.RequestCtx) {
	// 处理POST请求
	fmt.Fprint(ctx, "User created\n")
}

路由参数

FasthttpRouter支持多种参数匹配模式:

r := router.New()

// 命名参数
r.GET("/user/{id}", GetUser)

// 通配符参数
r.GET("/static/{filepath:*}", StaticFile)

// 可选参数
r.GET("/search/{query?}", Search)

路由分组

r := router.New()

// 用户相关路由
user := r.Group("/user")
user.GET("/", ListUsers)
user.POST("/", CreateUser)
user.GET("/{id}", GetUser)
user.PUT("/{id}", UpdateUser)
user.DELETE("/{id}", DeleteUser)

中间件支持

func Logger(next fasthttp.RequestHandler) fasthttp.RequestHandler {
	return func(ctx *fasthttp.RequestCtx) {
		start := time.Now()
		next(ctx)
		fmt.Printf("%s %s %s %v\n", 
			ctx.Method(), 
			ctx.Path(), 
			ctx.Response.StatusCode(), 
			time.Since(start))
	}
}

func main() {
	r := router.New()
	r.GET("/", Index)
	
	// 应用中间件
	wrappedHandler := Logger(r.Handler)
	
	fasthttp.ListenAndServe(":8080", wrappedHandler)
}

性能优化技巧

  1. 复用RequestCtx对象:fasthttp会复用ctx对象,不要在handler间传递它
  2. 避免频繁内存分配:使用ctx.PostBody()而不是ioutil.ReadAll
  3. 使用sync.Pool:对于频繁创建的对象使用对象池
var bufferPool = sync.Pool{
	New: func() interface{} {
		return &bytes.Buffer{}
	},
}

func Handler(ctx *fasthttp.RequestCtx) {
	buf := bufferPool.Get().(*bytes.Buffer)
	defer bufferPool.Put(buf)
	
	buf.Reset()
	// 使用buf处理数据
}

错误处理

r := router.New()
r.NotFound = func(ctx *fasthttp.RequestCtx) {
	ctx.SetStatusCode(fasthttp.StatusNotFound)
	fmt.Fprint(ctx, "Custom 404 page")
}

r.MethodNotAllowed = func(ctx *fasthttp.RequestCtx) {
	ctx.SetStatusCode(fasthttp.StatusMethodNotAllowed)
	fmt.Fprint(ctx, "Method not allowed")
}

实际案例:REST API服务

package main

import (
	"encoding/json"
	"log"

	"github.com/fasthttp/router"
	"github.com/valyala/fasthttp"
)

type User struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

var users = make(map[string]User)

func main() {
	r := router.New()

	// 用户路由
	r.GET("/users", listUsers)
	r.POST("/users", createUser)
	r.GET("/users/{id}", getUser)
	r.PUT("/users/{id}", updateUser)
	r.DELETE("/users/{id}", deleteUser)

	log.Fatal(fasthttp.ListenAndServe(":8080", r.Handler))
}

func listUsers(ctx *fasthttp.RequestCtx) {
	userList := make([]User, 0, len(users))
	for _, u := range users {
		userList = append(userList, u)
	}
	json.NewEncoder(ctx).Encode(userList)
}

func createUser(ctx *fasthttp.RequestCtx) {
	var user User
	if err := json.Unmarshal(ctx.PostBody(), &user); err != nil {
		ctx.Error(err.Error(), fasthttp.StatusBadRequest)
		return
	}
	users[user.ID] = user
	ctx.SetStatusCode(fasthttp.StatusCreated)
}

// 其他handler实现类似...

注意事项

  1. Fasthttp与标准库不兼容,不能混用net/http的handler
  2. RequestCtx的生命周期只在当前请求有效
  3. 某些标准库的特性在fasthttp中可能不可用

FasthttpRouter非常适合需要高性能HTTP服务的场景,特别是高并发、低延迟要求的应用。根据基准测试,它比标准库的路由性能高出数倍,内存分配也少得多。

回到顶部