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的源代码。
本文只发表在博客网,请勿转载!

浙公网安备 33010602011771号