go语言学习 - caddy添加nacos-gateway
添加我们自己的module,找到这个文件 \caddy\modules\caddyhttp\standard\imports.go
package standard import ( // standard Caddy HTTP app modules _ "github.com/caddyserver/caddy/v2/modules/caddyhttp" _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/caddyauth" //other... _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy" //other.. //添加我们的package _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/nacosgateway" )
先看看我们的配置,Caddyfile文件部分节点
:2015 { bind localhost 192.168.1.133 root * D:\myenv\webvu file_server { index index.html index.htm } handle /gate/* { uri strip_prefix /gate reverse_proxy { dynamic nacos { server_addr 192.168.1.109 server_port 8848 name_space myenv gateway_addr 192.168.1.133 gateway_port 2015 gateway_service caddy } } } }
在写下面代码前,我们还需要知道这个dynamic nacos的module.id是什么,可以断点这个文件caddyserver\caddy\modules.go
func GetModule(name string) (ModuleInfo, error) { modulesMu.RLock() defer modulesMu.RUnlock() m, ok := modules[name] if !ok { return ModuleInfo{}, fmt.Errorf("module not registered: %s", name) } return m, nil }
以下是部分关键代码。程序会在启动时向nacos注册caddy服务。/gate/{service}/htmlurl的请求来时,会向nacos获取{service}的实际地址,将/htmlurl转到该地址上。
package nacosgateway import ( "fmt" "net/http" "strconv" "strings" "sync" "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy" "github.com/nacos-group/nacos-sdk-go/v2/clients" "github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client" "github.com/nacos-group/nacos-sdk-go/v2/common/constant" "github.com/nacos-group/nacos-sdk-go/v2/model" "github.com/nacos-group/nacos-sdk-go/v2/vo" ) func init() { caddy.RegisterModule(NacosUpstreamSource{}) } // NacosUpstreamSource 实现了 UpstreamSource 接口 type NacosUpstreamSource struct { ServerAddr string `json:"server_addr,omitempty"` ServerPort uint64 `json:"server_port,omitempty"` NameSpace string `json:"namespace,omitempty"` GatewayAddr string `json:"gateway_addr,omitempty"` GatewayPort uint64 `json:"gateway_port,omitempty"` GatewayService string `json:"gateway_service,omitempty"` client naming_client.INamingClient upstreamCache map[string][]*reverseproxy.Upstream // 新增缓存字段 cacheMutex sync.RWMutex // 用于保护缓存的读写锁 } // 初始化 NacosUpstreamSource 时初始化缓存 func NewNacosUpstreamSource() *NacosUpstreamSource { return &NacosUpstreamSource{ // 其他字段初始化... upstreamCache: make(map[string][]*reverseproxy.Upstream), } } // Provision 初始化 Nacos 客户端 func (n *NacosUpstreamSource) Provision(ctx caddy.Context) error { serverConfigs := []constant.ServerConfig{ { IpAddr: n.ServerAddr, Port: n.ServerPort, }, } clientConfig := constant.ClientConfig{ NamespaceId: n.NameSpace, TimeoutMs: 5000, NotLoadCacheAtStart: true, LogDir: "/tmp/nacos/log", CacheDir: "/tmp/nacos/cache", } var err error n.client, err = clients.NewNamingClient( vo.NacosClientParam{ ClientConfig: &clientConfig, ServerConfigs: serverConfigs, }, ) if err != nil { return err } // 注册服务实例 success, err0 := n.client.RegisterInstance(vo.RegisterInstanceParam{ Ip: n.GatewayAddr, Port: n.GatewayPort, ServiceName: n.GatewayService }) if err0 != nil { panic(err0) } if !success { return fmt.Errorf("Service registration failed") } return nil } // GetUpstreams 从 Nacos 获取服务列表 func (n *NacosUpstreamSource) GetUpstreams(r *http.Request) ([]*reverseproxy.Upstream, error) { // 提取 URL 中的服务名 serviceName, newPath := extractServiceName(r.URL.Path) // 从 URL 中去掉 /{service} 部分 r.URL.Path = newPath if serviceName == "" { // 如果没有提取到,使用默认服务名 return nil, fmt.Errorf("No service name found in URL") } // 先从缓存中查找 n.cacheMutex.RLock() upstreams, exists := n.upstreamCache[serviceName] n.cacheMutex.RUnlock() if exists { return upstreams, nil } serviceInfo, err := n.client.GetService(vo.GetServiceParam{ ServiceName: serviceName, }) if err != nil { return nil, err } if len(serviceInfo.Hosts) == 0 { return nil, fmt.Errorf("No instances found for service %s", serviceName) } // 构建 Upstream upstreams = make([]*reverseproxy.Upstream, 0, len(serviceInfo.Hosts)) for _, instance := range serviceInfo.Hosts { upstream := &reverseproxy.Upstream{ Dial: fmt.Sprintf("%s:%d", instance.Ip, instance.Port), } upstreams = append(upstreams, upstream) } // 将结果存入缓存 n.cacheMutex.Lock() n.upstreamCache[serviceName] = upstreams n.cacheMutex.Unlock() return upstreams, nil } // CaddyModule 返回模块信息 func (NacosUpstreamSource) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "http.reverse_proxy.upstreams.nacos", New: func() caddy.Module { return NewNacosUpstreamSource() }, } } func (n *NacosUpstreamSource) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { d.Next() // 跳过指令名: nacos for d.NextBlock(0) { switch d.Val() { case "server_addr": if !d.NextArg() { return d.ArgErr() } n.ServerAddr = d.Val() //其他属性 case "gateway_service": if !d.NextArg() { return d.ArgErr() } n.GatewayService = d.Val() default: return d.Errf("unrecognized subdirective %s", d.Val()) } } return nil } var _ caddy.Provisioner = (*NacosUpstreamSource)(nil) var _ reverseproxy.UpstreamSource = (*NacosUpstreamSource)(nil)
后面学习一下seaweedfs的源代码。
本文只发表在博客网,请勿转载!