使用Golang编写API网关的实践指南

使用Golang编写API网关的实践指南 我们拥有许多小型微服务。我们需要集成API网关。请问是否有相关的示例代码。

5 回复

或许 httputil 中的 ReverseProxy 可以作为一个很好的构建模块。

更多关于使用Golang编写API网关的实践指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


calmh:

ReverseProxy

我不了解反向代理。你有示例代码吗?

如果你不需要服务发现、负载均衡、速率限制、监控、认证这些功能,那么就像 @calmh 建议的那样,直接使用 ReverseProxy 即可。否则,可以尝试使用市场上现有的解决方案。

在Go中构建API网关,一个实用的方案是使用gin框架配合反向代理。以下是一个基础示例:

package main

import (
    "github.com/gin-gonic/gin"
    "net/http/httputil"
    "net/url"
)

func main() {
    r := gin.Default()
    
    // 用户服务代理
    userServiceURL, _ := url.Parse("http://localhost:8081")
    userProxy := httputil.NewSingleHostReverseProxy(userServiceURL)
    
    r.Any("/users/*path", func(c *gin.Context) {
        userProxy.ServeHTTP(c.Writer, c.Request)
    })
    
    // 订单服务代理
    orderServiceURL, _ := url.Parse("http://localhost:8082")
    orderProxy := httputil.NewSingleHostReverseProxy(orderServiceURL)
    
    r.Any("/orders/*path", func(c *gin.Context) {
        orderProxy.ServeHTTP(c.Writer, c.Request)
    })
    
    r.Run(":8080")
}

对于更复杂的场景,可以集成中间件进行认证和限流:

// 认证中间件
func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")
        if token != "valid-token" {
            c.JSON(401, gin.H{"error": "Unauthorized"})
            c.Abort()
            return
        }
        c.Next()
    }
}

// 限流中间件
func RateLimitMiddleware() gin.HandlerFunc {
    limiter := rate.NewLimiter(100, 10) // 100 QPS
    return func(c *gin.Context) {
        if !limiter.Allow() {
            c.JSON(429, gin.H{"error": "Too many requests"})
            c.Abort()
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.Default()
    
    // 应用中间件
    r.Use(AuthMiddleware())
    r.Use(RateLimitMiddleware())
    
    // 服务路由配置
    services := map[string]string{
        "/users/":  "http://localhost:8081",
        "/orders/": "http://localhost:8082",
        "/products/": "http://localhost:8083",
    }
    
    for path, target := range services {
        targetURL, _ := url.Parse(target)
        proxy := httputil.NewSingleHostReverseProxy(targetURL)
        
        r.Any(path+"*action", func(c *gin.Context) {
            proxy.ServeHTTP(c.Writer, c.Request)
        })
    }
    
    r.Run(":8080")
}

如果需要服务发现功能,可以集成Consul:

func getServiceURL(serviceName string) string {
    config := api.DefaultConfig()
    client, _ := api.NewClient(config)
    
    services, _, _ := client.Catalog().Service(serviceName, "", nil)
    if len(services) > 0 {
        service := services[0]
        return fmt.Sprintf("http://%s:%d", service.ServiceAddress, service.ServicePort)
    }
    return ""
}

这个实现提供了路由转发、中间件支持和基本的服务发现能力。可以根据具体需求添加日志记录、监控指标收集和熔断器等功能。

回到顶部