generated from cloudwego/.github
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
93a584e
commit f596224
Showing
19 changed files
with
1,704 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,4 +27,3 @@ output/* | |
|
||
# Vscode files | ||
.vscode | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,187 @@ | ||
# .github | ||
# .github | ||
example中为使用示例,完整example代码地址:https://github.com/zhu-mi-shan/optionloader_example | ||
使用该组件需要安装etcd。 | ||
etcd中存储的配置文件例子如下: | ||
server: | ||
``` | ||
json_data='{"ServerBasicInfo": {"ServiceName": "echo_server_service","Method": "method1","Tags": {"tag1": "v1","tag2": "v2"}},"ServiceAddr": [{"Network": "tcd","Address": "127.0.0.1:8889"}],"MuxTransport": true,"MyConfig":{"configOne": "This is configOne","configTwo": ["Welcome","to","configTwo","!"]}}' | ||
etcdctl put "/KitexConfig/echo_server_service" "$(echo -n $json_data)" | ||
``` | ||
client: | ||
``` | ||
json_data='{"ClientBasicInfo":{"ServiceName": "echo_client_service","Method": "method1","Tags": {"tag1": "v1","tag2": "v2"}},"HostPorts": ["0.0.0.0:8888","0.0.0.0:8889"],"DestService": "echo_server_service","Protocol": "HTTP","Connection":{"Method": "LongConnection","LongConnection":{"MinIdlePerAddress": 1,"MaxIdlePerAddress": 10,"MaxIdleGlobal": 100,"MaxIdleTimeout": "1m"},"MuxConnection":{"ConnNum": 3}},"MyConfig":{"configOne": "This is configOne","configTwo": ["Welcome","to","configTwo","!"]}}' | ||
etcdctl put "/KitexConfig/echo_client_service/echo_server_service" "$(echo -n $json_data)" | ||
``` | ||
服务端,客户端均支持自定义新的配置文件结构config,自定义新的数据读取方式decoder, 以及新的解析option方法translator | ||
server端示例: | ||
``` | ||
const ( | ||
serverServiceName = "echo_server_service" | ||
) | ||
// 用户可以自定义读取数据的类型,要求通过Decode返回一个字节流 | ||
type myConfigParser struct { | ||
} | ||
func (p *myConfigParser) Decode(data []byte, config *etcdServer.EtcdConfig) error { | ||
return json.Unmarshal(data, config) | ||
} | ||
// 用户可以自定义新增Config文件结构,并且默认的的Config文件结构仍然存在 | ||
type myConfig struct { | ||
ConfigOne *string `mapstructure:"configOne"` | ||
ConfigTwo []string `mapstructure:"configTwo"` | ||
} | ||
func (r *myConfig) String() string { | ||
var output string | ||
if r.ConfigOne != nil { | ||
output += fmt.Sprintf("ConfigOne: %s\n", *r.ConfigOne) | ||
} | ||
if r.ConfigTwo != nil { | ||
output += fmt.Sprintf("ConfigTwo: %v\n", r.ConfigTwo) | ||
} | ||
return output | ||
} | ||
// 用户可自定义Translator,用于将myConfig解析成Options | ||
func myTranslator(config *etcdServer.EtcdConfig) ([]kitexserver.Option, error) { | ||
c := config.MyConfig | ||
var opts []kitexserver.Option | ||
//具体处理逻辑 | ||
_ = opts | ||
fmt.Println("myConfigTranslator run! myConfig:" + c.String()) | ||
return opts, nil | ||
} | ||
func main() { | ||
readerOptions := etcdServer.ReaderOptions{ | ||
ConfigParser: &myConfigParser{}, | ||
MyConfig: &myConfig{}, | ||
} | ||
utils.Printpath() | ||
reader, err := etcdServer.NewReader(readerOptions) | ||
//reader, err := etcdClient.NewReader(etcdClient.ReaderOptions{})//使用默认值时的 | ||
if err != nil { | ||
log.Fatal(err) | ||
return | ||
} | ||
myTranslators := []etcdServer.Translator{myTranslator} | ||
loader, err := etcdServer.NewLoader(serverServiceName, reader, myTranslators...) | ||
if err != nil { | ||
log.Fatal(err) | ||
return | ||
} | ||
err = loader.Load() | ||
if err != nil { | ||
log.Fatal(err) | ||
return | ||
} | ||
fmt.Println("Options: ", loader.GetSuite().Options()) | ||
config, _ := reader.GetConfig() | ||
fmt.Print("Config:", config.String()) | ||
svr := example.NewServer(new(TestServiceImpl), kitexserver.WithSuite(loader.GetSuite())) | ||
err = svr.Run() | ||
if err != nil { | ||
log.Println(err.Error()) | ||
} | ||
} | ||
``` | ||
client端示例: | ||
``` | ||
const ( | ||
serverServiceName = "echo_server_service" | ||
clientServiceName = "echo_client_service" | ||
) | ||
// 用户可以自定义读取数据的类型,要求通过Decode返回一个字节流 | ||
type myConfigParser struct { | ||
} | ||
func (p *myConfigParser) Decode(data []byte, config *etcdClient.EtcdConfig) error { | ||
return json.Unmarshal(data, config) | ||
} | ||
// 用户可以自定义新增Config文件结构,并且默认的的Config文件结构仍然存在 | ||
type myConfig struct { | ||
ConfigOne *string `mapstructure:"configOne"` | ||
ConfigTwo []string `mapstructure:"configTwo"` | ||
} | ||
func (r *myConfig) String() string { | ||
var output string | ||
if r.ConfigOne != nil { | ||
output += fmt.Sprintf("ConfigOne: %s\n", *r.ConfigOne) | ||
} | ||
if r.ConfigTwo != nil { | ||
output += fmt.Sprintf("ConfigTwo: %v\n", r.ConfigTwo) | ||
} | ||
return output | ||
} | ||
// 用户可自定义Translator,用于将myConfig解析成Options | ||
func myTranslator(config *etcdClient.EtcdConfig) ([]kitexclient.Option, error) { | ||
c := config.MyConfig | ||
if c == nil { | ||
return nil, nil | ||
} | ||
opts := []kitexclient.Option{} | ||
//具体处理逻辑 | ||
_ = opts | ||
fmt.Println("myConfigTranslator run! myConfig:" + c.String()) | ||
return opts, nil | ||
} | ||
func main() { | ||
readerOptions := etcdClient.ReaderOptions{ | ||
ConfigParser: &myConfigParser{}, | ||
MyConfig: &myConfig{}, | ||
} | ||
utils.Printpath() | ||
reader, err := etcdClient.NewReader(readerOptions) | ||
//reader, err := etcdClient.NewReader(etcdClient.ReaderOptions{})//使用默认值时的 | ||
if err != nil { | ||
log.Fatal(err) | ||
return | ||
} | ||
myTranslators := []etcdClient.Translator{myTranslator} | ||
loader, err := etcdClient.NewLoader(clientServiceName, serverServiceName, reader, myTranslators...) | ||
if err != nil { | ||
log.Fatal(err) | ||
return | ||
} | ||
err = loader.Load() | ||
if err != nil { | ||
log.Fatal(err) | ||
return | ||
} | ||
fmt.Println("Options: ", loader.GetSuite().Options()) | ||
config, _ := reader.GetConfig() | ||
fmt.Print("Config:", config.String()) | ||
c, err := example.NewClient("echo_server_service", kitexclient.WithSuite(loader.GetSuite())) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
req := examplegen.Req{ | ||
Id: 123, | ||
} | ||
resp, err := c.Test(context.Background(), &req) | ||
if err != nil { | ||
log.Fatal(err) | ||
return | ||
} | ||
fmt.Println(resp) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package etcdclient | ||
|
||
import ( | ||
clientv3 "go.etcd.io/etcd/client/v3" | ||
"text/template" | ||
"time" | ||
) | ||
|
||
// Options etcd config options. All the fields have default value. | ||
type ReaderOptions struct { | ||
Node []string | ||
Prefix string | ||
PathFormat string | ||
Timeout time.Duration | ||
ConfigParser ConfigParser | ||
MyConfig Config | ||
} | ||
|
||
func NewReader(opts ReaderOptions) (*EtcdReader, error) { | ||
if opts.Node == nil { | ||
opts.Node = []string{EtcdDefaultNode} | ||
} | ||
if opts.ConfigParser == nil { | ||
opts.ConfigParser = &defaultParser{} | ||
} | ||
if opts.Prefix == "" { | ||
opts.Prefix = EtcdDefaultConfigPrefix | ||
} | ||
if opts.Timeout == 0 { | ||
opts.Timeout = EtcdDefaultTimeout | ||
} | ||
if opts.PathFormat == "" { | ||
opts.PathFormat = EtcdClientDefaultPath | ||
} | ||
etcdClient, err := clientv3.New(clientv3.Config{ | ||
Endpoints: opts.Node, | ||
DialTimeout: opts.Timeout, | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
clientPathTemplate, err := template.New("clientName").Parse(opts.PathFormat) | ||
if err != nil { | ||
return nil, err | ||
} | ||
r := &EtcdReader{ | ||
config: &EtcdConfig{MyConfig: opts.MyConfig}, //配置文件读出结果 | ||
parser: opts.ConfigParser, //配置文件解码器 | ||
etcdClient: etcdClient, | ||
prefix: opts.Prefix, | ||
clientPathTemplate: clientPathTemplate, | ||
etcdTimeout: opts.Timeout, | ||
} | ||
|
||
return r, nil | ||
} | ||
|
||
func NewLoader(clientServiceName, serverServiceName string, reader *EtcdReader, myTranslators ...Translator) (*EtcdLoader, error) { | ||
|
||
// Register all translators | ||
translators := []Translator{ | ||
basicInfoTranslator, | ||
hostPortsTranslator, | ||
destServiceTranslator, | ||
protocolTranslator, | ||
connectionTranslator, | ||
} | ||
|
||
if len(myTranslators) != 0 { | ||
translators = append(translators, myTranslators...) | ||
} | ||
|
||
loader := &EtcdLoader{ | ||
translators: translators, | ||
ClientServiceName: clientServiceName, | ||
ServerServiceName: serverServiceName, | ||
reader: reader, | ||
} | ||
|
||
return loader, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package etcdclient | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
type ConfigParser interface { | ||
Decode(data []byte, config *EtcdConfig) error | ||
} | ||
|
||
type defaultParser struct { | ||
} | ||
|
||
func (p *defaultParser) Decode(data []byte, config *EtcdConfig) error { | ||
return json.Unmarshal(data, config) | ||
} | ||
|
||
type Config interface { | ||
String() string | ||
} | ||
|
||
type EtcdConfig struct { | ||
ClientBasicInfo *EndpointBasicInfo `mapstructure:"ClientBasicInfo"` | ||
HostPorts []string `mapstructure:"HostPorts"` | ||
DestService *string `mapstructure:"DestService"` | ||
Protocol *string `mapstructure:"Protocol"` | ||
Connection *Connection `mapstructure:"Connection"` | ||
MyConfig Config `mapstructure:"MyConfig"` | ||
} | ||
|
||
func (c *EtcdConfig) String() string { | ||
var builder strings.Builder | ||
|
||
if c.ClientBasicInfo != nil { | ||
builder.WriteString(fmt.Sprintf("ClientBasicInfo: %v\n", *c.ClientBasicInfo)) | ||
} | ||
|
||
if c.HostPorts != nil { | ||
builder.WriteString(fmt.Sprintf("HostPorts: %v\n", c.HostPorts)) | ||
} | ||
|
||
if c.DestService != nil { | ||
builder.WriteString(fmt.Sprintf("DestService: %v\n", *c.DestService)) | ||
} | ||
|
||
if c.Protocol != nil { | ||
builder.WriteString(fmt.Sprintf("Protocol: %v\n", *c.Protocol)) | ||
} | ||
|
||
if c.Connection != nil { | ||
builder.WriteString(fmt.Sprintf("Connection: %v\n", *c.Connection)) | ||
} | ||
|
||
if c.MyConfig != nil { | ||
builder.WriteString(c.MyConfig.String()) | ||
} | ||
|
||
return builder.String() | ||
} | ||
|
||
type EndpointBasicInfo struct { | ||
ServiceName string `mapstructure:"ServiceName"` | ||
Method string `mapstructure:"Method"` | ||
Tags map[string]string `mapstructure:"Tags"` | ||
} | ||
|
||
type IdleConfig struct { | ||
MinIdlePerAddress int `mapstructure:"MinIdlePerAddress"` | ||
MaxIdlePerAddress int `mapstructure:"MaxIdlePerAddress"` | ||
MaxIdleGlobal int `mapstructure:"MaxIdleGlobal"` | ||
MaxIdleTimeout string `mapstructure:"MaxIdleTimeout"` | ||
} | ||
type MuxConnection struct { | ||
ConnNum int `mapstructure:"ConnNum"` | ||
} | ||
|
||
type Connection struct { | ||
Method string `mapstructure:"Method"` | ||
LongConnection IdleConfig `mapstructure:"LongConnection"` | ||
MuxConnection MuxConnection `mapstructure:"MuxConnection"` | ||
} |
Oops, something went wrong.