服务注册与发现

目前在 Hertz 的开源版本支持的服务发现拓展都存放在 registry 中,欢迎大家参与项目贡献与维护。

到现在为止,支持的服务发现拓展有

配置

使用服务发现时会提供一些可选配置给用户。

配置 描述
WithSD 设置 isSD 为 true ,使用服务发现必选
WithTag 为 requestOptions 设置 tag 。
WithCustomizedAddrs 自定义目标实例地址。
WithLoadBalanceOptions 配置负载均衡选项。

WithSD

requestOptions 提供 WithSD 配置项,传入参数为 true 时将会设置 isSD 为 true。使用服务发现请求时必须使用 WithSD 配置项。

示例代码:

status, body, err := cli.Get(context.Background(), nil, "http://hertz.test.demo/ping", config.WithSD(true))

WithTag

requestOptions 提供 WithTag 配置项,使用此配置会为 requestOptions 设置 tag。

示例代码:

status, body, err := cli.Get(context.Background(), nil, "http://hertz.test.demo/ping", config.WithTag("foo", "var"))

WithCustomizedAddrs

此配置项指定服务发现时的目标实例地址。它将会覆盖来自 Resolver 的结果。Resolver 是服务发现中心,用于服务发现。

示例代码:

cli.Use(sd.Discovery(r, sd.WithCustomizedAddrs("127.0.0.1:8088")))

WithLoadBalanceOptions

此配置项可为客户端配置负载均衡算法和负载均衡参数。

示例代码:

cli.Use(sd.Discovery(r, sd.WithLoadBalanceOptions(loadbalance.NewWeightedBalancer(), loadbalance.Options{
    RefreshInterval: 5 * time.Second, 
    ExpireInterval:  15 * time.Second,
})))

Nacos

安装

go get github.com/hertz-contrib/registry/nacos

服务注册

Option

Nacos 拓展在服务注册部分中提供了 option 配置。

WithRegistryCluster

Nacos 扩展提供了 WithRegistryCluster 用于帮助用户配置自定义的集群。默认为 “DEFAULT” 。

函数签名:

func WithRegistryCluster(cluster string) RegistryOption

示例代码:

func main() {
    // ...
    r, err := nacos.NewDefaultNacosRegistry(
        nacos.WithRegistryCluster("Cluster123"),
    )
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}
WithRegistryGroup

Nacos 扩展提供了 WithRegistryGroup 用于帮助用户配置自定义的集群。默认为 “DEFAULT_GROUP” 。

函数签名:

func WithRegistryGroup(group string) RegistryOption

示例代码:

func main() {
    // ...
    r, err := nacos.NewDefaultNacosRegistry(
        nacos.WithRegistryGroup("Group1"),
    )
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

NewDefaultNacosRegistry

NewDefaultNacosRegistry 使用 nacos 创建一个默认的服务注册中心。会调用 NewDefaultNacosConfig 使用默认的客户端,默认设置 RegionID 为 cn-hangzhou、地址为 127.0.0.1、端口号为8848,且不会在开始时加载缓存。可自定义服务注册中心配置。

函数签名:

func NewDefaultNacosRegistry(opts ...RegistryOption) (registry.Registry, error)

示例代码:

func main() {
    // ...
    r, err := nacos.NewDefaultNacosRegistry()
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

NewNacosRegistry

NewNacosRegistry使用 nacos 创建一个可配置客户端的服务注册中心,需要传入自行配置的客户端。可自定义服务注册中心配置。

函数签名:

func NewNacosRegistry(client naming_client.INamingClient, opts ...RegistryOption) registry.Registry

示例代码:

func main() {
    // ...
    cli, err := clients.NewNamingClient(
        vo.NacosClientParam{
            ClientConfig:  &cc,
            ServerConfigs: sc,
        },
    )
    // ...
    r := nacos.NewNacosRegistry(cli)
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    // ...
}

服务发现

Option

Nacos 拓展在服务发现部分中提供了 option 配置。

WithRegistryCluster

Nacos 扩展提供了 WithRegistryCluster 用于帮助用户配置自定义的集群。默认为 “DEFAULT” 。

函数签名:

func WithRegistryCluster(cluster string) RegistryOption

示例代码:

func main() {
    client, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := nacos.NewDefaultNacosResolver(
    nacos.WithRegistryCluster("Cluster123"),
    )
    if err != nil {
        log.Fatal(err)
        return
    }
    client.Use(sd.Discovery(r))
    // ...
}
WithRegistryGroup

Nacos 扩展提供了 WithRegistryGroup 用于帮助用户配置自定义的集群。默认为 “DEFAULT_GROUP” 。

函数签名:

func WithRegistryGroup(group string) RegistryOption

示例代码:

func main() {
    client, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := nacos.NewDefaultNacosResolver(
    nacos.WithRegistryGroup("Group1"),
    )
    if err != nil {
        log.Fatal(err)
        return
    }
    client.Use(sd.Discovery(r))
    // ...
}

NewDefaultNacosResolver

NewDefaultNacosResolver 使用 nacos 创建一个默认的服务发现中心。会调用 NewDefaultNacosConfig 使用默认的客户端,默认设置 RegionID 为 cn-hangzhou、地址为 127.0.0.1、端口号为8848,且不会在开始时加载缓存。可自定义服务注册中心配置。

函数签名:

func NewDefaultNacosResolver(opts ...ResolverOption) (discovery.Resolver, error)

示例代码:

func main() {
    client, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := nacos.NewDefaultNacosResolver()
    if err != nil {
        log.Fatal(err)
        return
    }
    client.Use(sd.Discovery(r))
    // ...
}

NewNacosResolver

NewNacosResolver 使用 nacos 创建一个可配置客户端的服务发现中心,需要传入自行配置的客户端。可自定义服务发现中心配置。

函数签名:

func NewNacosResolver(cli naming_client.INamingClient, opts ...ResolverOption) discovery.Resolver

示例代码:

func main() {
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    // ...
    nacosCli, err := clients.NewNamingClient(
        vo.NacosClientParam{
            ClientConfig:  &cc,
            ServerConfigs: sc,
        })
    if err != nil {
        panic(err)
    }
    r := nacos.NewNacosResolver(nacosCli)
    cli.Use(sd.Discovery(r))
    // ...
}

使用示例

服务端

  • 使用 server.WithRegistry 设置注册扩展以及注册信息。
import (
    "context"
    "log"

    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/cloudwego/hertz/pkg/app/server/registry"
    "github.com/cloudwego/hertz/pkg/common/utils"
    "github.com/cloudwego/hertz/pkg/protocol/consts"
    "github.com/hertz-contrib/registry/nacos"
)

func main() {
    addr := "127.0.0.1:8888"
    r, err := nacos.NewDefaultNacosRegistry()
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
        ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
    })
    h.Spin()
}

客户端

  • 使用内置的 sd.Discovery 中间件,支持传入自定义的服务发现扩展以及负载均衡扩展。
  • 使用服务发现时需要将 Host 替换为服务名,并使用 config.WithSD 确定本次请求使用服务注册。
import (
    "context"
    "log"

    "github.com/cloudwego/hertz/pkg/app/client"
    "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
    "github.com/cloudwego/hertz/pkg/common/config"
    "github.com/cloudwego/hertz/pkg/common/hlog"
    "github.com/hertz-contrib/registry/nacos"
)

func main() {
    client, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := nacos.NewDefaultNacosResolver()
    if err != nil {
        log.Fatal(err)
        return
    }
    client.Use(sd.Discovery(r))
    for i := 0; i < 10; i++ {
        status, body, err := client.Get(context.Background(), nil, "http://hertz.test.demo/ping", config.WithSD(true))
        if err != nil {
            hlog.Fatal(err)
        }
        hlog.Infof("code=%d,body=%s\n", status, string(body))
    }
}

配置

可自定义 Nacos 客户端以及服务端的配置,参考 nacos-sdk-go 配置。

完整示例

完整用法示例详见 example

Consul

安装

go get github.com/hertz-contrib/registry/consul

服务注册

Option

Consul 拓展在服务注册部分中提供了 option 配置。

WithRegistryGroup

Consul 扩展提供了 WithCheck 用于帮助用户配置 Consul 中的 AgentServiceCheck 选项。默认调用 defaultCheck()

函数签名:

func WithCheck(check *api.AgentServiceCheck) Option

示例代码:

func main() {
    // ...
    consulClient, err := consulapi.NewClient(config)
    // ...
    check := &consulapi.AgentServiceCheck{
        // ...
    }
    r := consul.NewConsulRegister(consulClient, consul.WithCheck(check))
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

NewConsulRegister

NewConsulRegister 使用 consul 创建一个新的服务注册中心,需要传入客户端,其中客户端使用 NewClient 创建。可自定义服务注册中心配置,若不传入配置则设置 check.Timeout 为5秒,check.Internal 为5秒,check.DeregisterCriticalServiceAfter 为 1分钟。

函数签名:

func NewConsulRegister(consulClient *api.Client, opts ...Option) registry.Registry

示例代码:

func main() {
    // ...
    consulClient, err := consulapi.NewClient(config)
    // ...
    r := consul.NewConsulRegister(consulClient)
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

服务发现

Option

Consul 拓展在服务发现部分中提供了 option 配置。

WithRegistryGroup

Consul 扩展提供了 WithCheck 用于帮助用户配置 Consul 中的 AgentServiceCheck 选项。默认调用 defaultCheck()

函数签名:

func WithCheck(check *api.AgentServiceCheck) Option

示例代码:

func main() {
    // ...
    consulClient, err := consulapi.NewClient(consulConfig)
    if err != nil {
        log.Fatal(err)
        return
    }
    check := &consulapi.AgentServiceCheck{
        // ...
    }
    r := consul.NewConsulResolver(consulClient, consul.WithCheck(check))

    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
}

NewConsulResolver

NewConsulResolver 使用 consul 创建一个新的服务发现中心,需要传入客户端,其中客户端使用 NewClient 创建。可自定义服务发现中心配置。

函数签名:

func NewConsulResolver(consulClient *api.Client, opts ...Option) discovery.Resolver

示例代码:

func main() {
    // ...
    consulClient, err := consulapi.NewClient(consulConfig)
    if err != nil {
        log.Fatal(err)
        return
    }
    r := consul.NewConsulResolver(consulClient)

    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
}

使用示例

服务端

import (
    "context"
    "log"

    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/cloudwego/hertz/pkg/app/server/registry"
    "github.com/cloudwego/hertz/pkg/common/utils"
    "github.com/cloudwego/hertz/pkg/protocol/consts"
    consulapi "github.com/hashicorp/consul/api"
    "github.com/hertz-contrib/registry/consul"
)


func main() {
    // build a consul client
    config := consulapi.DefaultConfig()
    config.Address = "127.0.0.1:8500"
    consulClient, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatal(err)
        return
    }
    // build a consul register with the consul client
    r := consul.NewConsulRegister(consulClient)

    // run Hertz with the consul register
    addr := "127.0.0.1:8888"
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
        ctx.JSON(consts.StatusOK, utils.H{"ping": "pong1"})
    })
    h.Spin()
}

客户端

import (
    "log"

    "github.com/cloudwego/hertz/pkg/app/client"
    "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
    consulapi "github.com/hashicorp/consul/api"
    "github.com/hertz-contrib/registry/consul"
)

func main() {
    // build a consul client
    consulConfig := consulapi.DefaultConfig()
    consulConfig.Address = "127.0.0.1:8500"
    consulClient, err := consulapi.NewClient(consulConfig)
    if err != nil {
        log.Fatal(err)
        return
    }
    // build a consul resolver with the consul client
    r := consul.NewConsulResolver(consulClient)

    // build a hertz client with the consul resolver
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
}

配置

可自定义 Nacos 客户端以及服务端的配置,参考 consul 配置。

完整实例

完整用法示例详见 example

Etcd

安装

go get github.com/hertz-contrib/registry/etcd

服务注册

Option

Etcd 拓展在服务注册部分中提供了 option 配置。

WithTLSOpt

Etcd 扩展提供了 WithTLSOpt 用于帮助用户配置一个通过 tls/ssl 进行身份验证的选项。

函数签名:

func WithTLSOpt(certFile, keyFile, caFile string) Option

示例代码:

func main() {
    r, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"},
        etcd.WithTLSOpt(certFile, keyFile, caFile),
    )
    if err != nil {
        panic(err)
    }
    // ...
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    // ...
}

NewEtcdRegistry

NewEtcdRegistry 使用 etcd 创建一个新的服务注册中心,需要传入端点值。可自定义客户端配置并传入 New 创建一个新的客户端。可自定义服务注册中心配置。

函数签名:

func NewEtcdRegistry(endpoints []string, opts ...Option) (registry.Registry, error)

示例代码:

func main() {
    r, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"})
    if err != nil {
        panic(err)
    }
    // ...
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    // ...
}

服务发现

Option

Etcd 拓展在服务发现部分中提供了 option 配置。

WithTLSOpt

Etcd 扩展提供了 WithTLSOpt 用于帮助用户配置一个通过 tls/ssl 进行身份验证的选项。

函数签名:

func WithTLSOpt(certFile, keyFile, caFile string) Option

示例代码:

func main() {
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"},
        etcd.WithTLSOpt(certFile, keyFile, caFile),
    )
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}

NewEtcdResolver

NewEtcdResolver 使用 etcd 创建一个新的服务发现中心,需要传入端点值。可自定义客户端配置并传入 New 创建一个新的客户端。可自定义服务发现中心配置。

函数签名:

func NewEtcdResolver(endpoints []string, opts ...Option) (discovery.Resolver, error)

示例代码:

func main() {
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := etcd.NewEtcdResolver([]string{"127.0.0.1:2379"})
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}

使用示例

服务端

import (
    "context"

    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/cloudwego/hertz/pkg/app/server/registry"
    "github.com/cloudwego/hertz/pkg/common/utils"
    "github.com/cloudwego/hertz/pkg/protocol/consts"
    "github.com/hertz-contrib/registry/etcd"
)

func main() {
    r, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"})
    if err != nil {
        panic(err)
    }
    addr := "127.0.0.1:8888"
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    h.GET("/ping", func(_ context.Context, ctx *app.RequestContext) {
        ctx.JSON(consts.StatusOK, utils.H{"ping": "pong2"})
    })
    h.Spin()
}

客户端

import (
    "context"

    "github.com/cloudwego/hertz/pkg/app/client"
    "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
    "github.com/cloudwego/hertz/pkg/common/config"
    "github.com/cloudwego/hertz/pkg/common/hlog"
    "github.com/hertz-contrib/registry/etcd"
)

func main() {
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := etcd.NewEtcdResolver([]string{"127.0.0.1:2379"})
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    for i := 0; i < 10; i++ {
        status, body, err := cli.Get(context.Background(), nil, "http://hertz.test.demo/ping", config.WithSD(true))
        if err != nil {
            hlog.Fatal(err)
        }
        hlog.Infof("HERTZ: code=%d,body=%s", status, string(body))
    }
}

配置

可自定义 Etcd 客户端以及服务端的配置,参考 etcd-client 配置。

完整示例

完整用法示例详见 example

Eureka

安装

go get github.com/hertz-contrib/eureka

服务注册

NewEurekaRegistry

NewEurekaRegistry 使用 eureka 创建一个新的服务注册中心,需要将服务 Url 通过一个字符串切片传入 NewConn ,并同时传入心跳间隔时长。

函数签名:

func NewEurekaRegistry(servers []string, heatBeatInterval time.Duration) *eurekaRegistry

示例代码:

func main() {
    // ...
    r := eureka.NewEurekaRegistry([]string{"http://127.0.0.1:8761/eureka"}, 40*time.Second)
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.discovery.eureka",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    //...
}

NewEurekaRegistryFromConfig

NewEurekaRegistryFromConfig 使用 eureka 创建一个新的服务注册中心,需要传入配置并调用 NewConnFromConfig ,也需要传入心跳间隔时长。

函数签名:

func NewEurekaRegistryFromConfig(config fargo.Config, heatBeatInterval time.Duration) *eurekaRegistry

示例代码:

func main() {
    // ...
    config := fargo.Config{
    // ...
    }
    r := eureka.NewEurekaRegistryFromConfig(config, 40*time.Second)
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.discovery.eureka",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    //...
}

NewEurekaRegistryFromConn

NewEurekaRegistryFromConn 使用 eureka 创建一个新的服务注册中心,需要直接传入 conn ,也需要传入心跳间隔时长。

函数签名:

func NewEurekaRegistryFromConn(conn fargo.EurekaConnection, heatBeatInterval time.Duration) *eurekaRegistry

示例代码:

func main() {
    // ...
    conn := fargo.EurekaConnection{
    // ...
    }
    r := eureka.NewEurekaRegistryFromConn(conn, 40*time.Second)
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.discovery.eureka",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    //...
}

服务发现

NewEurekaResolver

NewEurekaResolver 使用 eureka 创建一个新的服务发现中心,需要将服务 Url 通过一个字符串切片传入 NewConn

函数签名:

func NewEurekaResolver(servers []string) *eurekaResolver

示例代码:

func main() {
    cli, err := client.NewClient()
    if err != nil {
        hlog.Fatal(err)
        return
    }
    r := eureka.NewEurekaResolver([]string{"http://127.0.0.1:8761/eureka"})

    cli.Use(sd.Discovery(r))
    // ...
}

NewEurekaResolverFromConfig

NewEurekaResolverFromConfig 使用 eureka 创建一个新的服务发现中心,需要传入配置并调用 NewConnFromConfig

函数签名:

func NewEurekaResolverFromConfig(config fargo.Config) *eurekaResolver

示例代码:

func main() {
    // ...
    config := fargo.Config{
    // ...
    }
    cli, err := client.NewClient()
    if err != nil {
        hlog.Fatal(err)
        return
    }
    r := eureka.NewEurekaResolverFromConfig(config)

    cli.Use(sd.Discovery(r))
    // ...
}

NewEurekaResolverFromConn

NewEurekaResolverFromConn 使用 eureka 创建一个新的服务发现中心,需要直接传入 conn 。

函数签名:

func NewEurekaResolverFromConn(conn fargo.EurekaConnection) *eurekaResolver

示例代码:

func main() {
    // ...
    conn := fargo.EurekaConnection{
    // ...
    }
    cli, err := client.NewClient()
    if err != nil {
        hlog.Fatal(err)
        return
    }
    r := eureka.NewEurekaResolverFromConn(conn)

    cli.Use(sd.Discovery(r))
    // ...
}

使用示例

服务端

import (
    "context"
    "time"

    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/cloudwego/hertz/pkg/app/server/registry"
    "github.com/cloudwego/hertz/pkg/common/utils"
    "github.com/cloudwego/hertz/pkg/protocol/consts"
    "github.com/hertz-contrib/eureka"
)

func main() {
    addr := "127.0.0.1:8888"
    r := eureka.NewEurekaRegistry([]string{"http://127.0.0.1:8761/eureka"}, 40*time.Second)
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.discovery.eureka",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
        ctx.JSON(consts.StatusOK, utils.H{"ping": "pong2"})
    })
    h.Spin()
}

客户端

import (
    "context"

    "github.com/cloudwego/hertz/pkg/app/client"
    "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
    "github.com/cloudwego/hertz/pkg/common/config"
    "github.com/cloudwego/hertz/pkg/common/hlog"
    "github.com/hertz-contrib/eureka"
)

func main() {
    cli, err := client.NewClient()
    if err != nil {
        hlog.Fatal(err)
        return
    }
    r := eureka.NewEurekaResolver([]string{"http://127.0.0.1:8761/eureka"})

    cli.Use(sd.Discovery(r))
    for i := 0; i < 10; i++ {
        status, body, err := cli.Get(context.Background(), nil, "http://hertz.discovery.eureka/ping", config.WithSD(true))
        if err != nil {
            hlog.Fatal(err)
        }
        hlog.Infof("code=%d,body=%s", status, string(body))
    }
}

配置

本项目使用 fargo 作为 eureka 客户端。 您应该参考 fargo 文档以了解高级配置。

完整示例

完整用法示例详见 example

Polaris

安装

go get github.com/hertz-contrib/registry/polaris

服务注册

NewPolarisRegistry

NewPolarisRegistry 使用 polaris 创建一个新的服务注册中心,可传入配置文件并调用 GetPolarisConfig ,若不传入则使用默认配置。

函数签名:

func NewPolarisRegistry(configFile ...string) (Registry, error)

示例代码:

func main() {
    r, err := polaris.NewPolarisRegistry(confPath)
    if err != nil {
        log.Fatal(err)
    }

    Info := &registry.Info{
        ServiceName: "hertz.test.demo",
        Addr:        utils.NewNetAddr("tcp", "127.0.0.1:8888"),
        Tags: map[string]string{
            "namespace": Namespace,
        },
    }
    h := server.Default(server.WithRegistry(r, Info), server.WithExitWaitTime(10*time.Second))
    // ...
}

服务发现

NewPolarisResolver

NewPolarisResolver 使用 polaris 创建一个新的服务发现中心,可传入配置文件并调用 GetPolarisConfig ,若不传入则使用默认配置。

函数签名:

func NewPolarisResolver(configFile ...string) (Resolver, error)

示例代码:

func main() {
    r, err := polaris.NewPolarisResolver(confPath)
    if err != nil {
        log.Fatal(err)
    }

    client, err := hclient.NewClient()
    client.Use(sd.Discovery(r))
    //...
}

使用示例

服务端

import (
    "context"
    "log"
    "time"

    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/cloudwego/hertz/pkg/app/server/registry"
    "github.com/cloudwego/hertz/pkg/common/utils"
    "github.com/cloudwego/hertz/pkg/protocol/consts"
    "github.com/hertz-contrib/registry/polaris"
)

const (
    confPath  = "polaris.yaml"
    Namespace = "Polaris"
    // At present,polaris server tag is v1.4.0,can't support auto create namespace,
    // If you want to use a namespace other than default,Polaris ,before you register an instance,
    // you should create the namespace at polaris console first.
)

func main() {
    r, err := polaris.NewPolarisRegistry(confPath)

    if err != nil {
        log.Fatal(err)
    }

    Info := &registry.Info{
        ServiceName: "hertz.test.demo",
        Addr:        utils.NewNetAddr("tcp", "127.0.0.1:8888"),
        Tags: map[string]string{
            "namespace": Namespace,
        },
    }
    h := server.Default(server.WithRegistry(r, Info), server.WithExitWaitTime(10*time.Second))

    h.GET("/hello", func(ctx context.Context, c *app.RequestContext) {
        c.String(consts.StatusOK, "Hello,Hertz!")
    })

    h.Spin()
}

客户端

import (
    "context"
    "log"

    hclient "github.com/cloudwego/hertz/pkg/app/client"
    "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
    "github.com/cloudwego/hertz/pkg/common/config"
    "github.com/cloudwego/hertz/pkg/common/hlog"
    "github.com/hertz-contrib/registry/polaris"
)

const (
    confPath  = "polaris.yaml"
    Namespace = "Polaris"
    // At present,polaris server tag is v1.4.0,can't support auto create namespace,
    // if you want to use a namespace other than default,Polaris ,before you register an instance,
    // you should create the namespace at polaris console first.
)

func main() {
    r, err := polaris.NewPolarisResolver(confPath)
    if err != nil {
        log.Fatal(err)
    }

    client, err := hclient.NewClient()
    client.Use(sd.Discovery(r))

    for i := 0; i < 10; i++ {
        // config.WithTag sets the namespace tag for service discovery
        status, body, err := client.Get(context.TODO(), nil, "http://hertz.test.demo/hello", config.WithSD(true), config.WithTag("namespace", Namespace))
        if err != nil {
            hlog.Fatal(err)
        }
        hlog.Infof("code=%d,body=%s\n", status, body)
    }
}

配置

可自定义 polaris 客户端以及服务端的配置,参考 polaris-go 配置。

完整示例

完整用法示例详见 example

Servicecomb

安装

go get github.com/hertz-contrib/registry/servicecomb

服务注册

Option

Servicecomb 拓展在服务注册部分中提供了 option 配置。

WithAppId

Servicecomb 扩展提供了 WithAppId 用于帮助用户配置 Servicecomb 的 AppId 。默认为 “DEFAULT" 。

函数签名:

func WithAppId(appId string) RegistryOption

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr},
        servicecomb.WithAppId("appID"),
        )
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.servicecomb.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}
WithRegistryVersionRule

Servicecomb 扩展提供了 WithRegistryVersionRule 用于帮助用户配置 Servicecomb 的版本要求 。默认为 1.0.0 。

函数签名:

func WithRegistryVersionRule(versionRule string) RegistryOption

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr},
        servicecomb.WithRegistryVersionRule("1.1.0"),
        )
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.servicecomb.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}
WithRegistryHostName

Servicecomb 扩展提供了 WithRegistryHostName 用于帮助用户配置 Servicecomb 的主机名 。默认为 ”DEFAULT" 。

函数签名:

func WithRegistryHostName(hostName string) RegistryOption

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr},
        servicecomb.WithRegistryHostName("hostName"),
        )
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.servicecomb.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}
WithRegistryHeartbeatInterval

Servicecomb 扩展提供了 WithRegistryHeartbeatInterval 用于帮助用户配置发送心跳包的间隔时长 。默认为5。

函数签名:

func WithRegistryHeartbeatInterval(second int32) RegistryOption

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr},
        servicecomb.WithRegistryHeartbeatInterval(10),
        )
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.servicecomb.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

NewDefaultSCRegistry

NewDefaultSCRegistry 使用 service-comb 创建一个默认服务注册中心,需要传入端点值。可自定义服务注册中心配置。

函数签名:

func NewDefaultSCRegistry(endPoints []string, opts ...RegistryOption) (registry.Registry, error)

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr})
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.servicecomb.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

NewSCRegistry

NewSCRegistry 使用 service-comb 创建一个新的服务注册中心。需要传入自定义客户端。可自定义服务注册中心配置。

函数签名:

func NewSCRegistry(client *sc.Client, opts ...RegistryOption) registry.Registry

示例代码:

func main() {
    client := &sc.Client{
        // ...
    }
    // ...
    r, err := servicecomb.NewSCRegistry(config)
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.servicecomb.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

服务发现

Option

Servicecomb 拓展在服务发现部分中提供了 option 配置。

WithAppId

Servicecomb 扩展提供了 WithAppId 用于帮助用户配置 Servicecomb 的 AppId 。默认为 “DEFAULT" 。

函数签名:

func WithResolverAppId(appId string) ResolverOption

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr},
        servicecomb.WithAppId("appID"),
        )
    if err != nil {
        panic(err)
    }
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}
WithResolverVersionRule

Servicecomb 扩展提供了 WithResolverVersionRule 用于帮助用户配置 Servicecomb 的版本要求 。默认为 latest 。

函数签名:

func WithResolverVersionRule(versionRule string) ResolverOption

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr},
        servicecomb.WithResolverVersionRule("1.0.0"),
        )
    if err != nil {
        panic(err)
    }
    cli, err := client.NewClient()
    if err != nil {
		panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}
WithResolverConsumerId

Servicecomb 扩展提供了 WithResolverConsumerId 用于帮助用户配置 Servicecomb 的 ConsumerId 。默认为空 。

函数签名:

func WithResolverConsumerId(consumerId string) ResolverOption

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr},
        servicecomb.WithResolverConsumerId("1"),
        )
    if err != nil {
        panic(err)
    }
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}

NewDefaultSCResolver

NewDefaultSCResolver 使用 service-comb 创建一个默认服务发现中心,需要传入端点值。可自定义服务发现中心配置。

函数签名:

func NewDefaultSCResolver(endPoints []string, opts ...ResolverOption) (discovery.Resolver, error)

示例代码:

func main() {
    // ...
    r, err := servicecomb.NewDefaultSCResolver([]string{scAddr})
    if err != nil {
        panic(err)
    }
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}

NewSCResolver

NewSCReslover 使用 service-comb 创建一个新的服务发现中心。需要传入自定义客户端。可自定义服务发现中心配置。

函数签名:

func NewSCResolver(cli *sc.Client, opts ...ResolverOption) discovery.Resolver

示例代码:

func main() {
    client := &sc.Client{
        // ...
    }
    // ...
    r, err := servicecomb.NewSCResolver(client)
    if err != nil {
        panic(err)
    }
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}

使用示例

服务端

import (
    "context"
    "log"
    "sync"

    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/cloudwego/hertz/pkg/app/server/registry"
    "github.com/cloudwego/hertz/pkg/common/utils"
    "github.com/cloudwego/hertz/pkg/protocol/consts"
    "github.com/hertz-contrib/registry/servicecomb"
)

func main() {
    const scAddr = "127.0.0.1:30100"
    const addr = "127.0.0.1:8701"
    r, err := servicecomb.NewDefaultSCRegistry([]string{scAddr})
    if err != nil {
        log.Fatal(err)
        return
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.servicecomb.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )

    h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
        ctx.JSON(consts.StatusOK, utils.H{"ping": "pong1"})
    })
    h.Spin()
}

客户端

import (
    "context"

    "github.com/cloudwego/hertz/pkg/app/client"
    "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
    "github.com/cloudwego/hertz/pkg/common/config"
    "github.com/cloudwego/hertz/pkg/common/hlog"
    "github.com/hertz-contrib/registry/servicecomb"
)

func main() {
    const scAddr = "127.0.0.1:30100"
    // build a servicecomb resolver
    r, err := servicecomb.NewDefaultSCResolver([]string{scAddr})
    if err != nil {
        panic(err)
    }
    // build a hertz client with the servicecomb resolver
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    for i := 0; i < 10; i++ {
        status, body, err := cli.Get(context.Background(), nil, "http://hertz.servicecomb.demo/ping", config.WithSD(true))
        if err != nil {
            hlog.Fatal(err)
        }
        hlog.Infof("code=%d,body=%s", status, string(body))
    }
}

配置

可自定义 Servicecomb 客户端以及服务端的配置,参考 go-chassis/sc-client 配置

完整示例

完整用法示例详见 example

Zookeeper

安装

go get github.com/hertz-contrib/registry/zookeeper

服务注册

NewZookeeperRegistry

NewZookeeperRegistry 使用 zookeeper 创建一个服务注册中心,需要将服务通过一个字符串切片与会话超时时间共同传入 Connect

函数签名:

func NewZookeeperRegistry(servers []string, sessionTimeout time.Duration) (registry.Registry, error)

示例代码:

func main() {
    // ...
    r, err := zookeeper.NewZookeeperRegistry([]string{"127.0.0.1:2181"}, 40*time.Second)
    if err != nil {
        panic(err)
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    // ...
}

NewZookeeperRegistryWithAuth

NewZookeeperRegistryWithAuth 使用 zookeeper 创建一个服务注册中心,需要将服务通过一个字符串切片与会话超时时间共同传入 Connect 。除此之外还需要传入用户与密码来调用 AddAuth ,用户与密码不能为空。

函数签名:

func NewZookeeperRegistryWithAuth(servers []string, sessionTimeout time.Duration, user, password string)

示例代码:

func main() {
    // ...
    r, err := zookeeper.NewZookeeperRegistryWithAuth([]string{"127.0.0.1:2181"}, 20*time.Second, "hertzuser", "hertzpass")
    if err != nil {
        panic(err)
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    // ...
}

服务发现

NewZookeeperResolver

NewZookeeperResolver 使用 zookeeper 创建一个服务发现中心,需要将服务通过一个字符串切片与会话超时时间共同传入 Connect

函数签名:

func NewZookeeperResolver(servers []string, sessionTimeout time.Duration) (discovery.Resolver, error)

示例代码:

func main() {
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := zookeeper.NewZookeeperResolver([]string{"127.0.0.1:2181"}, 40*time.Second)
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}

NewZookeeperResolverWithAuth

NewZookeeperResolverWithAuth 使用 zookeeper 创建一个服务发现中心,需要将服务通过一个字符串切片与会话超时时间共同传入 Connect 。除此之外还需要传入用户与密码来调用 AddAuth ,用户与密码不能为空。

函数签名:

func NewZookeeperResolverWithAuth(servers []string, sessionTimeout time.Duration, user, password string)

示例代码:

func main() {
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := zookeeper.NewZookeeperResolverWithAuth([]string{"127.0.0.1:2181"}, 40*time.Second, "hertzuser", "hertzpass")
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    // ...
}

使用示例

服务端

import (
    "context"
    "time"

    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/cloudwego/hertz/pkg/app/server/registry"
    "github.com/cloudwego/hertz/pkg/common/utils"
    "github.com/cloudwego/hertz/pkg/protocol/consts"
    "github.com/hertz-contrib/registry/zookeeper"
)

func main() {
    addr := "127.0.0.1:8888"
    r, err := zookeeper.NewZookeeperRegistry([]string{"127.0.0.1:2181"}, 40*time.Second)
    if err != nil {
        panic(err)
    }
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }))
    h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
        ctx.JSON(consts.StatusOK, utils.H{"ping": "pong2"})
    })
    h.Spin()
}

客户端

import (
    "context"
    "time"

    "github.com/cloudwego/hertz/pkg/app/client"
    "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
    "github.com/cloudwego/hertz/pkg/common/config"
    "github.com/cloudwego/hertz/pkg/common/hlog"
    "github.com/hertz-contrib/registry/zookeeper"
)

func main() {
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r, err := zookeeper.NewZookeeperResolver([]string{"127.0.0.1:2181"}, 40*time.Second)
    if err != nil {
        panic(err)
    }
    cli.Use(sd.Discovery(r))
    for i := 0; i < 10; i++ {
        status, body, err := cli.Get(context.Background(), nil, "http://hertz.test.demo/ping", config.WithSD(true))
        if err != nil {
            hlog.Fatal(err)
        }
        hlog.Infof("code=%d,body=%s", status, string(body))
    }
}

配置

可自定义 zookeeper 客户端以及服务端的配置,参考 go-zookeeper/zk 配置。

完整示例

完整用法示例详见 example

Redis

安装

go get github.com/hertz-contrib/registry/redis

服务注册

Option

Redis 拓展在服务注册部分中提供了 option 配置。

WithPassword

Redis 扩展提供了 WithPassword 配置 redis 的密码,此密码必须匹配服务器配置选项中指定的密码。

函数签名:

func WithPassword(password string) Option

示例代码:

func main() {
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithPassword("123456"))
    // ...
    h := server.Default(
    server.WithHostPorts(addr),
    server.WithRegistry(r, &registry.Info{
      ServiceName: "hertz.test.demo",
      Addr:        utils.NewNetAddr("tcp", addr),
      Weight:      10,
      Tags:        nil,
    }),
    )
    // ...
}
WithDB

Redis 扩展提供了 WithDB 配置连接到服务器后要选择的数据库。

函数签名:

func WithDB(db int) Option

示例代码:

func main() {
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithDB(1))
    // ...
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}
WithTLSConfig

Redis 扩展提供了 WithTLSConfig 配置 TLS 的配置项。

函数签名:

func WithTLSConfig(t *tls.Config) Option

示例代码:

func main() {
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithTLSConfig(&tls.Config{
    // ...
    }))
    // ...
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}
WithDialer

Redis 扩展提供了 WithDialer 配置 Dialer,Dialer 将会创建新的网络连接并优先于 Network 和 Addr 选项。

函数签名:

func WithDialer(dialer func(ctx context.Context, network, addr string) (net.Conn, error)) Option

示例代码:

func main() {
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithDialer(
    // ...
    ))
    // ...
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}
WithReadTimeout

Redis 扩展提供了 WithReadTimeout 配置读取 socket 超时的时间,默认为 3 秒。

函数签名:

func WithReadTimeout(t time.Duration) Option

示例代码:

func main() {
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithReadTimeout(5*time.Second))
    // ...
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}
WithWriteTimeout

Redis 扩展提供了 WithWriteTimeout 配置写入 socket 超时的时间,默认等同于 ReadTimeout

函数签名:

func WithWriteTimeout(t time.Duration) Option

示例代码:

func main() {
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithWriteTimeout(5*time.Second))
    // ...
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

NewRedisRegistry

NewRedisRegistry 使用 redis 创建一个新的服务注册中心,需要传入目标地址。可自定义客户端配置并传入 NewClient 创建一个新的客户端。

函数签名:

func NewRedisRegistry(addr string, opts ...Option) registry.Registry

示例代码:

func main() {
    r := redis.NewRedisRegistry("127.0.0.1:6379")
    // ...
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    // ...
}

服务发现

Option

Redis 拓展在服务发现部分中提供了 option 配置。

WithPassword

Redis 扩展提供了 WithPassword 配置 redis 的密码,此密码必须匹配服务器配置选项中指定的密码。

函数签名:

func WithPassword(password string) Option

示例代码:

func main() {
    cli, err := client.NewClient()
    // ...
    r := redis.NewRedisResolver("127.0.0.1:6379", redis.WithPassword("123456"))
    cli.Use(sd.Discovery(r))
    // ...
}
WithDB

Redis 扩展提供了 WithDB 配置连接到服务器后要选择的数据库。

函数签名:

func WithDB(db int) Option

示例代码:

func main() {
    cli, err := client.NewClient()
    // ...
    r := redis.NewRedisResolver("127.0.0.1:6379", redis.WithDB(1))
    cli.Use(sd.Discovery(r))
    // ...
}
WithTLSConfig

Redis 扩展提供了 WithTLSConfig 配置 TLS 的配置项。

函数签名:

func WithTLSConfig(t *tls.Config) Option

示例代码:

func main() {
    cli, err := client.NewClient()
    // ...
    r := redis.NewRedisResolver("127.0.0.1:6379", redis.WithTLSConfig(&tls.Config{
    // ...
    }))
    cli.Use(sd.Discovery(r))
    // ...
}
WithDialer

Redis 扩展提供了 WithDialer 配置 Dialer,Dialer 将会创建新的网络连接并优先于 Network 和 Addr 选项。

函数签名:

func WithDialer(dialer func(ctx context.Context, network, addr string) (net.Conn, error)) Option

示例代码:

func main() {
    cli, err := client.NewClient()
    // ...
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithDialer(
    // ...
    ))
    cli.Use(sd.Discovery(r))
    // ...
}
WithReadTimeout

Redis 扩展提供了 WithReadTimeout 配置读取 socket 超时的时间,默认为 3 秒。

函数签名:

func WithReadTimeout(t time.Duration) Option

示例代码:

func main() {
    cli, err := client.NewClient()
    // ...
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithReadTimeout(5*time.Second))
    // ...
    ))
    cli.Use(sd.Discovery(r))
    // ...
}
WithWriteTimeout

Redis 扩展提供了 WithWriteTimeout 配置写入 socket 超时的时间,默认等同于 ReadTimeout

函数签名:

func WithWriteTimeout(t time.Duration) Option

示例代码:

func main() {
    cli, err := client.NewClient()
    // ...
    r := redis.NewRedisRegistry("127.0.0.1:6379", redis.WithWriteTimeout(5*time.Second))
    // ...
    ))
    cli.Use(sd.Discovery(r))
    // ...
}

NewRedisResolver

NewRedisResolver 使用 redis 创建一个新的服务发现中心,需要传入目标地址。可自定义客户端配置并传入 NewClient 创建一个新的客户端。

函数签名:

func NewRedisResolver(addr string, opts ...Option) discovery.Resolver

示例代码:

func main() {
    cli, err := client.NewClient()
    // ...
    r := redis.NewRedisResolver("127.0.0.1:6379")
    cli.Use(sd.Discovery(r))
    // ...
}

使用示例

服务端

package main

import (
	"context"

	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/app/server"
	"github.com/cloudwego/hertz/pkg/app/server/registry"
	"github.com/cloudwego/hertz/pkg/common/utils"
	"github.com/cloudwego/hertz/pkg/protocol/consts"
	"github.com/hertz-contrib/registry/redis"
)

func main() {
    r := redis.NewRedisRegistry("127.0.0.1:6379")
    addr := "127.0.0.1:8888"
    h := server.Default(
        server.WithHostPorts(addr),
        server.WithRegistry(r, &registry.Info{
            ServiceName: "hertz.test.demo",
            Addr:        utils.NewNetAddr("tcp", addr),
            Weight:      10,
            Tags:        nil,
        }),
    )
    h.GET("/ping", func(_ context.Context, ctx *app.RequestContext) {
        ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
    })
    h.Spin()
}

客户端

package main

import (
	"context"

	"github.com/cloudwego/hertz/pkg/app/client"
	"github.com/cloudwego/hertz/pkg/app/middlewares/client/sd"
	"github.com/cloudwego/hertz/pkg/common/config"
	"github.com/cloudwego/hertz/pkg/common/hlog"
	"github.com/hertz-contrib/registry/redis"
)

func main() {
    cli, err := client.NewClient()
    if err != nil {
        panic(err)
    }
    r := redis.NewRedisResolver("127.0.0.1:6379")
    cli.Use(sd.Discovery(r))
    for i := 0; i < 10; i++ {
        status, body, err := cli.Get(context.Background(), nil, "http://hertz.test.demo/ping", config.WithSD(true))
        if err != nil {
            hlog.Fatal(err)
        }
        hlog.Infof("HERTZ: code=%d,body=%s", status, string(body))
    }
}

配置

可自定义 redis 客户端以及服务端的配置,参考 go-redis 配置。

完整示例

完整用法示例详见 example


最后修改 April 18, 2023 : docs(wip): request context handler (36ea2d4)