|
1 |
| -# Tarsgo Document |
| 1 | +# TarsGo Document |
2 | 2 | [点我查看中文版](README.zh.md)
|
3 | 3 | ## About
|
4 | 4 | - Tarsgo is high performance RPC framework in Golang programing language using the tars protocol.
|
|
9 | 9 | - Learn more about the whole Tars architecture and design at [Introduction](https://github.com/TarsCloud/Tars/blob/master/Introduction.en.md).
|
10 | 10 |
|
11 | 11 |
|
12 |
| -## Functional characteristics |
13 |
| -- Tars2go tool: tars file is automatically generated and converted into Go language, contains RPC server/client code; implemented in Go. |
14 |
| -- Serialization and deserialization of tars in Go. |
15 |
| -- The server supports heartbeat report, stat monitoring report, custom command processing, basic logging. |
16 |
| -- The client supports direct connection and route access, automatic reconnection, periodic refresh of node status, and also support for UDP/TCP protocol. |
17 |
| -- The support of remote log. |
18 |
| -- The support of property report. |
| 12 | +## Function & features |
| 13 | +- Tars2go tool: tars file is automatically generated and converted into Go language, contains RPC server/client code; |
| 14 | +- Serialization and deserialization of tars protocol in Go. |
| 15 | +- Auto service discovery. |
| 16 | +- TCP/UDP/Http server & Client. |
| 17 | +- The support of local logging and remote logging. |
| 18 | +- The support of statistical reporting, property statistics,and anormaly reporting. |
19 | 19 | - The support of set division.
|
20 | 20 | - The support of protocol buffers. See more in [pb2tarsgo](tars/tools/pb2tarsgo/README.md)
|
21 |
| - |
| 21 | +- The support of filter. |
| 22 | +- The support of zipkin opentracing. |
22 | 23 |
|
23 | 24 |
|
24 | 25 | ## Install
|
@@ -62,10 +63,9 @@ module TestApp
|
62 | 63 | #### 1.2 compile interface definition file
|
63 | 64 |
|
64 | 65 | ##### 1.2.1 build tars2go
|
65 |
| -Compile the tars2go tools and copy tars2go binary to into a directory in your $PATH. |
| 66 | +Compile and install the tars2go tools. |
66 | 67 |
|
67 |
| - cd $GOPATH/src/github.com/TarsCloud/TarsGo/tars/tools/tars2go && go build . |
68 |
| - cp tarsgo $GOPTAH/bin |
| 68 | + go install $GOPATH/src/github.com/TarsCloud/TarsGo/tars/tools/tars2go |
69 | 69 |
|
70 | 70 | ##### 1.2.2 compile the tars file and translate into go file
|
71 | 71 | tars2go --outdir=./vendor hello.tars
|
@@ -721,3 +721,146 @@ const (
|
721 | 721 |
|
722 | 722 | ```
|
723 | 723 |
|
| 724 | +### 11 HTTP Support |
| 725 | + |
| 726 | +`tars.TarsHttpMux` is multiplexer like [http.ServeMux](https://golang.org/pkg/net/http/#ServeMux),the `pattern` parameter is used as the interface name in monitoring report. |
| 727 | + |
| 728 | +Here is a sample of http server: |
| 729 | + |
| 730 | +```go |
| 731 | +package main |
| 732 | + |
| 733 | +import ( |
| 734 | + "net/http" |
| 735 | + "github.com/TarsCloud/TarsGo/tars" |
| 736 | +) |
| 737 | + |
| 738 | +func main() { |
| 739 | + mux := &tars.TarsHttpMux{} |
| 740 | + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { |
| 741 | + w.Write([]byte("Hello tafgo")) |
| 742 | + }) |
| 743 | + |
| 744 | + cfg := tars.GetServerConfig() |
| 745 | + tars.AddHttpServant(mux, cfg.App+"."+cfg.Server+".HttpObj") //Register http server |
| 746 | + tars.Run() |
| 747 | +} |
| 748 | + |
| 749 | + |
| 750 | +``` |
| 751 | + |
| 752 | +### 12 Using Context |
| 753 | +### context |
| 754 | +In the past, TarsGo did not use context in the generated client code, or in the implementation code passed in by the user. This makes us want to pass some framework information, such as client ip, port, etc., or the user passes some information about the call chain to the framework, which is difficult to implement. Through a refactoring of the interface, the context is supported, and the these information will be implemented through the context. This refactoring is designed to be compatible with older user behavior and is fully compatible. |
| 755 | + |
| 756 | + |
| 757 | +Server use context |
| 758 | + |
| 759 | +```go |
| 760 | +type ContextTestImp struct { |
| 761 | +} |
| 762 | +//only need to add ctx context.Context parameter |
| 763 | +func (imp *ContextTestImp) Add(ctx context.Context, a int32, b int32, c *int32) (int32, error) { |
| 764 | + //We can use context to get some usefull infomation we need ,such Client ,ip ,port and tracing infomation |
| 765 | + //read more detail under tars/util/current |
| 766 | + ip, ok := current.GetClientIPFromContext(ctx) |
| 767 | + if !ok { |
| 768 | + logger.Error("Error getting ip from context") |
| 769 | + } |
| 770 | + return 0, nil |
| 771 | +} |
| 772 | +//just change AddServant into AddServantWithContext |
| 773 | +app.AddServantWithContext(imp, cfg.App+"."+cfg.Server+".ContextTestObj") |
| 774 | +``` |
| 775 | + |
| 776 | +Client use context |
| 777 | + |
| 778 | +```go |
| 779 | + |
| 780 | + ctx := context.Background() |
| 781 | + c := make(map[string]string) |
| 782 | + c["a"] = "b" |
| 783 | +// juse change app.Add into app.AddWithContext, now u can pass context to framework, |
| 784 | +//if u want to setting request package's context,u can pass a optional parameter ,just like c,which is ...[string]string |
| 785 | + ret, err := app.AddWithContext(ctx, i, i*2, &out, c) |
| 786 | + |
| 787 | +``` |
| 788 | +Read full demo client and server under examples/ContextTestServer |
| 789 | + |
| 790 | + |
| 791 | +### 13 filter & zipkin plugin |
| 792 | +For supporting writing plugin,we add filter to the framework. We have client filter and server filter. |
| 793 | + |
| 794 | +```go |
| 795 | +//ServerFilter ,dispatch and f is passed as parameter , for dispatching user's implement. |
| 796 | +//req and resp is |
| 797 | +type ServerFilter func(ctx context.Context, d Dispatch, f interface{}, req *requestf.RequestPacket, resp *requestf.ResponsePacket, withContext bool) (err error) |
| 798 | +// |
| 799 | +type ClientFilter func(ctx context.Context, msg *Message, invoke Invoke, timeout time.Duration) (err error) |
| 800 | +//RegisterServerFilter registers the server side filter |
| 801 | +//func RegisterServerFilter(f ServerFilter) |
| 802 | +//RegisterClientFilter registers the client side filter |
| 803 | +//func RegisterClientFilter(f ClientFilter) |
| 804 | + |
| 805 | +``` |
| 806 | + |
| 807 | +Having these filters ,now we can add opentracing for every request. |
| 808 | +Let's take a look at client side filter for opentracing. |
| 809 | +```go |
| 810 | +//ZipkinClientFilter returns a client side tars filter, for hooking zipking opentracing. |
| 811 | +func ZipkinClientFilter() tars.ClientFilter { |
| 812 | + return func(ctx context.Context, msg *tars.Message, invoke tars.Invoke, timeout time.Duration) (err error) { |
| 813 | + var pCtx opentracing.SpanContext |
| 814 | + req := msg.Req |
| 815 | + //If span context is passed in the context, we use this context as parent span ,else start a new span. |
| 816 | + //The method name of the rpc request , is used as span's name . |
| 817 | + if parent := opentracing.SpanFromContext(ctx); parent != nil { |
| 818 | + pCtx = parent.Context() |
| 819 | + } |
| 820 | + cSpan := opentracing.GlobalTracer().StartSpan( |
| 821 | + req.SFuncName, |
| 822 | + opentracing.ChildOf(pCtx), |
| 823 | + ext.SpanKindRPCClient, |
| 824 | + ) |
| 825 | + defer cSpan.Finish() |
| 826 | + cfg := tars.GetServerConfig() |
| 827 | + |
| 828 | + //set additional information for the span ,like method, interface, protocol, vesion, ip and port etc. |
| 829 | + cSpan.SetTag("client.ipv4", cfg.LocalIP) |
| 830 | + cSpan.SetTag("tars.interface", req.SServantName) |
| 831 | + cSpan.SetTag("tars.method", req.SFuncName) |
| 832 | + cSpan.SetTag("tars.protocol", "tars") |
| 833 | + cSpan.SetTag("tars.client.version", tars.TarsVersion) |
| 834 | + |
| 835 | + //inject the span context into the request package's status ,which is map[string]string |
| 836 | + if req.Status != nil { |
| 837 | + err = opentracing.GlobalTracer().Inject(cSpan.Context(), opentracing.TextMap, opentracing.TextMapCarrier(req.Status)) |
| 838 | + if err != nil { |
| 839 | + logger.Error("inject span to status error:", err) |
| 840 | + } |
| 841 | + } else { |
| 842 | + s := make(map[string]string) |
| 843 | + err = opentracing.GlobalTracer().Inject(cSpan.Context(), opentracing.TextMap, opentracing.TextMapCarrier(s)) |
| 844 | + if err != nil { |
| 845 | + logger.Error("inject span to status error:", err) |
| 846 | + } else { |
| 847 | + req.Status = s |
| 848 | + } |
| 849 | + } |
| 850 | + //Nothing tho change , just invoke the request. |
| 851 | + err = invoke(ctx, msg, timeout) |
| 852 | + if err != nil { |
| 853 | + //invoke error ,logging the error information to the span. |
| 854 | + ext.Error.Set(cSpan, true) |
| 855 | + cSpan.LogFields(oplog.String("event", "error"), oplog.String("message", err.Error())) |
| 856 | + } |
| 857 | + |
| 858 | + return err |
| 859 | + } |
| 860 | +``` |
| 861 | +
|
| 862 | +
|
| 863 | +Server will add a filters ,which exact the span context from the reqeust pacakge's status, and start a new span. |
| 864 | +
|
| 865 | +Reqed more under TarsGo/tars/plugin/zipkintracing |
| 866 | +For client side and server side example code , read ZipkinTraceClient & ZipkinTraceServer under the examples. |
0 commit comments