Merge pull request #2 from bilibili/master

merge
pull/256/head
wuxingzhong 5 years ago committed by GitHub
commit d2274d9b06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      README.md
  2. 21
      doc/wiki-cn/FAQ.md
  3. 49
      doc/wiki-cn/blademaster-quickstart.md
  4. 4
      doc/wiki-cn/blademaster.md
  5. 69
      doc/wiki-cn/install.md
  6. 15
      misc/stat/dashboard/README.md
  7. 5922
      misc/stat/dashboard/prometheus.json
  8. 2
      pkg/net/http/blademaster/ratelimit.go
  9. 6
      pkg/net/http/blademaster/tree.go
  10. 29
      pkg/net/trace/zipkin/zipkin.go
  11. 1
      pkg/net/trace/zipkin/zipkin_test.go
  12. 3
      tool/kratos/template.go

@ -54,7 +54,8 @@ go build
## Documentation ## Documentation
[简体中文](doc/wiki-cn/summary.md) > [简体中文](doc/wiki-cn/summary.md)
> [FAQ](doc/wiki-cn/FAQ.md)
## License ## License
Kratos is under the MIT license. See the [LICENSE](./LICENSE) file for details. Kratos is under the MIT license. See the [LICENSE](./LICENSE) file for details.

@ -0,0 +1,21 @@
# 安装失败,提示go mod 错误
执行
```shell
go get -u github.com/bilibili/kratos/tool/kratos
```
出现以下错误时
```shell
go: github.com/prometheus/client_model@v0.0.0-20190220174349-fd36f4220a90: parsing go.mod: missing module line
go: github.com/remyoudompheng/bigfft@v0.0.0-20190806203942-babf20351dd7e3ac320adedbbe5eb311aec8763c: parsing go.mod: missing module line
```
如果你使用了https://goproxy.io/ 代理,那你要使用其他代理来替换它,然后删除GOPATH目录下的mod缓存文件夹,然后重新执行安装命令
代理列表
```
export GOPROXY=https://mirrors.aliyun.com/goproxy/
export GOPROXY=https://goproxy.cn/
export GOPROXY=https://goproxy.io/
```

@ -51,7 +51,8 @@ func initRouter(e *bm.Engine) {
e.Ping(ping) // engine自带的"/ping"接口,用于负载均衡检测服务健康状态 e.Ping(ping) // engine自带的"/ping"接口,用于负载均衡检测服务健康状态
g := e.Group("/kratos-demo") // e.Group 创建一组 "/kratos-demo" 起始的路由组 g := e.Group("/kratos-demo") // e.Group 创建一组 "/kratos-demo" 起始的路由组
{ {
g.GET("/start", howToStart) // g.GET 创建一个 "kratos-demo/start" 的路由,默认处理Handler为howToStart方法 g.GET("/start", howToStart) // g.GET 创建一个 "kratos-demo/start" 的路由,使用GET方式请求,默认处理Handler为howToStart方法
g.POST("start", howToStart) // g.POST 创建一个 "kratos-demo/start" 的路由,使用POST方式请求,默认处理Handler为howToStart方法
} }
} }
``` ```
@ -111,6 +112,52 @@ curl 'http://127.0.0.1:8000/metadata'
} }
``` ```
# 路径参数
使用方式如下:
```go
func initRouter(e *bm.Engine) {
e.Ping(ping)
g := e.Group("/kratos-demo")
{
g.GET("/start", howToStart)
// 路径参数有两个特殊符号":"和"*"
// ":" 跟在"/"后面为参数的key,匹配两个/中间的值 或 一个/到结尾(其中不再包含/)的值
// "*" 跟在"/"后面为参数的key,匹配从 /*开始到结尾的所有值,所有*必须写在最后且无法多个
// NOTE:这是不被允许的,会和 /start 冲突
// g.GET("/:xxx")
// NOTE: 可以拿到一个key为name的参数。注意只能匹配到/param1/felix,无法匹配/param1/felix/hao(该路径会404)
g.GET("/param1/:name", pathParam)
// NOTE: 可以拿到多个key参数。注意只能匹配到/param2/felix/hao/love,无法匹配/param2/felix或/param2/felix/hao
g.GET("/param2/:name/:value/:felid", pathParam)
// NOTE: 可以拿到一个key为name的参数 和 一个key为action的路径。
// NOTE: 如/params3/felix/hello,action的值为"/hello"
// NOTE: 如/params3/felix/hello/hi,action的值为"/hello/hi"
// NOTE: 如/params3/felix/hello/hi/,action的值为"/hello/hi/"
g.GET("/param3/:name/*action", pathParam)
}
}
func pathParam(c *bm.Context) {
name, _ := c.Params.Get("name")
value, _ := c.Params.Get("value")
felid, _ := c.Params.Get("felid")
action, _ := c.Params.Get("action")
path := c.RoutePath // NOTE: 获取注册的路由原始地址,如: /kratos-demo/param1/:name
c.JSONMap(map[string]interface{}{
"name": name,
"value": value,
"felid": felid,
"action": action,
"path": path,
}, nil)
}
```
# 性能分析 # 性能分析
启动时默认监听了`2333`端口用于`pprof`信息采集,如: 启动时默认监听了`2333`端口用于`pprof`信息采集,如:

@ -9,7 +9,7 @@
# 设计目标 # 设计目标
* 性能优异,不应该杂太多业务逻辑的成分 * 性能优异,不应该杂太多业务逻辑的成分
* 方便开发使用,开发对接的成本应该尽可能地小 * 方便开发使用,开发对接的成本应该尽可能地小
* 后续鉴权、认证等业务逻辑的模块应该可以通过业务模块的开发接入该框架内 * 后续鉴权、认证等业务逻辑的模块应该可以通过业务模块的开发接入该框架内
* 默认配置已经是 production ready 的配置,减少开发与线上环境的差异性 * 默认配置已经是 production ready 的配置,减少开发与线上环境的差异性
@ -30,7 +30,7 @@
`blademaster`处理请求的模式非常简单,大部分的逻辑都被封装在了各种`Handler`中。一般而言,业务逻辑作为最后一个`Handler`。 `blademaster`处理请求的模式非常简单,大部分的逻辑都被封装在了各种`Handler`中。一般而言,业务逻辑作为最后一个`Handler`。
正常情况下每个`Handler`按照顺序一个一个串行地执行下去,但是`Handler`中可以中断整个处理流程,直接输出`Response`。这种模式常被用于校验登陆的`middleware`中:一旦发现请求不合法,直接响应拒绝。 正常情况下每个`Handler`按照顺序一个一个串行地执行下去,但是`Handler`中可以中断整个处理流程,直接输出`Response`。这种模式常被用于校验登陆的`middleware`中:一旦发现请求不合法,直接响应拒绝。
请求处理的流程中也可以使用`Render`来辅助渲染`Response`,比如对于不同的请求需要响应不同的数据格式`JSON`、`XML`,此时可以使用不同的`Render`来简化逻辑。 请求处理的流程中也可以使用`Render`来辅助渲染`Response`,比如对于不同的请求需要响应不同的数据格式`JSON`、`XML`,此时可以使用不同的`Render`来简化逻辑。

@ -0,0 +1,69 @@
# 安装
1.安装protoc二进制文件
```
下载地址:https://github.com/google/protobuf/releases
mv bin/protoc /usr/local/bin/
mv -r include/google /usr/local/include/
```
2.安装protobuf库文件
```
go get -u github.com/golang/protobuf/proto
```
3.安装goprotobuf插件
```
go get github.com/golang/protobuf/protoc-gen-go
```
4.安装gogoprotobuf插件和依赖
```
//gogo
go get github.com/gogo/protobuf/protoc-gen-gogo
//gofast
go get github.com/gogo/protobuf/protoc-gen-gofast
//依赖
go get github.com/gogo/protobuf/proto
go get github.com/gogo/protobuf/gogoproto
```
5.安装框架依赖
```
# grpc (或者git clone https://github.com/grpc/grpc-go 然后复制到google.golang.org/grpc)
go get -u google.golang.org/grpc
# genproto (或者git clone https://github.com/google/go-genproto 然后复制到google.golang.org/genproto)
go get google.golang.org/genproto/...
```
6.安装kratos tool
```
go get -u github.com/bilibili/kratos/tool/kratos
cd $GOPATH/src
kratos new kratos-demo --proto
```
7.运行
```
cd kratos-demo/cmd
go build
./cmd -conf ../configs
```
打开浏览器访问:[http://localhost:8000/kratos-demo/start](http://localhost:8000/kratos-demo/start),你会看到输出了`Golang 大法好 !!!`
[kratos工具](kratos-tool.md)
-------------
[文档目录树](summary.md)

@ -0,0 +1,15 @@
#### dashboard
> 监控模版,针对服务框架内的监控指标的UI展示。
##### Requirments
- [Grafana](https://grafana.com) >= v6.1.4
- [Prometheus](https://prometheus.io) >= 2.x
##### Quick start
1. 搭建grafana
2. 导入`prometheus.json`文件
3. 修改对应的`Data source`
4. 保存

File diff suppressed because it is too large Load Diff

@ -16,7 +16,7 @@ type RateLimiter struct {
logTime int64 logTime int64
} }
// New return a ratelimit middleware. // NewRateLimiter return a ratelimit middleware.
func NewRateLimiter(conf *bbr.Config) (s *RateLimiter) { func NewRateLimiter(conf *bbr.Config) (s *RateLimiter) {
return &RateLimiter{ return &RateLimiter{
group: bbr.NewGroup(conf), group: bbr.NewGroup(conf),

@ -5,9 +5,9 @@
package blademaster package blademaster
import ( import (
"net/url" "net/url"
"strings" "strings"
"unicode" "unicode"
) )
// Param is a single URL parameter, consisting of a key and a value. // Param is a single URL parameter, consisting of a key and a value.

@ -2,6 +2,7 @@ package zipkin
import ( import (
"fmt" "fmt"
protogen "github.com/bilibili/kratos/pkg/net/trace/proto"
"time" "time"
"github.com/bilibili/kratos/pkg/net/trace" "github.com/bilibili/kratos/pkg/net/trace"
@ -30,7 +31,6 @@ func (r *report) WriteSpan(raw *trace.Span) (err error) {
spanID := model.ID(ctx.SpanID) spanID := model.ID(ctx.SpanID)
parentID := model.ID(ctx.ParentID) parentID := model.ID(ctx.ParentID)
tags := raw.Tags() tags := raw.Tags()
logs := raw.Logs()
span := model.SpanModel{ span := model.SpanModel{
SpanContext: model.SpanContext{ SpanContext: model.SpanContext{
TraceID: traceID, TraceID: traceID,
@ -40,7 +40,7 @@ func (r *report) WriteSpan(raw *trace.Span) (err error) {
Name: raw.OperationName(), Name: raw.OperationName(),
Timestamp: raw.StartTime(), Timestamp: raw.StartTime(),
Duration: raw.Duration(), Duration: raw.Duration(),
Tags: make(map[string]string, len(tags)+len(logs)), Tags: make(map[string]string, len(tags)),
} }
span.LocalEndpoint = &model.Endpoint{ServiceName: raw.ServiceName()} span.LocalEndpoint = &model.Endpoint{ServiceName: raw.ServiceName()}
for _, tag := range tags { for _, tag := range tags {
@ -65,13 +65,32 @@ func (r *report) WriteSpan(raw *trace.Span) (err error) {
} }
} }
} }
for _, lg := range logs { //log save to zipkin annotation
span.Tags[lg.Key] = string(lg.Value) span.Annotations = r.converLogsToAnnotations(raw.Logs())
}
r.rpt.Send(span) r.rpt.Send(span)
return return
} }
func (r *report) converLogsToAnnotations(logs []*protogen.Log) (annotations []model.Annotation) {
annotations = make([]model.Annotation, 0, len(annotations))
for _, lg := range logs {
annotations = append(annotations, r.converLogToAnnotation(lg)...)
}
return annotations
}
func (r *report) converLogToAnnotation(log *protogen.Log) (annotations []model.Annotation) {
annotations = make([]model.Annotation, 0, len(log.Fields))
for _, field := range log.Fields {
val := string(field.Value)
annotation := model.Annotation{
Timestamp: time.Unix(0, log.Timestamp),
Value: field.Key + " : " + val,
}
annotations = append(annotations, annotation)
}
return annotations
}
// Close close the report. // Close close the report.
func (r *report) Close() error { func (r *report) Close() error {
return r.rpt.Close() return r.rpt.Close()

@ -37,6 +37,7 @@ func TestZipkin(t *testing.T) {
t2 := trace.NewTracer("service2", report, true) t2 := trace.NewTracer("service2", report, true)
sp1 := t1.New("option_1") sp1 := t1.New("option_1")
sp2 := sp1.Fork("service3", "opt_client") sp2 := sp1.Fork("service3", "opt_client")
sp2.SetLog(trace.Log("log_k","log_v"))
// inject // inject
header := make(http.Header) header := make(http.Header)
t1.Inject(sp2, trace.HTTPFormat, header) t1.Inject(sp2, trace.HTTPFormat, header)

@ -142,8 +142,7 @@ func main() {
httpSrv := http.New(svc) httpSrv := http.New(svc)
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for { for s := range c {
s := <-c
log.Info("get a signal %s", s.String()) log.Info("get a signal %s", s.String())
switch s { switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:

Loading…
Cancel
Save