zookeeper as config center for service governance.
package main
import (
"context"
"log"
"github.com/cloudwego/kitex-examples/kitex_gen/api"
"github.com/cloudwego/kitex-examples/kitex_gen/api/echo"
"github.com/cloudwego/kitex/pkg/klog"
"github.com/cloudwego/kitex/pkg/rpcinfo"
"github.com/cloudwego/kitex/server"
zookeeperServer "github.com/kitex-contrib/config-zookeeper/server"
"github.com/kitex-contrib/config-zookeeper/zookeeper"
)
var _ api.Echo = &EchoImpl{}
// EchoImpl implements the last service interface defined in the IDL.
type EchoImpl struct{}
// Echo implements the Echo interface.
func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Response, err error) {
klog.Info("echo called")
return &api.Response{Message: req.Message}, nil
}
func main() {
zookeeperClient, err := zookeeper.NewClient(zookeeper.Options{})
if err != nil {
panic(err)
}
serviceName := "ServiceName" // your server-side service name
svr := echo.NewServer(
new(EchoImpl),
server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}),
server.WithSuite(zookeeperServer.NewSuite(serviceName, zookeeperClient)),
)
if err := svr.Run(); err != nil {
log.Println("server stopped with error:", err)
} else {
log.Println("server stopped")
}
}
package main
import (
"context"
"log"
"time"
"github.com/cloudwego/kitex-examples/kitex_gen/api"
"github.com/cloudwego/kitex-examples/kitex_gen/api/echo"
"github.com/cloudwego/kitex/client"
"github.com/cloudwego/kitex/pkg/klog"
zookeeperclient "github.com/kitex-contrib/config-zookeeper/client"
"github.com/kitex-contrib/config-zookeeper/utils"
"github.com/kitex-contrib/config-zookeeper/zookeeper"
)
type configLog struct{}
func (cl *configLog) Apply(opt *utils.Options) {
fn := func(k *zookeeper.ConfigParam) {
klog.Infof("zookeeper config %v", k)
}
opt.ZookeeperCustomFunctions = append(opt.ZookeeperCustomFunctions, fn)
}
func main() {
zookeeperClient, err := zookeeper.NewClient(zookeeper.Options{})
if err != nil {
panic(err)
}
cl := configLog{}
serviceName := "ServiceName" // your server-side service name
clientName := "ClientName" // your client-side service name
client, err := echo.NewClient(
serviceName,
client.WithHostPorts("0.0.0.0:8888"),
client.WithSuite(zookeeperclient.NewSuite(serviceName, clientName, zookeeperClient, &cl)),
)
if err != nil {
log.Fatal(err)
}
for {
req := &api.Request{Message: "my request"}
resp, err := client.Echo(context.Background(), req)
if err != nil {
klog.Errorf("take request error: %v", err)
} else {
klog.Infof("receive response %v", resp)
}
time.Sleep(time.Second * 10)
}
}
The client is initialized according to the parameters of Options
and connects to the zookeeper server. After the connection is established, the suite will listen to the corresponding node according to Path
and ServerPathFormat
orClientPathFormat
to updates its own policy dynamically. See the Options
variables below for specific parameters.
Provide the mechanism to custom the zookeeper parameter Path
.
type ConfigParam struct {
Prefix string
Path string
}
The final Path is param.Prefix + "/" + param.Path
Variable Name | Default Value | Introduction |
---|---|---|
Servers | 127.0.0.1:2181 | Zookeeper server nodes |
Prefix | /KitexConfig | The prefix of Zookeeper |
ClientPathFormat | {{.ClientServiceName}}/{{.ServerServiceName}}/{{.Category}} | Use go template syntax rendering to generate the appropriate ID, and use ClientServiceName ServiceName Category three metadata that can be customised |
ServerPathFormat | {{.Category}} | Use go template syntax rendering to generate the appropriate ID, and use ServiceName Category two metadatas that can be customised |
ConfigParser | defaultConfigParser | The default is the parser that parses json |
The configPath and configPrefix in the following example use default values, the service name is
ServiceName
and the client name isClientName
.
Currently, current limiting only supports the server side, so ClientServiceName is empty.
Variable | Introduction |
---|---|
connection_limit | Maximum concurrent connections |
qps_limit | Maximum request number every 100ms |
Example:
configPath: /KitexConfig/ServiceName/limit
{
"connection_limit": 100,
"qps_limit": 2000
}
Note:
- The granularity of the current limit configuration is server global, regardless of client or method.
- Not configured or value is 0 means not enabled.
- connection_limit and qps_limit can be configured independently, e.g. connection_limit = 100, qps_limit = 0
Variable | Introduction |
---|---|
type | 0: failure_policy 1: backup_policy |
failure_policy.backoff_policy | Can only be set one of fixed none random |
Example:
configPath: /KitexConfig/ClientName/ServiceName/retry
{
"*": {
"enable": true,
"type": 0,
"failure_policy": {
"stop_policy": {
"max_retry_times": 3,
"max_duration_ms": 2000,
"cb_policy": {
"error_rate": 0.3
}
},
"backoff_policy": {
"backoff_type": "fixed",
"cfg_items": {
"fix_ms": 50
}
},
"retry_same_node": false
}
},
"echo": {
"enable": true,
"type": 1,
"backup_policy": {
"retry_delay_ms": 100,
"retry_same_node": false,
"stop_policy": {
"max_retry_times": 2,
"max_duration_ms": 300,
"cb_policy": {
"error_rate": 0.2
}
}
}
}
}
Note: retry.Container has built-in support for specifying the default configuration using the *
wildcard (see the getRetryer method for details).
Example:
configPath: /KitexConfig/ClientName/ServiceName/rpc_timeout
{
"*": {
"conn_timeout_ms": 100,
"rpc_timeout_ms": 3000
},
"echo": {
"conn_timeout_ms": 50,
"rpc_timeout_ms": 1000
}
}
Note: The circuit breaker implementation of kitex does not currently support changing the global default configuration (see initServiceCB for details).
Variable | Introduction |
---|---|
min_sample | Minimum statistical sample number |
Example:
The echo method uses the following configuration (0.3, 100) and other methods use the global default configuration (0.5, 200)
configPath: /KitexConfig/ClientName/ServiceName/circuit_break
{
"echo": {
"enable": true,
"err_rate": 0.3,
"min_sample": 100
}
}
Variable | Introduction |
---|---|
enable | Whether to enable degradation |
percentage | The percentage of dropped requests |
Example:
configPath: /KitexConfig/ClientName/ServiceName/degradation
{
"enable": true,
"percentage": 30
}
Note: Degradation is not enabled by default.
Refer to example for more usage.
In ZooKeeper, when a node is created, its parent must exist.
This Package use https://github.com/go-zookeeper/zk
maintained by: jiuxia211