etcd

package module
v0.0.0-...-d07355f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 17, 2024 License: Apache-2.0 Imports: 16 Imported by: 3

README

etcd (This is a community driven project)

Etcd as service discovery for Hertz.

How to use?

Server

example/server/main.go

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/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()
}
Client

example/client/main.go

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/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))
	}
}

How to run example?

run docker
make prepare
Run etcd cluster
make prepare-cluster
run server
go run ./example/server/main.go
run client
go run ./example/client/main.go
/hertz.test.demo/127.0.0.1:8888:{"Weight":10,"Tags":null}
2022/08/23 21:11:29.109063 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.109268 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.109377 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.109523 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.109887 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.112675 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.113081 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.114662 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.114854 main.go:57: [Info] code=200,body={"ping":"pong2"}
2022/08/23 21:11:29.115257 main.go:57: [Info] code=200,body={"ping":"pong2"}

Authentication

Server
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/etcd"
)

func main() {
	r, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"}, etcd.WithAuthOpt("root", "123456"))
	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()
}
Client
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/etcd"
)

func main() {
	cli, err := client.NewClient()
	if err != nil {
		panic(err)
	}
	r, err := etcd.NewEtcdResolver([]string{"127.0.0.1:2379"}, etcd.WithAuthOpt("root", "123456"))
	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))
	}
}

Retry

After the service is registered to ETCD, it will regularly check the status of the service. If any abnormal status is found, it will try to register the service again. observeDelay is the delay time for checking the service status under normal conditions, and retryDelay is the delay time for attempting to register the service after disconnecting.

Default Retry Config
Config Name Default Value Description
WithMaxAttemptTimes 5 Used to set the maximum number of attempts, if 0, it means infinite attempts
WithObserveDelay 30 * time.Second Used to set the delay time for checking service status under normal connection conditions
WithRetryDelay 10 * time.Second Used to set the retry delay time after disconnecting
Example
package main

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/etcd"
)

func main() {
	r, _ := etcd.NewEtcdRegistry(
		[]string{"127.0.0.1:2379"},
		etcd.WithMaxAttemptTimes(10),
		etcd.WithObserveDelay(20*time.Second),
		etcd.WithRetryDelay(5*time.Second),
	)

	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()
}

How to Dynamically specify ip and port

To dynamically specify an IP and port, one should first set the environment variables HERTZ_IP_TO_REGISTRY and HERTZ_PORT_TO_REGISTRY. If these variables are not set, the system defaults to using the service's listening IP and port. Notably, if the service's listening IP is either not set or set to "::", the system will automatically retrieve and use the machine's IPV4 address.

Compatibility

Compatible with server (3.0.0 - 3.5.4) etcd-clientv3 see

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewEtcdRegistry

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

NewEtcdRegistry creates a etcd based registry.

func NewEtcdResolver

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

NewEtcdResolver creates a etcd based resolver.

Types

type Option

type Option func(o *option)

func WithAuthOpt

func WithAuthOpt(username, password string) Option

WithAuthOpt returns an option that authentication by username and password.

func WithMaxAttemptTimes

func WithMaxAttemptTimes(maxAttemptTimes uint) Option

WithMaxAttemptTimes sets the maximum number of call attempt times, including the initial call

func WithObserveDelay

func WithObserveDelay(observeDelay time.Duration) Option

WithObserveDelay sets the delay time for checking the service status under normal conditions

func WithRetryDelay

func WithRetryDelay(t time.Duration) Option

WithRetryDelay sets the delay time of retry

func WithTLSOpt

func WithTLSOpt(certFile, keyFile, caFile string) Option

WithTLSOpt returns a option that authentication by tls/ssl.

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL