generated from cloudwego/.github
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* feat: support local file config of client and server * del: .DS_Store * add: license header * fix: staticcheck error report * fix: use NewRetryContainerWithPercentageLimit to create retry container * docs: correct sentence placement * fix: use individual module in example folder * feat: merge ClientWatcher and ServerWatcher into ConfigWatcher * fix: update error judgment of utils.PathExists() * docs: update README.md * chore: move example folder to kitex-contrib/example * fix: set alias for client/server to avoid same package name * fix: delete useless log * fix: add recover for new goroutines to avoid crashing * add: comments for exported symbols * del: monitor/key.go * feat: separating filewatch and configmonitor * docs: update README.md * fix: README.md usage import package error * add: monitor test cases * test: add entire progress test * fix: add mutex for start/stop file watching * fix: staticcheck error report * fix: multiple clients can listen to the same key without affecting each other * delete: remove the gomock module and use self-made simple mock instead * feat: upgrade required module version * fix: remove redundant golang versions in workflow tests * add: use example of this lib * fix: README_CN.md spell error * chore: README add supported file types * fix: panic when type assertion fails at runtime * chore: add log while callback is nil * fix: README.md lib name error * chore: add licenses --------- Co-authored-by: kinggo <lilong.21@bytedance.com>
- Loading branch information
1 parent
d1b4643
commit 90fb161
Showing
30 changed files
with
4,904 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
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,335 @@ | ||
# .github | ||
# config-file (*This is a community driven project*) | ||
|
||
[中文](README_CN.md) | ||
|
||
Read, load, and listen to local configuration files | ||
|
||
## Usage | ||
|
||
### Supported file types | ||
|
||
| json | yaml | | ||
| --- | --- | | ||
| ✔ | ✔ | | ||
|
||
### Basic | ||
|
||
#### Server | ||
|
||
```go | ||
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" | ||
kitexserver "github.com/cloudwego/kitex/server" | ||
"github.com/kitex-contrib/config-file/filewatcher" | ||
fileserver "github.com/kitex-contrib/config-file/server" | ||
) | ||
|
||
var _ api.Echo = &EchoImpl{} | ||
|
||
const ( | ||
filepath = "kitex_server.json" | ||
key = "ServiceName" | ||
serviceName = "ServiceName" | ||
) | ||
|
||
// 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() { | ||
klog.SetLevel(klog.LevelDebug) | ||
|
||
// create a file watcher object | ||
fw, err := filewatcher.NewFileWatcher(filepath) | ||
if err != nil { | ||
panic(err) | ||
} | ||
// start watching file changes | ||
if err = fw.StartWatching(); err != nil { | ||
panic(err) | ||
} | ||
defer fw.StopWatching() | ||
|
||
svr := echo.NewServer( | ||
new(EchoImpl), | ||
kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), | ||
kitexserver.WithSuite(fileserver.NewSuite(key, fw)), // add watcher | ||
) | ||
if err := svr.Run(); err != nil { | ||
log.Println("server stopped with error:", err) | ||
} else { | ||
log.Println("server stopped") | ||
} | ||
} | ||
``` | ||
|
||
#### Client | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"context" | ||
"log" | ||
"os" | ||
"os/signal" | ||
"time" | ||
|
||
"github.com/cloudwego/kitex-examples/kitex_gen/api" | ||
"github.com/cloudwego/kitex-examples/kitex_gen/api/echo" | ||
kitexclient "github.com/cloudwego/kitex/client" | ||
"github.com/cloudwego/kitex/pkg/klog" | ||
fileclient "github.com/kitex-contrib/config-file/client" | ||
"github.com/kitex-contrib/config-file/filewatcher" | ||
) | ||
|
||
const ( | ||
filepath = "kitex_client.json" | ||
key = "ClientName/ServiceName" | ||
serviceName = "ServiceName" | ||
clientName = "ClientName" | ||
) | ||
|
||
func main() { | ||
klog.SetLevel(klog.LevelDebug) | ||
|
||
// create a file watcher object | ||
fw, err := filewatcher.NewFileWatcher(filepath) | ||
if err != nil { | ||
panic(err) | ||
} | ||
// start watching file changes | ||
if err = fw.StartWatching(); err != nil { | ||
panic(err) | ||
} | ||
|
||
go func() { | ||
sig := make(chan os.Signal, 1) | ||
signal.Notify(sig, os.Interrupt, os.Kill) | ||
<-sig | ||
fw.StopWatching() | ||
os.Exit(1) | ||
}() | ||
|
||
client, err := echo.NewClient( | ||
serviceName, | ||
kitexclient.WithHostPorts("0.0.0.0:8888"), | ||
kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw)), | ||
) | ||
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) | ||
} | ||
} | ||
|
||
``` | ||
|
||
#### Governance Policy | ||
> The service name is `ServiceName` and the client name is `ClientName`. | ||
##### Rate Limit Category=limit | ||
> Currently, current limiting only supports the server side, so ClientServiceName is empty. | ||
[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/limiter/item_limiter.go#L33) | ||
|
||
|Variable|Introduction| | ||
|----|----| | ||
|connection_limit| Maximum concurrent connections | | ||
|qps_limit| Maximum request number every 100ms | | ||
|
||
Example: | ||
```json | ||
{ | ||
"ServiceName": { | ||
"limit": { | ||
"connection_limit": 300, | ||
"qps_limit": 200 | ||
} | ||
} | ||
} | ||
``` | ||
|
||
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 | ||
|
||
##### Retry Policy Category=retry | ||
[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/retry/policy.go#L63) | ||
|
||
|Variable|Introduction| | ||
|----|----| | ||
|type| 0: failure_policy 1: backup_policy| | ||
|failure_policy.backoff_policy| Can only be set one of `fixed` `none` `random` | | ||
|
||
Example: | ||
```json | ||
{ | ||
"ClientName/ServiceName": { | ||
"retry": { | ||
"*": { | ||
"enable": true, | ||
"type": 0, | ||
"failure_policy": { | ||
"stop_policy": { | ||
"max_retry_times": 3, | ||
"max_duration_ms": 2000, | ||
"cb_policy": { | ||
"error_rate": 0.2 | ||
} | ||
} | ||
} | ||
}, | ||
"Echo": { | ||
"enable": true, | ||
"type": 1, | ||
"backup_policy": { | ||
"retry_delay_ms": 200, | ||
"stop_policy": { | ||
"max_retry_times": 2, | ||
"max_duration_ms": 1000, | ||
"cb_policy": { | ||
"error_rate": 0.3 | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
Note: retry.Container has built-in support for specifying the default configuration using the `*` wildcard (see the [getRetryer](https://github.com/cloudwego/kitex/blob/v0.5.1/pkg/retry/retryer.go#L240) method for details). | ||
|
||
##### RPC Timeout Category=rpc_timeout | ||
|
||
[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/rpctimeout/item_rpc_timeout.go#L42) | ||
|
||
Example: | ||
```json | ||
{ | ||
"ClientName/ServiceName": { | ||
"timeout": { | ||
"*": { | ||
"conn_timeout_ms": 100, | ||
"rpc_timeout_ms": 2000 | ||
}, | ||
"Pay": { | ||
"conn_timeout_ms": 50, | ||
"rpc_timeout_ms": 1000 | ||
} | ||
}, | ||
} | ||
} | ||
``` | ||
|
||
##### Circuit Break: Category=circuit_break | ||
|
||
[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/circuitbreak/item_circuit_breaker.go#L30) | ||
|
||
|Variable|Introduction| | ||
|----|----| | ||
|min_sample| Minimum statistical sample number| | ||
|
||
The echo method uses the following configuration (0.3, 100) and other methods use the global default configuration (0.5, 200) | ||
|
||
Example: | ||
```json | ||
|
||
{ | ||
"ClientName/ServiceName": { | ||
"circuitbreaker": { | ||
"Echo": { | ||
"enable": true, | ||
"err_rate": 0.3, | ||
"min_sample": 100 | ||
} | ||
}, | ||
} | ||
} | ||
``` | ||
|
||
Note: The circuit breaker implementation of kitex does not currently support changing the global default configuration (see [initServiceCB](https://github.com/cloudwego/kitex/blob/v0.5.1/pkg/circuitbreak/cbsuite.go#L195) for details). | ||
### More Info | ||
|
||
Refer to [example](https://github.com/kitex-contrib/config-file/tree/main/example) for more usage. | ||
|
||
## Note | ||
|
||
For client configuration, you should write all their configurations in the same pair of `$UserServiceName/$ServerServiceName`, for example | ||
|
||
```json | ||
{ | ||
"ClientName/ServiceName": { | ||
"timeout": { | ||
"*": { | ||
"conn_timeout_ms": 100, | ||
"rpc_timeout_ms": 2000 | ||
}, | ||
"Pay": { | ||
"conn_timeout_ms": 50, | ||
"rpc_timeout_ms": 1000 | ||
} | ||
}, | ||
"circuitbreaker": { | ||
"Echo": { | ||
"enable": true, | ||
"err_rate": 0.3, | ||
"min_sample": 100 | ||
} | ||
}, | ||
"retry": { | ||
"*": { | ||
"enable": true, | ||
"type": 0, | ||
"failure_policy": { | ||
"stop_policy": { | ||
"max_retry_times": 3, | ||
"max_duration_ms": 2000, | ||
"cb_policy": { | ||
"error_rate": 0.2 | ||
} | ||
} | ||
} | ||
}, | ||
"Echo": { | ||
"enable": true, | ||
"type": 1, | ||
"backup_policy": { | ||
"retry_delay_ms": 200, | ||
"stop_policy": { | ||
"max_retry_times": 2, | ||
"max_duration_ms": 1000, | ||
"cb_policy": { | ||
"error_rate": 0.3 | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` |
Oops, something went wrong.