diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 504f89d..1d01079 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: services: consul: - image: 'consul:latest' + image: 'hashicorp/consul:latest' ports: - '8500:8500' polaris: diff --git a/consul/Makefile b/consul/Makefile index 8c054e7..87e8aef 100644 --- a/consul/Makefile +++ b/consul/Makefile @@ -1,3 +1,3 @@ prepare: - docker pull consul:latest - docker run -d --name=dev-consul -e CONSUL_BIND_INTERFACE=eth0 -p 8500:8500 consul:latest + docker pull hashicorp/consul:latest + docker run -d --name=dev-consul -e CONSUL_BIND_INTERFACE=eth0 -p 8500:8500 hashicorp/consul:latest diff --git a/eureka/example/client/main.go b/eureka/example/basic/client/main.go similarity index 69% rename from eureka/example/client/main.go rename to eureka/example/basic/client/main.go index 9941f59..a6ec634 100644 --- a/eureka/example/client/main.go +++ b/eureka/example/basic/client/main.go @@ -17,6 +17,8 @@ package main import ( "context" + "github.com/cloudwego/hertz/pkg/protocol" + "github.com/cloudwego/hertz/pkg/app/client" "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd" "github.com/cloudwego/hertz/pkg/common/config" @@ -34,10 +36,19 @@ func main() { 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)) + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) if err != nil { hlog.Fatal(err) } - hlog.Infof("code=%d,body=%s", status, string(body)) + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) } } diff --git a/eureka/example/server/main.go b/eureka/example/basic/server/main.go similarity index 100% rename from eureka/example/server/main.go rename to eureka/example/basic/server/main.go diff --git a/eureka/example/custom_config_mutiple_server/client/main.go b/eureka/example/custom_config_mutiple_server/client/main.go new file mode 100644 index 0000000..5ad5b28 --- /dev/null +++ b/eureka/example/custom_config_mutiple_server/client/main.go @@ -0,0 +1,187 @@ +// Copyright 2022 CloudWeGo Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "encoding/json" + "net" + "time" + + "github.com/cloudwego/hertz/pkg/app/client" + "github.com/cloudwego/hertz/pkg/app/client/discovery" + "github.com/cloudwego/hertz/pkg/app/client/loadbalance" + "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/cloudwego/hertz/pkg/protocol" + "github.com/hertz-contrib/registry/eureka" + "github.com/hudl/fargo" +) + +var configPath = "paht/to/your/config/file.gcfg" + +type Message struct { + Message string `json:"message"` +} + +func main() { + // build a eureka resolver from custom config file + eurekaConfig, err := fargo.ReadConfig(configPath) + if err != nil { + hlog.Fatal(err) + } + r := eureka.NewEurekaResolverFromConfig(eurekaConfig) + + discoveryWithSD(r) + discoveryWithTag(r) + discoveryWithCustomizedAddr(r) + discoveryWithLoadBalanceOptions(r) + discoveryThenUsePostMethod(r) +} + +func discoveryWithSD(r discovery.Resolver) { + hlog.Info("simply discovery:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + cli.Use(sd.Discovery(r)) + for i := 0; i < 10; i++ { + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} + +func discoveryWithTag(r discovery.Resolver) { + hlog.Info("discovery with tag:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + cli.Use(sd.Discovery(r)) + + for i := 0; i < 10; i++ { + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true), config.WithTag("key1", "val1")) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} + +func discoveryWithCustomizedAddr(r discovery.Resolver) { + hlog.Info("discovery with customizedAddr:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + + cli.Use(sd.Discovery(r, sd.WithCustomizedAddrs(net.JoinHostPort("127.0.0.1", "5001")))) + for i := 0; i < 10; i++ { + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} + +func discoveryWithLoadBalanceOptions(r discovery.Resolver) { + hlog.Info("discovery with loadBalanceOptions:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + cli.Use(sd.Discovery(r, sd.WithLoadBalanceOptions(loadbalance.NewWeightedBalancer(), loadbalance.Options{ + RefreshInterval: 5 * time.Second, + ExpireInterval: 15 * time.Second, + }))) + for i := 0; i < 10; i++ { + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} + +func discoveryThenUsePostMethod(r discovery.Resolver) { + hlog.Info("discovery and use post method to send request:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + cli.Use(sd.Discovery(r)) + + for i := 0; i < 10; i++ { + // set request config、method、request uri. + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("POST") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + m := Message{Message: "hello"} + bytes, _ := json.Marshal(m) + // set body and content type + req.SetBody(bytes) + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err := cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} diff --git a/eureka/example/custom_config_mutiple_server/config.gcfg b/eureka/example/custom_config_mutiple_server/config.gcfg new file mode 100644 index 0000000..174d440 --- /dev/null +++ b/eureka/example/custom_config_mutiple_server/config.gcfg @@ -0,0 +1,5 @@ +[Eureka] +ServiceUrls = http://127.0.0.1:8761/eureka +ConnectTimeoutSeconds = 10 +Retries = 3 +PollIntervalSeconds = 30 diff --git a/eureka/example/custom_config_mutiple_server/server/main.go b/eureka/example/custom_config_mutiple_server/server/main.go new file mode 100644 index 0000000..523bb98 --- /dev/null +++ b/eureka/example/custom_config_mutiple_server/server/main.go @@ -0,0 +1,112 @@ +// Copyright 2022 CloudWeGo Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "net" + "sync" + "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/hlog" + "github.com/cloudwego/hertz/pkg/common/utils" + "github.com/cloudwego/hertz/pkg/protocol/consts" + "github.com/hertz-contrib/registry/eureka" + "github.com/hudl/fargo" +) + +var ( + wg sync.WaitGroup + configPath = "paht/to/your/config/file.gcfg" +) + +type Message struct { + Message string `json:"message"` +} + +func main() { + // custom config + eurekaConfig, err := fargo.ReadConfig(configPath) + if err != nil { + hlog.Fatal(err) + } + r := eureka.NewEurekaRegistryFromConfig(eurekaConfig, 40*time.Second) + + wg.Add(2) + go func() { + defer wg.Done() + addr := net.JoinHostPort("127.0.0.1", "5001") + + h := server.Default( + server.WithHostPorts(addr), + server.WithRegistry(r, ®istry.Info{ + ServiceName: "hertz.discovery.eureka", + Addr: utils.NewNetAddr("tcp", addr), + Weight: 10, + Tags: map[string]string{ + "key1": "val1", + }, + }), + ) + h.GET("/ping", func(c context.Context, ctx *app.RequestContext) { + ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"}) + }) + + h.POST("ping", func(c context.Context, ctx *app.RequestContext) { + m := Message{} + if err := ctx.Bind(&m); err != nil { + ctx.String(consts.StatusBadRequest, err.Error()) + return + } + ctx.JSON(consts.StatusOK, m) + }) + h.Spin() + }() + + go func() { + defer wg.Done() + addr := net.JoinHostPort("127.0.0.1", "5002") + + h := server.Default( + server.WithHostPorts(addr), + server.WithRegistry(r, ®istry.Info{ + ServiceName: "hertz.discovery.eureka", + Addr: utils.NewNetAddr("tcp", addr), + Weight: 10, + Tags: map[string]string{ + "key1": "val1", + }, + }), + ) + h.GET("/ping", func(c context.Context, ctx *app.RequestContext) { + ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"}) + }) + + h.POST("ping", func(c context.Context, ctx *app.RequestContext) { + m := Message{} + if err := ctx.Bind(&m); err != nil { + ctx.String(consts.StatusBadRequest, err.Error()) + return + } + ctx.JSON(consts.StatusOK, m) + }) + h.Spin() + }() + + wg.Wait() +} diff --git a/eureka/example/custom_conn_mutiple_server/client/main.go b/eureka/example/custom_conn_mutiple_server/client/main.go new file mode 100644 index 0000000..3841202 --- /dev/null +++ b/eureka/example/custom_conn_mutiple_server/client/main.go @@ -0,0 +1,187 @@ +// Copyright 2022 CloudWeGo Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "encoding/json" + "net" + "time" + + "github.com/cloudwego/hertz/pkg/app/client" + "github.com/cloudwego/hertz/pkg/app/client/discovery" + "github.com/cloudwego/hertz/pkg/app/client/loadbalance" + "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/cloudwego/hertz/pkg/protocol" + "github.com/hertz-contrib/registry/eureka" + "github.com/hudl/fargo" +) + +type Message struct { + Message string `json:"message"` +} + +func main() { + // build a eureka resolver from custom conn + eurekaConn := fargo.EurekaConnection{ + ServiceUrls: []string{"http://127.0.0.1:8761/eureka"}, + Timeout: 10 * time.Second, + Retries: 3, + PollInterval: 30 * time.Second, + } + r := eureka.NewEurekaResolverFromConn(eurekaConn) + + discoveryWithSD(r) + discoveryWithTag(r) + discoveryWithCustomizedAddr(r) + discoveryWithLoadBalanceOptions(r) + discoveryThenUsePostMethod(r) +} + +func discoveryWithSD(r discovery.Resolver) { + hlog.Info("simply discovery:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + cli.Use(sd.Discovery(r)) + for i := 0; i < 10; i++ { + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} + +func discoveryWithTag(r discovery.Resolver) { + hlog.Info("discovery with tag:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + cli.Use(sd.Discovery(r)) + + for i := 0; i < 10; i++ { + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true), config.WithTag("key1", "val1")) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} + +func discoveryWithCustomizedAddr(r discovery.Resolver) { + hlog.Info("discovery with customizedAddr:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + + cli.Use(sd.Discovery(r, sd.WithCustomizedAddrs(net.JoinHostPort("127.0.0.1", "5001")))) + for i := 0; i < 10; i++ { + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} + +func discoveryWithLoadBalanceOptions(r discovery.Resolver) { + hlog.Info("discovery with loadBalanceOptions:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + cli.Use(sd.Discovery(r, sd.WithLoadBalanceOptions(loadbalance.NewWeightedBalancer(), loadbalance.Options{ + RefreshInterval: 5 * time.Second, + ExpireInterval: 15 * time.Second, + }))) + for i := 0; i < 10; i++ { + // set request method、config、request uri + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("GET") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + // set content type + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err = cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} + +func discoveryThenUsePostMethod(r discovery.Resolver) { + hlog.Info("discovery and use post method to send request:") + cli, err := client.NewClient() + if err != nil { + panic(err) + } + cli.Use(sd.Discovery(r)) + + for i := 0; i < 10; i++ { + // set request config、method、request uri. + req := protocol.AcquireRequest() + req.SetOptions(config.WithSD(true)) + req.SetMethod("POST") + req.SetRequestURI("http://hertz.discovery.eureka/ping") + m := Message{Message: "hello"} + bytes, _ := json.Marshal(m) + // set body and content type + req.SetBody(bytes) + req.Header.SetContentTypeBytes([]byte("application/json")) + resp := protocol.AcquireResponse() + // send request + err := cli.Do(context.Background(), req, resp) + if err != nil { + hlog.Fatal(err) + } + hlog.Infof("code=%d,body=%s", resp.StatusCode(), string(resp.Body())) + } +} diff --git a/eureka/example/custom_conn_mutiple_server/server/main.go b/eureka/example/custom_conn_mutiple_server/server/main.go new file mode 100644 index 0000000..babbca9 --- /dev/null +++ b/eureka/example/custom_conn_mutiple_server/server/main.go @@ -0,0 +1,110 @@ +// Copyright 2022 CloudWeGo Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "net" + "sync" + "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/eureka" + "github.com/hudl/fargo" +) + +var wg sync.WaitGroup + +type Message struct { + Message string `json:"message"` +} + +func main() { + // custom eurekaConn + conn := fargo.EurekaConnection{ + ServiceUrls: []string{"http://127.0.0.1:8761/eureka"}, + Timeout: 10 * time.Second, + Retries: 3, + PollInterval: 30 * time.Second, + } + r := eureka.NewEurekaRegistryFromConn(conn, 40*time.Second) + + wg.Add(2) + go func() { + defer wg.Done() + addr := net.JoinHostPort("127.0.0.1", "5001") + + h := server.Default( + server.WithHostPorts(addr), + server.WithRegistry(r, ®istry.Info{ + ServiceName: "hertz.discovery.eureka", + Addr: utils.NewNetAddr("tcp", addr), + Weight: 10, + Tags: map[string]string{ + "key1": "val1", + }, + }), + ) + h.GET("/ping", func(c context.Context, ctx *app.RequestContext) { + ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"}) + }) + + h.POST("ping", func(c context.Context, ctx *app.RequestContext) { + m := Message{} + if err := ctx.Bind(&m); err != nil { + ctx.String(consts.StatusBadRequest, err.Error()) + return + } + ctx.JSON(consts.StatusOK, m) + }) + h.Spin() + }() + + go func() { + defer wg.Done() + addr := net.JoinHostPort("127.0.0.1", "5002") + + h := server.Default( + server.WithHostPorts(addr), + server.WithRegistry(r, ®istry.Info{ + ServiceName: "hertz.discovery.eureka", + Addr: utils.NewNetAddr("tcp", addr), + Weight: 10, + Tags: map[string]string{ + "key1": "val1", + }, + }), + ) + h.GET("/ping", func(c context.Context, ctx *app.RequestContext) { + ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"}) + }) + + h.POST("ping", func(c context.Context, ctx *app.RequestContext) { + m := Message{} + if err := ctx.Bind(&m); err != nil { + ctx.String(consts.StatusBadRequest, err.Error()) + return + } + ctx.JSON(consts.StatusOK, m) + }) + h.Spin() + }() + + wg.Wait() +}