diff --git a/bcs-services/bcs-bscp/cmd/feed-server/etc/feed_server.yaml b/bcs-services/bcs-bscp/cmd/feed-server/etc/feed_server.yaml
index c595a43acf..7072a39e96 100644
--- a/bcs-services/bcs-bscp/cmd/feed-server/etc/feed_server.yaml
+++ b/bcs-services/bcs-bscp/cmd/feed-server/etc/feed_server.yaml
@@ -96,6 +96,34 @@ downstream:
burst: 500
waitTimeMil: 50
+# feed server's rate limiter related settings.
+rateLimiter:
+ # 是否启用限流器,默认为false(关闭)
+ enable:
+ # clientBandwidth为单个客户端下载文件所评估的可用带宽,用于决定单次下载流控阈值,单位为MB/s,默认为50(50MB/s=400Mb/s)
+ clientBandwidth:
+ # global为全局限流器配置,整个feed-server粒度
+ global:
+ # limit为流量速率限制,单位为MB/s,默认为1000(1000MB/s=8000Mb/s)
+ limit:
+ # burst为允许处理的突发流量上限(允许系统在短时间内处理比速率限制更多的流量),单位为MB,默认为2000(2000MB=16000Mb)
+ burst:
+ # biz为业务粒度限流器配置
+ biz:
+ # 业务默认配置(优先级低于显示设置的业务配置)
+ default:
+ # limit为流量速率限制,单位为MB/s,默认为100(100MB/s=800Mb/s)
+ limit:
+ # burst为允许处理的突发流量上限(允许系统在短时间内处理比速率限制更多的流量),单位为MB,默认为200(200MB=1600Mb)
+ burst:
+ # 显示设置的业务配置
+ spec:
+ 2:
+ # limit为流量速率限制,单位为MB/s
+ limit:
+ # burst为允许处理的突发流量上限(允许系统在短时间内处理比速率限制更多的流量),单位为MB
+ burst:
+
# feed server's local cache related settings.
# Note:
# 1. These configurations depend on you host's in-memory cache size, the larger the value of these
diff --git a/bcs-services/bcs-bscp/cmd/feed-server/service/metric.go b/bcs-services/bcs-bscp/cmd/feed-server/service/metric.go
index 9bde9dc090..44c2ec1d30 100644
--- a/bcs-services/bcs-bscp/cmd/feed-server/service/metric.go
+++ b/bcs-services/bcs-bscp/cmd/feed-server/service/metric.go
@@ -75,6 +75,31 @@ func initMetric(name string) *metric {
}, []string{"bizID", "appName"})
metrics.Register().MustRegister(m.clientCurrentMemUsage)
+ m.downloadTotalSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: metrics.Namespace,
+ Subsystem: metrics.FSConfigConsume,
+ Name: "file_download_total_size_bytes",
+ Help: "Total size of files downloaded, biz 0 means global",
+ ConstLabels: labels,
+ }, []string{"bizID"})
+ metrics.Register().MustRegister(m.downloadTotalSize)
+ m.downloadDelayRequests = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: metrics.Namespace,
+ Subsystem: metrics.FSConfigConsume,
+ Name: "file_download_delay_requests",
+ Help: "Total number of downloaded file delayed requests, biz 0 means global",
+ ConstLabels: labels,
+ }, []string{"bizID"})
+ metrics.Register().MustRegister(m.downloadDelayRequests)
+ m.downloadDelayMilliseconds = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: metrics.Namespace,
+ Subsystem: metrics.FSConfigConsume,
+ Name: "file_download_delay_milliseconds",
+ Help: "Delay milliseconds of downloaded file, biz 0 means global",
+ ConstLabels: labels,
+ }, []string{"bizID"})
+ metrics.Register().MustRegister(m.downloadDelayMilliseconds)
+
return m
}
@@ -84,6 +109,7 @@ type metric struct {
// watchCounter record the total connection count of sidecars with watch, used to get the new the connection count
// within a specified time range.
watchCounter *prometheus.CounterVec
+
// clientMaxCPUUsage The maximum cpu usage of the client was collected
clientMaxCPUUsage *prometheus.GaugeVec
// clientMaxMemUsage the maximum memory usage was collected
@@ -92,4 +118,15 @@ type metric struct {
clientCurrentCPUUsage *prometheus.GaugeVec
// clientCurrentMemUsage the current memory usage of the client is collected
clientCurrentMemUsage *prometheus.GaugeVec
+
+ downloadTotalSize *prometheus.GaugeVec
+ downloadDelayRequests *prometheus.GaugeVec
+ downloadDelayMilliseconds *prometheus.GaugeVec
+}
+
+// collectDownload collects metrics for download
+func (m *metric) collectDownload(biz string, totalSize, delayRequests, delayMilliseconds int64) {
+ m.downloadTotalSize.With(prm.Labels{"bizID": biz}).Set(float64(totalSize))
+ m.downloadDelayRequests.With(prm.Labels{"bizID": biz}).Set(float64(delayRequests))
+ m.downloadDelayMilliseconds.With(prm.Labels{"bizID": biz}).Set(float64(delayMilliseconds))
}
diff --git a/bcs-services/bcs-bscp/cmd/feed-server/service/rpc_sidecar.go b/bcs-services/bcs-bscp/cmd/feed-server/service/rpc_sidecar.go
index 164036d6ef..9a328d3d1f 100644
--- a/bcs-services/bcs-bscp/cmd/feed-server/service/rpc_sidecar.go
+++ b/bcs-services/bcs-bscp/cmd/feed-server/service/rpc_sidecar.go
@@ -38,6 +38,7 @@ import (
pbbase "github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/protocol/core/base"
pbkv "github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/protocol/core/kv"
pbfs "github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/protocol/feed-server"
+ "github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/ratelimiter"
"github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/runtime/jsoni"
sfs "github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/sf-share"
"github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/tools"
@@ -456,7 +457,37 @@ func (s *Service) GetDownloadURL(ctx context.Context, req *pbfs.GetDownloadURLRe
return nil, status.Errorf(codes.Aborted, "generate temp download url failed, %s", err.Error())
}
- return &pbfs.GetDownloadURLResp{Url: downloadLink}, nil
+ if !s.rl.Enable() {
+ return &pbfs.GetDownloadURLResp{Url: downloadLink, WaitTimeMil: 0}, nil
+ }
+ // 对于单个大文件下载,受限于单个客户端和服务端之间的带宽(比如为10MB/s=80Mb/s),而在存储服务端支持更高带宽的情况下(比如100MB/s),
+ // 哪怕单个文件2GB,在限流器阈值比单个客户端下载带宽高的情况下,还是应该允许其他客户端去存储服务端下载,
+ // 超过客户端下载带宽的大文件暂且按客户端带宽计入流控
+ // 多个大文件的持续下载,会影响到限流器流控的精确性,当前暂时只计入每个大文件首次一秒内的流控情况,后续的流量消耗不计入
+ var gWaitTimeMil, bWaitTimeMil int64
+ bandwidth := int(s.rl.ClientBandwidth()) * ratelimiter.MB
+ if int(req.FileMeta.CommitSpec.Content.ByteSize) > bandwidth {
+ gWaitTimeMil = s.rl.Global().WaitTimeMil(bandwidth)
+ bWaitTimeMil = s.rl.UseBiz(uint(req.BizId)).WaitTimeMil(bandwidth)
+ } else {
+ gWaitTimeMil = s.rl.Global().WaitTimeMil(int(req.FileMeta.CommitSpec.Content.ByteSize))
+ bWaitTimeMil = s.rl.UseBiz(uint(req.BizId)).WaitTimeMil(int(req.FileMeta.CommitSpec.Content.ByteSize))
+ }
+
+ // 分别统计全局和业务粒度流控情况
+ gs := s.rl.Global().Stats()
+ s.mc.collectDownload("0", gs.TotalByteSize, gs.DelayCnt, gs.DelayMilliseconds)
+ bs := s.rl.UseBiz(uint(req.BizId)).Stats()
+ logs.V(1).Infof("biz: %d, download file total byte size:%d, delay cnt:%d, delay milliseconds:%d",
+ req.BizId, bs.TotalByteSize, bs.DelayCnt, bs.DelayMilliseconds)
+ s.mc.collectDownload(fmt.Sprintf("%d", req.BizId), bs.TotalByteSize, bs.DelayCnt, bs.DelayMilliseconds)
+
+ // 优先使用流控时间长的
+ wt := bWaitTimeMil
+ if bWaitTimeMil < gWaitTimeMil {
+ wt = gWaitTimeMil
+ }
+ return &pbfs.GetDownloadURLResp{Url: downloadLink, WaitTimeMil: wt}, nil
}
// PullKvMeta pull an app's latest release metadata only when the app's configures is kv type.
diff --git a/bcs-services/bcs-bscp/cmd/feed-server/service/service.go b/bcs-services/bcs-bscp/cmd/feed-server/service/service.go
index 8b6563fb1e..8d84426df8 100644
--- a/bcs-services/bcs-bscp/cmd/feed-server/service/service.go
+++ b/bcs-services/bcs-bscp/cmd/feed-server/service/service.go
@@ -31,6 +31,7 @@ import (
"github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/dal/repository"
"github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/iam/auth"
"github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/logs"
+ "github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/ratelimiter"
"github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/rest"
"github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/runtime/handler"
"github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/runtime/shutdown"
@@ -51,6 +52,7 @@ type Service struct {
name string
mc *metric
gwMux *runtime.ServeMux
+ rl *ratelimiter.RL
}
// NewService create a service instance.
@@ -81,6 +83,9 @@ func NewService(sd serviced.Discover, name string) (*Service, error) {
return nil, fmt.Errorf("new repository provider failed, err: %v", err)
}
+ rl := ratelimiter.New(cc.FeedServer().RateLimiter)
+ logs.Infof("init rate limiter, conf: %+v", cc.FeedServer().RateLimiter)
+
return &Service{
bll: bl,
authorizer: authorizer,
@@ -89,6 +94,7 @@ func NewService(sd serviced.Discover, name string) (*Service, error) {
provider: provider,
mc: initMetric(name),
gwMux: gwMux,
+ rl: rl,
}, nil
}
diff --git a/bcs-services/bcs-bscp/pkg/cc/service.go b/bcs-services/bcs-bscp/pkg/cc/service.go
index 21e200c666..dbd31bb008 100644
--- a/bcs-services/bcs-bscp/pkg/cc/service.go
+++ b/bcs-services/bcs-bscp/pkg/cc/service.go
@@ -371,6 +371,7 @@ type FeedServerSetting struct {
FSLocalCache FSLocalCache `yaml:"fsLocalCache"`
Downstream Downstream `yaml:"downstream"`
MRLimiter MatchReleaseLimiter `yaml:"matchReleaseLimiter"`
+ RateLimiter RateLimiter `yaml:"rateLimiter"`
}
// trySetFlagBindIP try set flag bind ip.
@@ -394,6 +395,7 @@ func (s *FeedServerSetting) trySetDefault() {
s.GSE.trySetDefault()
s.RedisCluster.trySetDefault()
s.MRLimiter.trySetDefault()
+ s.RateLimiter.trySetDefault()
}
// Validate FeedServerSetting option.
@@ -423,6 +425,10 @@ func (s FeedServerSetting) Validate() error {
return err
}
+ if err := s.RateLimiter.validate(); err != nil {
+ return err
+ }
+
if err := s.Esb.validate(); err != nil {
return err
}
diff --git a/bcs-services/bcs-bscp/pkg/cc/types.go b/bcs-services/bcs-bscp/pkg/cc/types.go
index acee64955b..3ed488b994 100644
--- a/bcs-services/bcs-bscp/pkg/cc/types.go
+++ b/bcs-services/bcs-bscp/pkg/cc/types.go
@@ -1098,6 +1098,104 @@ func (lm *MatchReleaseLimiter) trySetDefault() {
}
}
+// RateLimiter defines the rate limiter options for traffic control.
+type RateLimiter struct {
+ Enable bool `yaml:"enable"`
+ ClientBandwidth uint `yaml:"clientBandwidth"`
+ Global BasicRL `yaml:"global"`
+ Biz BizRLs `yaml:"biz"`
+}
+
+// BizRLs defines the rate limiters for biz
+type BizRLs struct {
+ Default BasicRL `yaml:"default"`
+ Spec map[uint]BasicRL `yaml:"spec"`
+}
+
+// BasicRL defines the basic options for rate limiter.
+type BasicRL struct {
+ Limit uint `yaml:"limit"`
+ Burst uint `yaml:"burst"`
+}
+
+const (
+ // DefaultClientBandwidth default client bandwidth
+ DefaultClientBandwidth = 50 // 50MB/s = 400Mb/s
+ // DefaultGlobalRateLimit default global rate limit
+ DefaultGlobalRateLimit = 1000 // 1000MB/s = 8000Mb/s
+ // DefaultGlobalRateBurst default global rate burst
+ DefaultGlobalRateBurst = 2000 // 2000MB = 16000Mb
+ // DefaultBizRateLimit default biz rate limit
+ DefaultBizRateLimit = 100 // 100MB/s = 800Mb/s
+ // DefaultBizRateBurst default biz rate burst
+ DefaultBizRateBurst = 200 // 200MB = 1600Mb
+)
+
+// validate if the rate limiter is valid or not.
+func (rl RateLimiter) validate() error {
+ if rl.Biz.Default.Burst < rl.Biz.Default.Limit {
+ return fmt.Errorf("invalid rateLimiter.biz.default.burst value %d, should >= rateLimiter.biz.default.limit "+
+ "value %d", rl.Global.Burst, rl.Global.Limit)
+ }
+
+ if rl.Global.Limit < rl.Biz.Default.Limit {
+ return fmt.Errorf("invalid rateLimiter.global.limit value %d, should >= rateLimiter.biz.default.limit value %d",
+ rl.Global.Limit, rl.ClientBandwidth)
+ }
+
+ if rl.Global.Burst < rl.Biz.Default.Burst {
+ return fmt.Errorf("invalid rateLimiter.global.burst value %d, should >= rateLimiter.biz.default.burst value %d",
+ rl.Global.Burst, rl.Global.Limit)
+ }
+
+ for bizID, l := range rl.Biz.Spec {
+ if l.Burst < l.Limit {
+ return fmt.Errorf("invalid rateLimiter.biz.spec.%d.burst value %d, "+
+ "should >= rateLimiter.biz.spec.%d.limit value %d", bizID, l.Burst, bizID, l.Limit)
+ }
+ }
+
+ return nil
+}
+
+// trySetDefault try set the default value of rate limiter
+func (rl *RateLimiter) trySetDefault() {
+ if rl.ClientBandwidth == 0 {
+ rl.ClientBandwidth = DefaultClientBandwidth
+ }
+
+ if rl.Global.Limit == 0 {
+ rl.Global.Limit = DefaultGlobalRateLimit
+ }
+
+ if rl.Global.Burst == 0 {
+ rl.Global.Burst = DefaultGlobalRateBurst
+ }
+
+ if rl.Biz.Default.Limit == 0 {
+ rl.Biz.Default.Limit = DefaultBizRateLimit
+ }
+
+ if rl.Biz.Default.Burst == 0 {
+ rl.Biz.Default.Burst = DefaultBizRateBurst
+ }
+
+ for bizID, l := range rl.Biz.Spec {
+ if l.Limit == 0 {
+ rl.Biz.Spec[bizID] = BasicRL{
+ Limit: DefaultBizRateLimit,
+ Burst: l.Burst,
+ }
+ }
+ if l.Burst == 0 {
+ rl.Biz.Spec[bizID] = BasicRL{
+ Limit: rl.Biz.Spec[bizID].Limit,
+ Burst: DefaultBizRateBurst,
+ }
+ }
+ }
+}
+
// Credential credential encryption algorithm and master key
type Credential struct {
MasterKey string `yaml:"master_key"`
diff --git a/bcs-services/bcs-bscp/pkg/protocol/feed-server/feed_server.pb.go b/bcs-services/bcs-bscp/pkg/protocol/feed-server/feed_server.pb.go
index e9e4119c62..d292fe833c 100644
--- a/bcs-services/bcs-bscp/pkg/protocol/feed-server/feed_server.pb.go
+++ b/bcs-services/bcs-bscp/pkg/protocol/feed-server/feed_server.pb.go
@@ -1003,7 +1003,8 @@ type GetDownloadURLResp struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
+ Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
+ WaitTimeMil int64 `protobuf:"varint,2,opt,name=wait_time_mil,json=waitTimeMil,proto3" json:"wait_time_mil,omitempty"` // the time(milliseconds) that the client should wait before downloading file
}
func (x *GetDownloadURLResp) Reset() {
@@ -1045,6 +1046,13 @@ func (x *GetDownloadURLResp) GetUrl() string {
return ""
}
+func (x *GetDownloadURLResp) GetWaitTimeMil() int64 {
+ if x != nil {
+ return x.WaitTimeMil
+ }
+ return 0
+}
+
// App 对外简单版本
type App struct {
state protoimpl.MessageState
@@ -1921,145 +1929,147 @@ var file_feed_server_proto_rawDesc = []byte{
0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x46,
0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74,
0x61, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x26, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x6f,
+ 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x6f,
0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a,
- 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22,
- 0x78, 0x0a, 0x03, 0x41, 0x70, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x72,
- 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
- 0x70, 0x62, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52,
- 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0b, 0x4c, 0x69, 0x73,
- 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x69, 0x7a, 0x5f,
- 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x69, 0x7a, 0x49, 0x64, 0x12,
- 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05,
- 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x2d, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1d, 0x0a, 0x04, 0x61, 0x70, 0x70, 0x73, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x04,
- 0x61, 0x70, 0x70, 0x73, 0x22, 0x66, 0x0a, 0x0d, 0x50, 0x75, 0x6c, 0x6c, 0x4b, 0x76, 0x4d, 0x65,
- 0x74, 0x61, 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x69, 0x7a, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x08,
- 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d,
- 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x07, 0x61,
- 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18,
- 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x58, 0x0a, 0x0e,
- 0x50, 0x75, 0x6c, 0x6c, 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1d,
- 0x0a, 0x0a, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a,
- 0x08, 0x6b, 0x76, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x0c, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x07, 0x6b,
- 0x76, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x22, 0xd5, 0x01, 0x0a, 0x06, 0x4b, 0x76, 0x4d, 0x65, 0x74,
- 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
- 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6b, 0x76, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, 0x76, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x08,
- 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10,
- 0x2e, 0x70, 0x62, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
- 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0d, 0x6b, 0x76,
- 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x6b, 0x76, 0x2e, 0x4b, 0x76, 0x41, 0x74, 0x74, 0x61, 0x63,
- 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x6b, 0x76, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d,
- 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x73,
- 0x70, 0x65, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x62, 0x63, 0x6f,
- 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65,
- 0x63, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x22, 0x62,
- 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4b, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x12,
- 0x15, 0x0a, 0x06, 0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
- 0x05, 0x62, 0x69, 0x7a, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x65,
- 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e,
- 0x41, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61,
- 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
- 0x65, 0x79, 0x22, 0x3f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4b, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65,
- 0x52, 0x65, 0x73, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x6b, 0x76, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, 0x76, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a,
- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x22, 0xee, 0x01, 0x0a, 0x10, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77,
- 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x69, 0x7a, 0x5f,
- 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x69, 0x7a, 0x49, 0x64, 0x12,
- 0x1e, 0x0a, 0x0b, 0x62, 0x6b, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12,
- 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x15,
- 0x0a, 0x06, 0x70, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
- 0x70, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
- 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63,
- 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x09,
- 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x0e, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52,
- 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x69, 0x6c,
- 0x65, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66, 0x69, 0x6c,
- 0x65, 0x44, 0x69, 0x72, 0x22, 0x2c, 0x0a, 0x11, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77,
- 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73,
- 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b,
- 0x49, 0x64, 0x22, 0x48, 0x0a, 0x16, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
- 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x06,
+ 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12,
+ 0x22, 0x0a, 0x0d, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x6c,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x77, 0x61, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65,
+ 0x4d, 0x69, 0x6c, 0x22, 0x78, 0x0a, 0x03, 0x41, 0x70, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12,
+ 0x2c, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x73,
+ 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a,
+ 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x06,
0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x69,
- 0x7a, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x4c, 0x0a, 0x17,
- 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61,
- 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
- 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41,
- 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74,
- 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x3f, 0x0a, 0x13, 0x41, 0x73,
- 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75,
- 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0f,
- 0x0a, 0x0b, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12,
- 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x32, 0xf3, 0x05, 0x0a, 0x08,
- 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x3a, 0x0a, 0x09, 0x48, 0x61, 0x6e, 0x64,
- 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x48, 0x61, 0x6e,
- 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x13, 0x2e,
- 0x70, 0x62, 0x66, 0x73, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x52, 0x65,
- 0x73, 0x70, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e,
- 0x67, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69,
- 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4d, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x38, 0x0a,
- 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x53, 0x69,
- 0x64, 0x65, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x16, 0x2e, 0x70, 0x62,
- 0x66, 0x73, 0x2e, 0x46, 0x65, 0x65, 0x64, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x73, 0x73,
- 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0f, 0x50, 0x75, 0x6c, 0x6c, 0x41,
- 0x70, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x18, 0x2e, 0x70, 0x62, 0x66,
- 0x73, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x41, 0x70, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74,
- 0x61, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x50, 0x75, 0x6c, 0x6c,
- 0x41, 0x70, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x22,
- 0x00, 0x12, 0x45, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
- 0x55, 0x52, 0x4c, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x6f,
- 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x70,
- 0x62, 0x66, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55,
- 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x0a, 0x50, 0x75, 0x6c, 0x6c,
- 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x50, 0x75,
- 0x6c, 0x6c, 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x70, 0x62,
- 0x66, 0x73, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73,
- 0x70, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x3a, 0x01, 0x2a, 0x22, 0x26, 0x2f, 0x61,
- 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x2f, 0x62, 0x69, 0x7a, 0x2f, 0x7b,
- 0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6b, 0x76, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x61,
- 0x64, 0x61, 0x74, 0x61, 0x12, 0x6c, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4b, 0x76, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x76, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x47,
- 0x65, 0x74, 0x4b, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x33, 0x82,
- 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76,
- 0x31, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x2f, 0x62, 0x69, 0x7a, 0x2f, 0x7b, 0x62, 0x69, 0x7a, 0x5f,
- 0x69, 0x64, 0x7d, 0x2f, 0x6b, 0x76, 0x73, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x7b, 0x6b, 0x65,
- 0x79, 0x7d, 0x12, 0x33, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x12, 0x11,
- 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65,
- 0x71, 0x1a, 0x12, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x41, 0x73, 0x79, 0x6e, 0x63,
- 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x16, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e,
- 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71,
- 0x1a, 0x17, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77,
- 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x13, 0x41,
- 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74,
- 0x75, 0x73, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44,
+ 0x7a, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x2d, 0x0a, 0x0c, 0x4c, 0x69, 0x73,
+ 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1d, 0x0a, 0x04, 0x61, 0x70, 0x70,
+ 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41,
+ 0x70, 0x70, 0x52, 0x04, 0x61, 0x70, 0x70, 0x73, 0x22, 0x66, 0x0a, 0x0d, 0x50, 0x75, 0x6c, 0x6c,
+ 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x69, 0x7a,
+ 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x69, 0x7a, 0x49, 0x64,
+ 0x12, 0x28, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x4d, 0x65, 0x74,
+ 0x61, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61,
+ 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68,
+ 0x22, 0x58, 0x0a, 0x0e, 0x50, 0x75, 0x6c, 0x6c, 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65,
+ 0x73, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49,
+ 0x64, 0x12, 0x27, 0x0a, 0x08, 0x6b, 0x76, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x73, 0x18, 0x03, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4b, 0x76, 0x4d, 0x65, 0x74,
+ 0x61, 0x52, 0x07, 0x6b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x22, 0xd5, 0x01, 0x0a, 0x06, 0x4b,
+ 0x76, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6b, 0x76, 0x5f, 0x74, 0x79,
+ 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, 0x76, 0x54, 0x79, 0x70, 0x65,
+ 0x12, 0x2c, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x76, 0x69,
+ 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37,
+ 0x0a, 0x0d, 0x6b, 0x76, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x6b, 0x76, 0x2e, 0x4b, 0x76, 0x41,
+ 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x6b, 0x76, 0x41, 0x74, 0x74,
+ 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e,
+ 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+ 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x70,
+ 0x65, 0x63, 0x22, 0x62, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4b, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x69, 0x7a, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x08, 0x61, 0x70,
+ 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70,
+ 0x62, 0x66, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x07, 0x61, 0x70, 0x70,
+ 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x3f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4b, 0x76, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x6b, 0x76, 0x5f, 0x74,
+ 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, 0x76, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xee, 0x01, 0x0a, 0x10, 0x41, 0x73, 0x79, 0x6e,
+ 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x12, 0x15, 0x0a, 0x06,
+ 0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x69,
+ 0x7a, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0b, 0x62, 0x6b, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f,
+ 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6b, 0x41, 0x67, 0x65, 0x6e,
+ 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69,
+ 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x70, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x05, 0x70, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e,
+ 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
+ 0x12, 0x2b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d,
+ 0x65, 0x74, 0x61, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x19, 0x0a,
+ 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x07, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x69, 0x72, 0x22, 0x2c, 0x0a, 0x11, 0x41, 0x73, 0x79, 0x6e,
+ 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x17, 0x0a,
+ 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+ 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x16, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44,
0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71,
- 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77,
- 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22,
- 0x00, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
- 0x54, 0x65, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x4b, 0x69, 0x6e, 0x67, 0x2f,
- 0x62, 0x6b, 0x2d, 0x62, 0x63, 0x73, 0x2f, 0x62, 0x63, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69,
- 0x63, 0x65, 0x73, 0x2f, 0x62, 0x63, 0x73, 0x2d, 0x62, 0x73, 0x63, 0x70, 0x2f, 0x70, 0x6b, 0x67,
- 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x2d, 0x73,
- 0x65, 0x72, 0x76, 0x65, 0x72, 0x3b, 0x70, 0x62, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x33,
+ 0x12, 0x15, 0x0a, 0x06, 0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
+ 0x52, 0x05, 0x62, 0x69, 0x7a, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f,
+ 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64,
+ 0x22, 0x4c, 0x0a, 0x17, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+ 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x31, 0x0a, 0x06, 0x73,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x62,
+ 0x66, 0x73, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x3f,
+ 0x0a, 0x13, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53,
+ 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x49, 0x4e,
+ 0x47, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x32,
+ 0xf3, 0x05, 0x0a, 0x08, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x3a, 0x0a, 0x09,
+ 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x62, 0x66, 0x73,
+ 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x1a, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61,
+ 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x13, 0x2e, 0x70, 0x62, 0x66,
+ 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x22,
+ 0x00, 0x12, 0x38, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x66,
+ 0x73, 0x2e, 0x53, 0x69, 0x64, 0x65, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x61, 0x1a,
+ 0x16, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x46, 0x65, 0x65, 0x64, 0x57, 0x61, 0x74, 0x63, 0x68,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0f, 0x50,
+ 0x75, 0x6c, 0x6c, 0x41, 0x70, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x18,
+ 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x41, 0x70, 0x70, 0x46, 0x69, 0x6c,
+ 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e,
+ 0x50, 0x75, 0x6c, 0x6c, 0x41, 0x70, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52,
+ 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x77, 0x6e,
+ 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x47,
+ 0x65, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71,
+ 0x1a, 0x18, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
+ 0x6f, 0x61, 0x64, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x0a,
+ 0x50, 0x75, 0x6c, 0x6c, 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x66,
+ 0x73, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x4b, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x1a,
+ 0x14, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x4b, 0x76, 0x4d, 0x65, 0x74,
+ 0x61, 0x52, 0x65, 0x73, 0x70, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x3a, 0x01, 0x2a,
+ 0x22, 0x26, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x2f, 0x62,
+ 0x69, 0x7a, 0x2f, 0x7b, 0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6b, 0x76, 0x73, 0x2f,
+ 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x6c, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4b,
+ 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x47, 0x65,
+ 0x74, 0x4b, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x70, 0x62,
+ 0x66, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28, 0x2f, 0x61,
+ 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x2f, 0x62, 0x69, 0x7a, 0x2f, 0x7b,
+ 0x62, 0x69, 0x7a, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6b, 0x76, 0x73, 0x2f, 0x64, 0x61, 0x74, 0x61,
+ 0x2f, 0x7b, 0x6b, 0x65, 0x79, 0x7d, 0x12, 0x33, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70,
+ 0x70, 0x73, 0x12, 0x11, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70,
+ 0x70, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x4c, 0x69, 0x73,
+ 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x41,
+ 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x16, 0x2e, 0x70,
+ 0x62, 0x66, 0x73, 0x2e, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+ 0x64, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x73, 0x79, 0x6e,
+ 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12,
+ 0x54, 0x0a, 0x13, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x73,
+ 0x79, 0x6e, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75,
+ 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x66, 0x73, 0x2e, 0x41, 0x73, 0x79, 0x6e,
+ 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52,
+ 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x65, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x4b,
+ 0x69, 0x6e, 0x67, 0x2f, 0x62, 0x6b, 0x2d, 0x62, 0x63, 0x73, 0x2f, 0x62, 0x63, 0x73, 0x2d, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x62, 0x63, 0x73, 0x2d, 0x62, 0x73, 0x63, 0x70,
+ 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x66, 0x65,
+ 0x65, 0x64, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3b, 0x70, 0x62, 0x66, 0x73, 0x62, 0x06,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/bcs-services/bcs-bscp/pkg/protocol/feed-server/feed_server.proto b/bcs-services/bcs-bscp/pkg/protocol/feed-server/feed_server.proto
index 9cc9d1d8d4..877f566bbd 100644
--- a/bcs-services/bcs-bscp/pkg/protocol/feed-server/feed_server.proto
+++ b/bcs-services/bcs-bscp/pkg/protocol/feed-server/feed_server.proto
@@ -148,6 +148,7 @@ message GetDownloadURLReq {
message GetDownloadURLResp {
string url = 1;
+ int64 wait_time_mil = 2; // the time(milliseconds) that the client should wait before downloading file
}
// App 对外简单版本
diff --git a/bcs-services/bcs-bscp/pkg/ratelimiter/ratelimiter.go b/bcs-services/bcs-bscp/pkg/ratelimiter/ratelimiter.go
new file mode 100644
index 0000000000..66ba586a1f
--- /dev/null
+++ b/bcs-services/bcs-bscp/pkg/ratelimiter/ratelimiter.go
@@ -0,0 +1,166 @@
+/*
+ * Tencent is pleased to support the open source community by making Blueking Container Service available.
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ * Licensed under the MIT License (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ * http://opensource.org/licenses/MIT
+ * 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 ratelimiter provides custom rate limiter
+package ratelimiter
+
+import (
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "golang.org/x/time/rate"
+
+ "github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/cc"
+)
+
+// RateLimiter is interface for rate limiter
+type RateLimiter interface {
+ // WaitTimeMil returns the wait time(milliseconds) according to the rate limiter
+ // 用于引导调用方等待相应时间后再访问服务,从而达到流控效果,避免服务过载
+ WaitTimeMil(size int) int64
+ // Stats returns the statistics of rate limiter
+ Stats() *StatsData
+}
+
+// New news a rate limiter
+// it is intended for direct use for other package
+func New(config cc.RateLimiter) *RL {
+ globalLimiter := NewGlobalRL(config.Global.Limit, config.Global.Burst)
+ bizLimiters := NewBizRLs(config.Biz)
+ return &RL{
+ enable: config.Enable,
+ clientBw: config.ClientBandwidth,
+ globalRL: globalLimiter,
+ bizRLs: bizLimiters,
+ }
+}
+
+// Enable returns enable of rate limiter
+func (r *RL) Enable() bool {
+ return r.enable
+}
+
+// ClientBandwidth returns client bandwidth of rate limiter
+func (r *RL) ClientBandwidth() uint {
+ return r.clientBw
+}
+
+// Global is global rate limiter
+func (r *RL) Global() RateLimiter {
+ return r.globalRL
+}
+
+// UseBiz uses rate limiter of specific biz
+func (r *RL) UseBiz(bizID uint) RateLimiter {
+ return r.bizRLs.getLimiter(bizID)
+}
+
+// RL is rate limiter for unified use
+type RL struct {
+ enable bool
+ clientBw uint
+ globalRL *globalRL
+ bizRLs *bizRLs
+}
+
+// globalRL is rate limiter for global dimension
+type globalRL struct {
+ *baseRL
+}
+
+// NewGlobalRL news a global rate limiter
+func NewGlobalRL(limit, burst uint) *globalRL {
+ return &globalRL{
+ baseRL: newBaseRL(limit, burst),
+ }
+}
+
+// bizRLs is rate limiter for biz dimension
+type bizRLs struct {
+ mutex sync.Mutex
+ defaultConf cc.BasicRL
+ bizLimiters map[uint]*baseRL
+}
+
+// NewBizRLs news rate limiters for biz
+func NewBizRLs(b cc.BizRLs) *bizRLs {
+ bizLimiters := make(map[uint]*baseRL)
+ for bizID, rl := range b.Spec {
+ bizLimiters[bizID] = newBaseRL(rl.Limit, rl.Burst)
+ }
+ return &bizRLs{
+ defaultConf: b.Default,
+ bizLimiters: bizLimiters,
+ }
+}
+
+// getLimiter get rate limiter for specific biz
+func (b *bizRLs) getLimiter(bizID uint) *baseRL {
+ b.mutex.Lock()
+ defer b.mutex.Unlock()
+ if limiter, exists := b.bizLimiters[bizID]; exists {
+ return limiter
+ }
+ defaultLimiter := newBaseRL(b.defaultConf.Limit, b.defaultConf.Burst)
+ b.bizLimiters[bizID] = defaultLimiter
+ return defaultLimiter
+}
+
+// baseRL is base rate limiter
+type baseRL struct {
+ limiter *rate.Limiter
+ totalByteSize int64
+ delayCnt int64
+ delayMilliseconds int64
+}
+
+// StatsData is stats data
+type StatsData struct {
+ TotalByteSize int64
+ DelayCnt int64
+ DelayMilliseconds int64
+}
+
+// MB means byte size of 1MB
+var MB = 1024 * 1024
+
+// newBaseRL news a base rate limiter
+// limit为流量速率限制,单位为MB/s,burst为允许处理的突发流量上限,单位为MB(允许系统在短时间内处理比速率限制更多的流量)
+// 内部实现使用令牌桶算法,令牌恢复速率为limit,在令牌被消耗完且不再有任何令牌消耗时,令牌数恢复至burst需要burst/limit秒
+// 举例说明:limit为100,burst为200,则将创建一个每秒生成100MB令牌、容量为200MB的限流器
+func newBaseRL(limit, burst uint) *baseRL {
+ return &baseRL{
+ limiter: rate.NewLimiter(rate.Limit(int(limit)*MB), int(burst)*MB),
+ }
+}
+
+// WaitTimeMil returns the wait time(milliseconds) according to the rate limiter
+func (r *baseRL) WaitTimeMil(size int) int64 {
+ atomic.AddInt64(&r.totalByteSize, int64(size))
+ reservation := r.limiter.ReserveN(time.Now(), size)
+ delay := reservation.Delay()
+ atomic.StoreInt64(&r.delayMilliseconds, delay.Milliseconds())
+ if delay > 0 {
+ atomic.AddInt64(&r.delayCnt, 1)
+ }
+ return delay.Milliseconds()
+}
+
+// Stats returns the statistics of rate limiter
+func (r *baseRL) Stats() *StatsData {
+ return &StatsData{
+ TotalByteSize: atomic.LoadInt64(&r.totalByteSize),
+ DelayCnt: atomic.LoadInt64(&r.delayCnt),
+ DelayMilliseconds: atomic.LoadInt64(&r.delayMilliseconds),
+ }
+}
diff --git a/bcs-services/bcs-bscp/pkg/ratelimiter/ratelimiter_test.go b/bcs-services/bcs-bscp/pkg/ratelimiter/ratelimiter_test.go
new file mode 100644
index 0000000000..758f47e2f2
--- /dev/null
+++ b/bcs-services/bcs-bscp/pkg/ratelimiter/ratelimiter_test.go
@@ -0,0 +1,149 @@
+/*
+ * Tencent is pleased to support the open source community by making Blueking Container Service available.
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ * Licensed under the MIT License (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ * http://opensource.org/licenses/MIT
+ * 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 ratelimiter
+
+import (
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/TencentBlueKing/bk-bcs/bcs-services/bcs-bscp/pkg/cc"
+)
+
+var config = cc.RateLimiter{
+ Enable: true,
+ ClientBandwidth: 10,
+ Global: cc.BasicRL{
+ Limit: 10,
+ Burst: 20,
+ },
+ Biz: cc.BizRLs{
+ Default: cc.BasicRL{
+ Limit: 5,
+ Burst: 5,
+ },
+ Spec: map[uint]cc.BasicRL{
+ 1: {
+ Limit: 10,
+ Burst: 20,
+ },
+ 2: {
+ Limit: 10,
+ Burst: 10,
+ },
+ },
+ },
+}
+
+func TestNewRateLimiter(t *testing.T) {
+ rl := New(config)
+ assert.NotNil(t, rl)
+ assert.NotNil(t, rl.Global())
+ assert.NotNil(t, rl.UseBiz(1))
+ assert.NotNil(t, rl.UseBiz(2))
+ // rl.UseBiz(3) will create new one with default biz config
+ assert.NotNil(t, rl.UseBiz(3))
+
+}
+
+func TestGlobalWaitTime(t *testing.T) {
+ r := New(config)
+ rl := r.Global()
+ testWaitTime(t, rl)
+}
+
+func TestBizWaitTime(t *testing.T) {
+ r := New(config)
+ rl := r.UseBiz(1)
+ testWaitTime(t, rl)
+}
+
+func TestGlobalStats(t *testing.T) {
+ config2 := config
+ config2.Global = cc.BasicRL{
+ Limit: 10,
+ Burst: 10,
+ }
+ r := New(config2)
+ rl := r.Global()
+ testStats(t, rl)
+}
+
+func TestBizStats(t *testing.T) {
+ r := New(config)
+ rl := r.UseBiz(2)
+ testStats(t, rl)
+}
+
+func TestBizStats2(t *testing.T) {
+ config3 := config
+ config3.Biz.Default = cc.BasicRL{
+ Limit: 10,
+ Burst: 10,
+ }
+ r := New(config3)
+ rl := r.UseBiz(3)
+ testStats(t, rl)
+}
+
+func testWaitTime(t *testing.T, rl RateLimiter) {
+
+ // Add a request that fits within the burst capacity
+ waitTime := rl.WaitTimeMil(MB * 20)
+ assert.Equal(t, int64(0), waitTime)
+
+ // Add another request that should be rate-limited
+ waitTime = rl.WaitTimeMil(MB * 5)
+ assert.True(t, waitTime > 0)
+
+ // Add another request that should be rate-limited too and wait time should be increased based on last time
+ waitTime = rl.WaitTimeMil(MB * 10)
+ assert.True(t, waitTime > 1000) // 1000 milliseconds
+ assert.True(t, waitTime < 2000) // 2000 milliseconds
+ t.Logf("waitTime: %d milliseconds", waitTime)
+
+ // After wait for corresponding time, it will be not rate-limited when size is less than the number of tokens
+ // Note that at this point, the number of tokens has not yet recovered to burst, recover speed is rate limit(10MB/s)
+ time.Sleep(time.Millisecond * time.Duration(waitTime))
+ waitTime = rl.WaitTimeMil(1)
+ assert.Equal(t, int64(0), waitTime)
+ time.Sleep(time.Second) // which will be recovered to rate limit
+ waitTime = rl.WaitTimeMil(MB * 10)
+ assert.Equal(t, int64(0), waitTime)
+ time.Sleep(time.Second * 2) // which will be recovered to burst(20MB)
+ waitTime = rl.WaitTimeMil(MB * 20)
+ assert.Equal(t, int64(0), waitTime)
+}
+
+func testStats(t *testing.T, rl RateLimiter) {
+ // Test initial stats
+ stats := rl.Stats()
+ assert.NotNil(t, stats)
+ assert.Equal(t, int64(0), stats.TotalByteSize)
+ assert.Equal(t, int64(0), stats.DelayCnt)
+ assert.Equal(t, int64(0), stats.DelayMilliseconds)
+
+ // Simulate some traffic
+ rl.WaitTimeMil(MB * 10) // which will not be rate-limited
+ rl.WaitTimeMil(MB * 10) // which will be rate-limited
+ rl.WaitTimeMil(MB * 10) // which will be rate-limited
+
+ stats = rl.Stats()
+ assert.NotNil(t, stats)
+ assert.True(t, stats.TotalByteSize == int64(MB*30))
+ assert.True(t, stats.DelayCnt == 2)
+ assert.True(t, stats.DelayMilliseconds > 1000)
+ assert.True(t, stats.DelayMilliseconds <= 2000)
+ t.Logf("stats.DelayMilliseconds: %d", stats.DelayMilliseconds)
+}
diff --git a/bcs-services/bcs-bscp/ui/src/components/version-log.vue b/bcs-services/bcs-bscp/ui/src/components/version-log.vue
index e304806004..f9b31d76ea 100644
--- a/bcs-services/bcs-bscp/ui/src/components/version-log.vue
+++ b/bcs-services/bcs-bscp/ui/src/components/version-log.vue
@@ -21,7 +21,7 @@