Skip to content

Commit

Permalink
feat/optimize for version 0.2.0 (douyu#133)
Browse files Browse the repository at this point in the history
* update registry

* add servcie definition

* add metric type

* update grpc resolver; polish registry

* update defers

* polish code

* update swr balancer; support traffic grouping and isolation

* add governor server by config
add makefile params
add env params

* optimize gorm

* remove useless code

* grpc interceptor

* tidy mod

* modify the mechanism of loading configuration

* optimize code

* add unit test

* improve governor

* add test and optimize cycle

* Update Readme

* add jupiter job

* clear hook

* jupiter test service
add etcd docker

* add test case for signals

* fix self-assignment

* fix demo

* fix race

* add etcdv3 test,and etcd lease seesion

* add grpc test
add server register metric

* keep compatible

* optimize cycle

* Upgrade agollo to v4.0.0

* 使用etcdv3库中mutex,增加worker etcd分布式任务锁

* 配置文件ConcurrentDelay设置为负数,编译报错问题修改

* fix race for test

* change github actions yml

* xcron增加阻塞与非阻塞锁

* optimize service kind

* run test

* add test

* fix bug

* add a simple demo

* add comment

* update travis

* update travis etcdv3

* fix go race

* fix etcd

* modify attr_test.go

* add etcd lease

* add etcd service for github actions

* revert swr

* fix data race with a low way

* fix test case

* fix bug

* fix diy flag for test

* add test cover

* fix test case

Co-authored-by: aerox <[email protected]>
Co-authored-by: askuy <[email protected]>
Co-authored-by: mlboy <[email protected]>
Co-authored-by: stirling <[email protected]>
Co-authored-by: younglifestyle <[email protected]>
  • Loading branch information
6 people authored Aug 3, 2020
1 parent 9744334 commit f84f675
Show file tree
Hide file tree
Showing 136 changed files with 5,746 additions and 1,006 deletions.
13 changes: 12 additions & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Go

on:
push:
branches: [ master ]
# branches:
pull_request:
branches: [ master ]

Expand All @@ -27,6 +27,17 @@ jobs:
image: redis
ports:
- 6379:6379
etcd:
image: "quay.io/coreos/etcd:v3.3"
env:
ETCD_ADVERTISE_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCDCTL_API: "3"
ALLOW_NONE_AUTHENTICATION: "yes"
ports:
- 2379:2379
- 2380:2380
- 4001:4001

steps:
- name: Set up Go ${{ matrix.go }}
Expand Down
9 changes: 8 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,25 @@ sudo: required
services:
- mysql
- redis-server
- docker

go:
- 1.13.x
- 1.14.x
env:
- GO111MODULE=on

before_install:
before_install:
- go get golang.org/x/tools/cmd/goimports
- mysql -e 'CREATE DATABASE IF NOT EXISTS test;'
- docker pull xieyanze/etcd3
- docker run -d -p 127.0.0.1:2379:2379 xieyanze/etcd3
- wget https://github.com/etcd-io/etcd/releases/download/v3.4.10/etcd-v3.4.10-linux-amd64.tar.gz
- tar xvf etcd-v3.4.10-linux-amd64.tar.gz

script:
- etcd-v3.4.10-linux-amd64/etcdctl put "/hello" "jupiter"
- etcd-v3.4.10-linux-amd64/etcdctl get "/hello"
- diff -u <(echo -n) <(gofmt -d -s .)
# - diff -u <(echo -n) <(goimports -d .)
- go test -v -race ./... -coverprofile=coverage.txt -covermode=atomic
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ func startGRPCServer() server.Server {
func startWorker() worker.Worker {
cron := xcron.DefaultConfig().Build()
cron.Schedule(xcron.Every(time.Second*10), xcron.FuncJob(func() error {
fmt.Println("now: ", time.Now().Local().String())
return nil
}))
return cron
Expand Down
10 changes: 10 additions & 0 deletions api/configuration.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
syntax = "proto3";
package com.douyu.jupiter.proto.registry.configuration;

option go_package="configuration";

message Configuration {

}

message Route
16 changes: 4 additions & 12 deletions doc/wiki-cn/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func main() {
app := &MyApplication{}
app.Startup()
app.SetRegistry(
etcdv3.DefaultConfig().BuildRegistry(),
etcdv3.DefaultConfig().Build(),
)
app.Run()
}
Expand All @@ -119,8 +119,8 @@ func main() {
app.Startup()
app.SetRegistry( // 多注册中心
compound.New(
etcdv3.StdConfig("bj01").BuildRegistry(), // 读取配置文件中 jupiter.etcdv3.bj01的配置,自动初始化一个etcd registry
etcdv3.StdConfig("bj02").BuildRegistry(), // 读取配置文件中 jupiter.etcdv3.bj02的配置,自动初始化一个etcd registry
etcdv3.StdConfig("bj01").Build(), // 读取配置文件中 jupiter.etcdv3.bj01的配置,自动初始化一个etcd registry
etcdv3.StdConfig("bj02").Build(), // 读取配置文件中 jupiter.etcdv3.bj02的配置,自动初始化一个etcd registry
),
)
app.Run()
Expand Down Expand Up @@ -157,15 +157,7 @@ func dialServer() {
```golang
// 1. 注册一个resolver
func init() {
resolver.Register(etcdv3.Config{
ReadTimeout: time.Second * 3,
Prefix: "jupiter",
Config: &clientEtcdv3.Config{
Endpoints: []string{"127.0.0.1:2379"},
ConnectTimeout: time.Second * 3,
Secure: false,
},
}.BuildResolver())
resolver.Register("etcd", etcdv3.StdConfig("wh").Build())
}
// 2. 通过resolver获取服务器地址
func dialServer() {
Expand Down
187 changes: 187 additions & 0 deletions doc/wiki-cn/service_register_and_discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# 服务注册与发现

### 1. 服务定义

``` golang
type ServiceInfo struct {
Name string `json:"name"`
Scheme string `json:"scheme"`
IP string `json:"ip"`
Port int `json:"port"`
Weight float64 `json:"weight"`
Enable bool `json:"enable"`
Healthy bool `json:"healthy"`
Metadata map[string]string `json:"metadata"`
Region string `json:"region"`
Zone string `json:"zone"`
Deployment string `json:"deployment"`
}
```


### 2. 流量控制

#### 2.1 红绿发布

蓝绿发布,是在生产环境稳定集群之外,额外部署一个与稳定集群规模相同的新集群,并通过流量控制,逐步引入流量至新集群直至100%,
原先稳定集群将与新集群同时保持在线一段时间,期间发生任何异常,可立刻将所有流量切回至原稳定集群,实现快速回滚。直到全部验证成功后,
下线老的稳定集群,新集群成为新的稳定集群。


1. 部署新的集群, 但不接入流量
```mermaid
graph LR
client --> service-v1-1
client --> service-v1-2
client --> service-v1-3
client -.X.-> service-v2-1
client -.X.-> service-v2-2
client -.X.-> service-v2-3
subgraph g2 [v2:red cluster]
service-v2-1
service-v2-2
service-v2-3
end
subgraph g1 [v1:green cluster]
service-v1-1
service-v1-2
service-v1-3
end
```
2. 将流量逐步导入v2集群,同时保持v1集群在线
```mermaid
graph LR
subgraph g1 [v1:green cluster]
service-v1-1
service-v1-2
service-v1-3
end
client --> service-v2-1
client --> service-v2-2
client --> service-v2-3
client --X--> service-v1-1
client --X--> service-v1-2
client --X--> service-v1-3
subgraph g2 [v2:red cluster]
service-v2-1
service-v2-2
service-v2-3
end
```

验证失败,立即将流量切到v1集群。


#### 2.2 灰度发布

灰度发布,是在生产环境稳定集群之外,额外部署一个小规模的灰度集群,并通过流量控制,引入部分流量到灰度集群,进行生产全量发布前的灰度验证。
如果验证失败,可立刻将所有流量切回至稳定集群,取消灰度发布过程;如果验证成功,则将新版本进行全量发布升级至生产环境稳定集群,完成灰度发布过程。

```mermaid
graph LR
subgraph g1 [v1:stable cluster]
service-v1-1
service-v1-2
service-v1-3
end
client --> service-v1-1
client --90%--> service-v1-2
client --> service-v1-3
client -.-> service-v2-1
client -.10%.-> service-v2-2
subgraph g2 [v2:grap cluster]
service-v2-1
service-v2-2
end
```
蓝绿发布和灰度发布的各有优缺点,需要根据具体业务和资源成本自行选择。这里以灰度发布为例,讨论jupiter中对gRPC服务进行流量控制,从而实现灰度发布。

#### 2.3 Jupiter中对gRPC服务进行灰度发布



### 3. 服务注册

应用服务注册键的修改有两个场景:
* 服务端注册、注销
* 治理端更新


为了保证在各个场景下的键修改安全,不同于一般的etcd键值更新方式:
* 对于服务端注册、注销:
* 获取key锁成功,读取治理键,将治理键值合并到注册键。
* 获取key锁失败,等待1s重新注册。最多重试三次
* 对于治理端更新
* 获取key锁成功,读取注册建,将治理键值合并写入,并单独写一个治理键。
* 获取key锁失败,由治理端用户触发重试

该方式保证了:
1. 多写端的键安全
2. 注册键删除后,治理键依旧可用。重新注册后,治理配置不会丢失
3. 兼容

另外,app sider(一个单独的agent,与应用同机部署),提供了两个功能:
1. etcdproxy, 代理etcd请求。最直观的优势是应用不再需要关心和配置etcd地址。
2. healthcheck, 对同机的app做健康检查,判定应用不可用时,主动注销服务。理论上应用不在需要使用 etcd lease 保证异常状态下的服务正常注销。

其中:
1. enable: 服务是否被客户端发现(即是否导入流量)
2. weight: 流量权重,客户端按照该权重配发流量
3. group: 流量分组, 多个分组使用','分隔



## 2 服务发现

### 2.1 负载均衡

常见的负载均衡算法有:

> Round Robin: 轮询算法,顾名思义请求将会依次发给每一个实例,来共同分担所有的请求。
> Random: 随机算法,将所有的请求随机分发给健康的实例。
> Least Conn: 最小连接数,在所有健康的实例中任选两个,将请求发给连接数较小的那一个实例。
> Weighted Round Robin: 加权轮询算法,根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。
针对流量分组的需求,naming在上述算法的基础上,实现了grpc.Resolver和grpc.Picker接口,提供基于分组和权重的负载均衡能力。
目前,naming支持 __group weighted random__ 算法, 通过调节配置:

> 单一分组内所有节点weight=1, 退化为组内Random算法。
> 组名置空,退化为全局Random算法。
之所以,使用Random而不是RoundRobin保底,原因是:

> 1. 常见的RoundRobin算法也会在初始阶段,增加随机因子,保证后端负载压力均衡。与Random算法效果相似。
> 2. 实现上,Random更简单
### 2.2 实现

naming.etcdResolver 实现了grpc.Resolver接口,相比etcdv3.GRPCResolver:

> naming.etcdResolver 支持grpc.Balancer最新接口。相对的etcdv3.GRPCResolver已被标记为Deprecated.
naming.groupPickerBuilder 实现了balancer.Builder接口,并向balancer包注入group_weight负载均衡器。


```go
// 服务发现
if len(options.iniConfig.EtcdEndpoints) > 0 {
if resolver.Get("grpc") == nil {
resolver.Register(naming.NewResolver("grpc", options.iniConfig.EtcdEndpoints))
}

options.dialOptions = append(options.dialOptions, grpc.WithBalancerName(naming.NameWeight))
}
// ...
cc, err := grpc.DialContext(
ctx,
"grpc:///" + options.iniConfig.Address,
options.dialOptions...,
)
```


如注释行所述,发起调用的时候必须在context中写入_group, 用于表明请求的服务组。否则会退化为 __全局随机的负载均衡策略__

_group的自动写入和匹配,在下一个版本中引入。

2 changes: 2 additions & 0 deletions example/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* [通过远端配置读取结构体配置示例](./config/structByRemoteConfig)
* [监听远端配置读取单行配置示例](./config/onelineByRemoteConfigWatch)
* [监听远端配置读取结构体配置示例](./config/structByRemoteConfigWatch)
* [通过Apollo配置读取单行配置示例](./config/onelinebyApollo)
* [通过etcdv3配置读取单行配置示例](./config/onelineByEtcdv3)
* [日志示例](./logger)
* [日志终端展示示例](./logger/command)
* [日志文本展示示例](./logger/file)
Expand Down
10 changes: 1 addition & 9 deletions example/all/cmd/demo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package main

import (
"fmt"
"log"

"github.com/douyu/jupiter/example/all/internal/app/demo"
Expand All @@ -26,16 +25,9 @@ import (
func main() {
eng := demo.NewEngine()

eng.AfterStop(func() error {
fmt.Println("exit...")
return nil
})

eng.SetGovernor("127.0.0.1:9391")

eng.SetRegistry( // 多注册中心
compound.New(
etcdv3.StdConfig("wh01").BuildRegistry(),
etcdv3.StdConfig("wh01").Build(),
),
)

Expand Down
10 changes: 0 additions & 10 deletions example/all/internal/app/demo/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,3 @@ func (eng *Engine) execJob() error {
xlog.Warn("exec job", xlog.String("warn", "print warning"))
return nil
}

func (eng *Engine) printLogs() error {
go func() {
for {
xlog.Info("hello", xlog.String("a", "b"))
time.Sleep(time.Second)
}
}()
return nil
}
Loading

0 comments on commit f84f675

Please sign in to comment.