diff --git a/protocol/dubbo/client.go b/protocol/dubbo/client.go deleted file mode 100644 index 630e9a76862d7d5f9be6caeb6a678936f940ac40..0000000000000000000000000000000000000000 --- a/protocol/dubbo/client.go +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "math/rand" -// "strings" -// "sync" -// "time" -//) -// -//import ( -// hessian "github.com/apache/dubbo-go-hessian2" -// "github.com/dubbogo/getty" -// gxsync "github.com/dubbogo/gost/sync" -// perrors "github.com/pkg/errors" -// "go.uber.org/atomic" -// "gopkg.in/yaml.v2" -//) -// -//import ( -// "github.com/apache/dubbo-go/common" -// "github.com/apache/dubbo-go/common/constant" -// "github.com/apache/dubbo-go/common/logger" -// "github.com/apache/dubbo-go/config" -//) -// -//var ( -// errInvalidCodecType = perrors.New("illegal CodecType") -// errInvalidAddress = perrors.New("remote address invalid or empty") -// errSessionNotExist = perrors.New("session not exist") -// errClientClosed = perrors.New("client closed") -// errClientReadTimeout = perrors.New("client read timeout") -// -// clientConf *ClientConfig -// clientGrpool *gxsync.TaskPool -//) -// -//func init() { -// -// // load clientconfig from consumer_config -// // default use dubbo -// consumerConfig := config.GetConsumerConfig() -// if consumerConfig.ApplicationConfig == nil { -// return -// } -// protocolConf := config.GetConsumerConfig().ProtocolConf -// defaultClientConfig := GetDefaultClientConfig() -// if protocolConf == nil { -// logger.Info("protocol_conf default use dubbo config") -// } else { -// dubboConf := protocolConf.(map[interface{}]interface{})[DUBBO] -// if dubboConf == nil { -// logger.Warnf("dubboConf is nil") -// return -// } -// dubboConfByte, err := yaml.Marshal(dubboConf) -// if err != nil { -// panic(err) -// } -// err = yaml.Unmarshal(dubboConfByte, &defaultClientConfig) -// if err != nil { -// panic(err) -// } -// } -// clientConf = &defaultClientConfig -// if err := clientConf.CheckValidity(); err != nil { -// logger.Warnf("[CheckValidity] error: %v", err) -// return -// } -// setClientGrpool() -// -// rand.Seed(time.Now().UnixNano()) -//} -// -//// SetClientConf ... -//func SetClientConf(c ClientConfig) { -// clientConf = &c -// err := clientConf.CheckValidity() -// if err != nil { -// logger.Warnf("[ClientConfig CheckValidity] error: %v", err) -// return -// } -// setClientGrpool() -//} -// -//// GetClientConf ... -//func GetClientConf() ClientConfig { -// return *clientConf -//} -// -//func setClientGrpool() { -// if clientConf.GrPoolSize > 1 { -// clientGrpool = gxsync.NewTaskPool(gxsync.WithTaskPoolTaskPoolSize(clientConf.GrPoolSize), gxsync.WithTaskPoolTaskQueueLength(clientConf.QueueLen), -// gxsync.WithTaskPoolTaskQueueNumber(clientConf.QueueNumber)) -// } -//} -// -//// Options ... -//type Options struct { -// // connect timeout -// ConnectTimeout time.Duration -// // request timeout -// RequestTimeout time.Duration -//} -// -////AsyncCallbackResponse async response for dubbo -//type AsyncCallbackResponse struct { -// common.CallbackResponse -// Opts Options -// Cause error -// Start time.Time // invoke(call) start time == write start time -// ReadStart time.Time // read start time, write duration = ReadStart - Start -// Reply interface{} -//} -// -//// Client ... -//type Client struct { -// opts Options -// conf ClientConfig -// pool *gettyRPCClientPool -// sequence atomic.Uint64 -// -// pendingResponses *sync.Map -//} -// -//// NewClient ... -//func NewClient(opt Options) *Client { -// -// switch { -// case opt.ConnectTimeout == 0: -// opt.ConnectTimeout = 3 * time.Second -// fallthrough -// case opt.RequestTimeout == 0: -// opt.RequestTimeout = 3 * time.Second -// } -// -// // make sure that client request sequence is an odd number -// initSequence := uint64(rand.Int63n(time.Now().UnixNano())) -// if initSequence%2 == 0 { -// initSequence++ -// } -// -// c := &Client{ -// opts: opt, -// pendingResponses: new(sync.Map), -// conf: *clientConf, -// } -// c.sequence.Store(initSequence) -// c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) -// -// return c -//} -// -//// Request ... -//type Request struct { -// addr string -// svcUrl common.URL -// method string -// args interface{} -// atta map[string]string -//} -// -//// NewRequest ... -//func NewRequest(addr string, svcUrl common.URL, method string, args interface{}, atta map[string]string) *Request { -// return &Request{ -// addr: addr, -// svcUrl: svcUrl, -// method: method, -// args: args, -// atta: atta, -// } -//} -// -//// Response ... -//type Response struct { -// reply interface{} -// atta map[string]string -//} -// -//// NewResponse ... -//func NewResponse(reply interface{}, atta map[string]string) *Response { -// return &Response{ -// reply: reply, -// atta: atta, -// } -//} -// -//// CallOneway call one way -//func (c *Client) CallOneway(request *Request) error { -// -// return perrors.WithStack(c.call(CT_OneWay, request, NewResponse(nil, nil), nil)) -//} -// -//// Call if @response is nil, the transport layer will get the response without notify the invoker. -//func (c *Client) Call(request *Request, response *Response) error { -// -// ct := CT_TwoWay -// if response.reply == nil { -// ct = CT_OneWay -// } -// -// return perrors.WithStack(c.call(ct, request, response, nil)) -//} -// -//// AsyncCall ... -//func (c *Client) AsyncCall(request *Request, callback common.AsyncCallback, response *Response) error { -// -// return perrors.WithStack(c.call(CT_TwoWay, request, response, callback)) -//} -// -//func (c *Client) call(ct CallType, request *Request, response *Response, callback common.AsyncCallback) error { -// -// p := &DubboPackage{} -// p.Service.Path = strings.TrimPrefix(request.svcUrl.Path, "/") -// p.Service.Interface = request.svcUrl.GetParam(constant.INTERFACE_KEY, "") -// p.Service.Version = request.svcUrl.GetParam(constant.VERSION_KEY, "") -// p.Service.Group = request.svcUrl.GetParam(constant.GROUP_KEY, "") -// p.Service.Method = request.method -// -// p.Service.Timeout = c.opts.RequestTimeout -// var timeout = request.svcUrl.GetParam(strings.Join([]string{constant.METHOD_KEYS, request.method + constant.RETRIES_KEY}, "."), "") -// if len(timeout) != 0 { -// if t, err := time.ParseDuration(timeout); err == nil { -// p.Service.Timeout = t -// } -// } -// -// p.Header.SerialID = byte(S_Dubbo) -// p.Body = hessian.NewRequest(request.args, request.atta) -// -// var rsp *PendingResponse -// if ct != CT_OneWay { -// p.Header.Type = hessian.PackageRequest_TwoWay -// rsp = NewPendingResponse() -// rsp.response = response -// rsp.callback = callback -// } else { -// p.Header.Type = hessian.PackageRequest -// } -// -// var ( -// err error -// session getty.Session -// conn *gettyRPCClient -// ) -// conn, session, err = c.selectSession(request.addr) -// if err != nil { -// return perrors.WithStack(err) -// } -// if session == nil { -// return errSessionNotExist -// } -// defer func() { -// if err == nil { -// c.pool.put(conn) -// return -// } -// conn.close() -// }() -// -// if err = c.transfer(session, p, rsp); err != nil { -// return perrors.WithStack(err) -// } -// -// if ct == CT_OneWay || callback != nil { -// return nil -// } -// -// select { -// case <-getty.GetTimeWheel().After(c.opts.RequestTimeout): -// c.removePendingResponse(SequenceType(rsp.seq)) -// return perrors.WithStack(errClientReadTimeout) -// case <-rsp.done: -// err = rsp.err -// } -// -// return perrors.WithStack(err) -//} -// -//// Close ... -//func (c *Client) Close() { -// if c.pool != nil { -// c.pool.close() -// } -// c.pool = nil -//} -// -//func (c *Client) selectSession(addr string) (*gettyRPCClient, getty.Session, error) { -// rpcClient, err := c.pool.getGettyRpcClient(DUBBO, addr) -// if err != nil { -// return nil, nil, perrors.WithStack(err) -// } -// return rpcClient, rpcClient.selectSession(), nil -//} -// -//func (c *Client) heartbeat(session getty.Session) error { -// return c.transfer(session, nil, NewPendingResponse()) -//} -// -//func (c *Client) transfer(session getty.Session, pkg *DubboPackage, -// rsp *PendingResponse) error { -// -// var ( -// sequence uint64 -// err error -// ) -// -// sequence = c.sequence.Add(1) -// -// if pkg == nil { -// pkg = &DubboPackage{} -// pkg.Body = hessian.NewRequest([]interface{}{}, nil) -// pkg.Body = []interface{}{} -// pkg.Header.Type = hessian.PackageHeartbeat -// pkg.Header.SerialID = byte(S_Dubbo) -// } -// pkg.Header.ID = int64(sequence) -// -// // cond1 -// if rsp != nil { -// rsp.seq = sequence -// c.addPendingResponse(rsp) -// } -// -// err = session.WritePkg(pkg, c.opts.RequestTimeout) -// if err != nil { -// c.removePendingResponse(SequenceType(rsp.seq)) -// } else if rsp != nil { // cond2 -// // cond2 should not merged with cond1. cause the response package may be returned very -// // soon and it will be handled by other goroutine. -// rsp.readStart = time.Now() -// } -// -// return perrors.WithStack(err) -//} -// -//func (c *Client) addPendingResponse(pr *PendingResponse) { -// c.pendingResponses.Store(SequenceType(pr.seq), pr) -//} -// -//func (c *Client) removePendingResponse(seq SequenceType) *PendingResponse { -// if c.pendingResponses == nil { -// return nil -// } -// if presp, ok := c.pendingResponses.Load(seq); ok { -// c.pendingResponses.Delete(seq) -// return presp.(*PendingResponse) -// } -// return nil -//} diff --git a/protocol/dubbo/client_test.go b/protocol/dubbo/client_test.go deleted file mode 100644 index 4f5913c56f4c2d509b86de7b6fdf26ebee9e2727..0000000000000000000000000000000000000000 --- a/protocol/dubbo/client_test.go +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "bytes" -// "context" -// "sync" -// "testing" -// "time" -//) -// -//import ( -// hessian "github.com/apache/dubbo-go-hessian2" -// perrors "github.com/pkg/errors" -// "github.com/stretchr/testify/assert" -//) -// -//import ( -// "github.com/apache/dubbo-go/common" -// "github.com/apache/dubbo-go/common/proxy/proxy_factory" -// "github.com/apache/dubbo-go/protocol" -//) -// -//func TestClient_CallOneway(t *testing.T) { -// proto, url := InitTest(t) -// -// c := &Client{ -// pendingResponses: new(sync.Map), -// conf: *clientConf, -// opts: Options{ -// ConnectTimeout: 3e9, -// RequestTimeout: 6e9, -// }, -// } -// c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) -// -// //user := &User{} -// err := c.CallOneway(NewRequest("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, nil)) -// assert.NoError(t, err) -// -// // destroy -// proto.Destroy() -//} -// -//func TestClient_Call(t *testing.T) { -// proto, url := InitTest(t) -// -// c := &Client{ -// pendingResponses: new(sync.Map), -// conf: *clientConf, -// opts: Options{ -// ConnectTimeout: 3e9, -// RequestTimeout: 10e9, -// }, -// } -// c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) -// -// var ( -// user *User -// err error -// ) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetBigPkg", []interface{}{nil}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.NotEqual(t, "", user.Id) -// assert.NotEqual(t, "", user.Name) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{Id: "1", Name: "username"}, *user) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser0", []interface{}{"1", nil, "username"}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{Id: "1", Name: "username"}, *user) -// -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser1", []interface{}{}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser2", []interface{}{}, nil), NewResponse(user, nil)) -// assert.EqualError(t, err, "error") -// -// user2 := []interface{}{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser3", []interface{}{}, nil), NewResponse(&user2, nil)) -// assert.NoError(t, err) -// assert.Equal(t, &User{Id: "1", Name: "username"}, user2[0]) -// -// user2 = []interface{}{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser4", []interface{}{[]interface{}{"1", "username"}}, nil), NewResponse(&user2, nil)) -// assert.NoError(t, err) -// assert.Equal(t, &User{Id: "1", Name: "username"}, user2[0]) -// -// user3 := map[interface{}]interface{}{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser5", []interface{}{map[interface{}]interface{}{"id": "1", "name": "username"}}, nil), NewResponse(&user3, nil)) -// assert.NoError(t, err) -// assert.NotNil(t, user3) -// assert.Equal(t, &User{Id: "1", Name: "username"}, user3["key"]) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser6", []interface{}{0}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{Id: "", Name: ""}, *user) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser6", []interface{}{1}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{Id: "1", Name: ""}, *user) -// -// // destroy -// proto.Destroy() -//} -// -//func TestClient_AsyncCall(t *testing.T) { -// proto, url := InitTest(t) -// -// c := &Client{ -// pendingResponses: new(sync.Map), -// conf: *clientConf, -// opts: Options{ -// ConnectTimeout: 3e9, -// RequestTimeout: 6e9, -// }, -// } -// c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) -// -// user := &User{} -// lock := sync.Mutex{} -// lock.Lock() -// err := c.AsyncCall(NewRequest("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, nil), func(response common.CallbackResponse) { -// r := response.(AsyncCallbackResponse) -// assert.Equal(t, User{Id: "1", Name: "username"}, *r.Reply.(*Response).reply.(*User)) -// lock.Unlock() -// }, NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{}, *user) -// -// // destroy -// lock.Lock() -// proto.Destroy() -// lock.Unlock() -//} -// -//func InitTest(t *testing.T) (protocol.Protocol, common.URL) { -// -// hessian.RegisterPOJO(&User{}) -// -// methods, err := common.ServiceMap.Register("dubbo", &UserProvider{}) -// assert.NoError(t, err) -// assert.Equal(t, "GetBigPkg,GetUser,GetUser0,GetUser1,GetUser2,GetUser3,GetUser4,GetUser5,GetUser6", methods) -// -// // config -// SetClientConf(ClientConfig{ -// ConnectionNum: 2, -// HeartbeatPeriod: "5s", -// SessionTimeout: "20s", -// PoolTTL: 600, -// PoolSize: 64, -// GettySessionParam: GettySessionParam{ -// CompressEncoding: false, -// TcpNoDelay: true, -// TcpKeepAlive: true, -// KeepAlivePeriod: "120s", -// TcpRBufSize: 262144, -// TcpWBufSize: 65536, -// PkgWQSize: 512, -// TcpReadTimeout: "4s", -// TcpWriteTimeout: "5s", -// WaitTimeout: "1s", -// MaxMsgLen: 10240000000, -// SessionName: "client", -// }, -// }) -// assert.NoError(t, clientConf.CheckValidity()) -// SetServerConfig(ServerConfig{ -// SessionNumber: 700, -// SessionTimeout: "20s", -// GettySessionParam: GettySessionParam{ -// CompressEncoding: false, -// TcpNoDelay: true, -// TcpKeepAlive: true, -// KeepAlivePeriod: "120s", -// TcpRBufSize: 262144, -// TcpWBufSize: 65536, -// PkgWQSize: 512, -// TcpReadTimeout: "1s", -// TcpWriteTimeout: "5s", -// WaitTimeout: "1s", -// MaxMsgLen: 10240000000, -// SessionName: "server", -// }}) -// assert.NoError(t, srvConf.CheckValidity()) -// -// // Export -// proto := GetProtocol() -// url, err := common.NewURL("dubbo://127.0.0.1:20000/UserProvider?anyhost=true&" + -// "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" + -// "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&" + -// "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" + -// "side=provider&timeout=3000×tamp=1556509797245&bean.name=UserProvider") -// assert.NoError(t, err) -// proto.Export(&proxy_factory.ProxyInvoker{ -// BaseInvoker: *protocol.NewBaseInvoker(url), -// }) -// -// time.Sleep(time.Second * 2) -// -// return proto, url -//} -// -//////////////////////////////////// -//// provider -//////////////////////////////////// -// -//type ( -// User struct { -// Id string `json:"id"` -// Name string `json:"name"` -// } -// -// UserProvider struct { -// user map[string]User -// } -//) -// -//// size:4801228 -//func (u *UserProvider) GetBigPkg(ctx context.Context, req []interface{}, rsp *User) error { -// argBuf := new(bytes.Buffer) -// for i := 0; i < 4000; i++ { -// argBuf.WriteString("击鼓其镗,踊跃用兵。土国城漕,我独南行。从孙子仲,平陈与宋。不我以归,忧心有忡。爰居爰处?爰丧其马?于以求之?于林之下。死生契阔,与子成说。执子之手,与子偕老。于嗟阔兮,不我活兮。于嗟洵兮,不我信兮。") -// argBuf.WriteString("击鼓其镗,踊跃用兵。土国城漕,我独南行。从孙子仲,平陈与宋。不我以归,忧心有忡。爰居爰处?爰丧其马?于以求之?于林之下。死生契阔,与子成说。执子之手,与子偕老。于嗟阔兮,不我活兮。于嗟洵兮,不我信兮。") -// } -// rsp.Id = argBuf.String() -// rsp.Name = argBuf.String() -// return nil -//} -// -//func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error { -// rsp.Id = req[0].(string) -// rsp.Name = req[1].(string) -// return nil -//} -// -//func (u *UserProvider) GetUser0(id string, k *User, name string) (User, error) { -// return User{Id: id, Name: name}, nil -//} -// -//func (u *UserProvider) GetUser1() error { -// return nil -//} -// -//func (u *UserProvider) GetUser2() error { -// return perrors.New("error") -//} -// -//func (u *UserProvider) GetUser3(rsp *[]interface{}) error { -// *rsp = append(*rsp, User{Id: "1", Name: "username"}) -// return nil -//} -// -//func (u *UserProvider) GetUser4(ctx context.Context, req []interface{}) ([]interface{}, error) { -// -// return []interface{}{User{Id: req[0].([]interface{})[0].(string), Name: req[0].([]interface{})[1].(string)}}, nil -//} -// -//func (u *UserProvider) GetUser5(ctx context.Context, req []interface{}) (map[interface{}]interface{}, error) { -// return map[interface{}]interface{}{"key": User{Id: req[0].(map[interface{}]interface{})["id"].(string), Name: req[0].(map[interface{}]interface{})["name"].(string)}}, nil -//} -// -//func (u *UserProvider) GetUser6(id int64) (*User, error) { -// if id == 0 { -// return nil, nil -// } -// return &User{Id: "1"}, nil -//} -// -//func (u *UserProvider) Reference() string { -// return "UserProvider" -//} -// -//func (u User) JavaClassName() string { -// return "com.ikurento.user.User" -//} diff --git a/protocol/dubbo/codec.go b/protocol/dubbo/codec.go deleted file mode 100644 index 8dd91c2d31e898def02d94ec0539e7a8acd2b818..0000000000000000000000000000000000000000 --- a/protocol/dubbo/codec.go +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "bufio" -// "bytes" -// "fmt" -// "time" -//) -// -//import ( -// "github.com/apache/dubbo-go-hessian2" -// "github.com/apache/dubbo-go/common" -// perrors "github.com/pkg/errors" -//) -// -////SerialID serial ID -//type SerialID byte -// -//const ( -// // S_Dubbo dubbo serial id -// S_Dubbo SerialID = 2 -//) -// -////CallType call type -//type CallType int32 -// -//const ( -// // CT_UNKNOWN unknown call type -// CT_UNKNOWN CallType = 0 -// // CT_OneWay call one way -// CT_OneWay CallType = 1 -// // CT_TwoWay call in request/response -// CT_TwoWay CallType = 2 -//) -// -////////////////////////////////////////////// -//// dubbo package -////////////////////////////////////////////// -// -//// SequenceType ... -//type SequenceType int64 -// -//// DubboPackage ... -//type DubboPackage struct { -// Header hessian.DubboHeader -// Service hessian.Service -// Body interface{} -// Err error -//} -// -//func (p DubboPackage) String() string { -// return fmt.Sprintf("DubboPackage: Header-%v, Path-%v, Body-%v", p.Header, p.Service, p.Body) -//} -// -//// Marshal ... -//func (p *DubboPackage) Marshal() (*bytes.Buffer, error) { -// codec := hessian.NewHessianCodec(nil) -// -// pkg, err := codec.Write(p.Service, p.Header, p.Body) -// if err != nil { -// return nil, perrors.WithStack(err) -// } -// -// return bytes.NewBuffer(pkg), nil -//} -// -//// Unmarshal ... -//func (p *DubboPackage) Unmarshal(buf *bytes.Buffer, opts ...interface{}) error { -// // fix issue https://github.com/apache/dubbo-go/issues/380 -// bufLen := buf.Len() -// if bufLen < hessian.HEADER_LENGTH { -// return perrors.WithStack(hessian.ErrHeaderNotEnough) -// } -// -// codec := hessian.NewHessianCodec(bufio.NewReaderSize(buf, bufLen)) -// -// // read header -// err := codec.ReadHeader(&p.Header) -// if err != nil { -// return perrors.WithStack(err) -// } -// -// if len(opts) != 0 { // for client -// client, ok := opts[0].(*Client) -// if !ok { -// return perrors.Errorf("opts[0] is not of type *Client") -// } -// -// if p.Header.Type&hessian.PackageRequest != 0x00 { -// // size of this array must be '7' -// // https://github.com/apache/dubbo-go-hessian2/blob/master/request.go#L272 -// p.Body = make([]interface{}, 7) -// } else { -// pendingRsp, ok := client.pendingResponses.Load(SequenceType(p.Header.ID)) -// if !ok { -// return perrors.Errorf("client.GetPendingResponse(%v) = nil", p.Header.ID) -// } -// p.Body = &hessian.Response{RspObj: pendingRsp.(*PendingResponse).response.reply} -// } -// } -// -// // read body -// err = codec.ReadBody(p.Body) -// return perrors.WithStack(err) -//} -// -////////////////////////////////////////////// -//// PendingResponse -////////////////////////////////////////////// -// -//// PendingResponse ... -//type PendingResponse struct { -// seq uint64 -// err error -// start time.Time -// readStart time.Time -// callback common.AsyncCallback -// response *Response -// done chan struct{} -//} -// -//// NewPendingResponse ... -//func NewPendingResponse() *PendingResponse { -// return &PendingResponse{ -// start: time.Now(), -// response: &Response{}, -// done: make(chan struct{}), -// } -//} -// -//// GetCallResponse ... -//func (r PendingResponse) GetCallResponse() common.CallbackResponse { -// return AsyncCallbackResponse{ -// Cause: r.err, -// Start: r.start, -// ReadStart: r.readStart, -// Reply: r.response, -// } -//} diff --git a/protocol/dubbo/codec_test.go b/protocol/dubbo/codec_test.go deleted file mode 100644 index c9599da6c76799e05dc4b96a00b958409bcc846b..0000000000000000000000000000000000000000 --- a/protocol/dubbo/codec_test.go +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "bytes" -// "testing" -// "time" -//) -// -//import ( -// hessian "github.com/apache/dubbo-go-hessian2" -// perrors "github.com/pkg/errors" -// "github.com/stretchr/testify/assert" -//) -// -//func TestDubboPackage_MarshalAndUnmarshal(t *testing.T) { -// pkg := &DubboPackage{} -// pkg.Body = []interface{}{"a"} -// pkg.Header.Type = hessian.PackageHeartbeat -// pkg.Header.SerialID = byte(S_Dubbo) -// pkg.Header.ID = 10086 -// -// // heartbeat -// data, err := pkg.Marshal() -// assert.NoError(t, err) -// -// pkgres := &DubboPackage{} -// pkgres.Body = []interface{}{} -// err = pkgres.Unmarshal(data) -// assert.NoError(t, err) -// assert.Equal(t, hessian.PackageHeartbeat|hessian.PackageRequest|hessian.PackageRequest_TwoWay, pkgres.Header.Type) -// assert.Equal(t, byte(S_Dubbo), pkgres.Header.SerialID) -// assert.Equal(t, int64(10086), pkgres.Header.ID) -// assert.Equal(t, 0, len(pkgres.Body.([]interface{}))) -// -// // request -// pkg.Header.Type = hessian.PackageRequest -// pkg.Service.Interface = "Service" -// pkg.Service.Path = "path" -// pkg.Service.Version = "2.6" -// pkg.Service.Method = "Method" -// pkg.Service.Timeout = time.Second -// data, err = pkg.Marshal() -// assert.NoError(t, err) -// -// pkgres = &DubboPackage{} -// pkgres.Body = make([]interface{}, 7) -// err = pkgres.Unmarshal(data) -// assert.NoError(t, err) -// assert.Equal(t, hessian.PackageRequest, pkgres.Header.Type) -// assert.Equal(t, byte(S_Dubbo), pkgres.Header.SerialID) -// assert.Equal(t, int64(10086), pkgres.Header.ID) -// assert.Equal(t, "2.0.2", pkgres.Body.([]interface{})[0]) -// assert.Equal(t, "path", pkgres.Body.([]interface{})[1]) -// assert.Equal(t, "2.6", pkgres.Body.([]interface{})[2]) -// assert.Equal(t, "Method", pkgres.Body.([]interface{})[3]) -// assert.Equal(t, "Ljava/lang/String;", pkgres.Body.([]interface{})[4]) -// assert.Equal(t, []interface{}{"a"}, pkgres.Body.([]interface{})[5]) -// assert.Equal(t, map[string]string{"dubbo": "2.0.2", "interface": "Service", "path": "path", "timeout": "1000", "version": "2.6"}, pkgres.Body.([]interface{})[6]) -//} -// -//func TestIssue380(t *testing.T) { -// pkg := &DubboPackage{} -// buf := bytes.NewBuffer([]byte("hello")) -// err := pkg.Unmarshal(buf) -// assert.True(t, perrors.Cause(err) == hessian.ErrHeaderNotEnough) -//} diff --git a/protocol/dubbo/config.go b/protocol/dubbo/config.go deleted file mode 100644 index f00931e00fb011e30a60f47d0cdd234446180534..0000000000000000000000000000000000000000 --- a/protocol/dubbo/config.go +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "time" -//) -// -//import ( -// "github.com/dubbogo/getty" -// perrors "github.com/pkg/errors" -//) -// -//type ( -// // GettySessionParam ... -// GettySessionParam struct { -// CompressEncoding bool `default:"false" yaml:"compress_encoding" json:"compress_encoding,omitempty"` -// TcpNoDelay bool `default:"true" yaml:"tcp_no_delay" json:"tcp_no_delay,omitempty"` -// TcpKeepAlive bool `default:"true" yaml:"tcp_keep_alive" json:"tcp_keep_alive,omitempty"` -// KeepAlivePeriod string `default:"180s" yaml:"keep_alive_period" json:"keep_alive_period,omitempty"` -// keepAlivePeriod time.Duration -// TcpRBufSize int `default:"262144" yaml:"tcp_r_buf_size" json:"tcp_r_buf_size,omitempty"` -// TcpWBufSize int `default:"65536" yaml:"tcp_w_buf_size" json:"tcp_w_buf_size,omitempty"` -// PkgWQSize int `default:"1024" yaml:"pkg_wq_size" json:"pkg_wq_size,omitempty"` -// TcpReadTimeout string `default:"1s" yaml:"tcp_read_timeout" json:"tcp_read_timeout,omitempty"` -// tcpReadTimeout time.Duration -// TcpWriteTimeout string `default:"5s" yaml:"tcp_write_timeout" json:"tcp_write_timeout,omitempty"` -// tcpWriteTimeout time.Duration -// WaitTimeout string `default:"7s" yaml:"wait_timeout" json:"wait_timeout,omitempty"` -// waitTimeout time.Duration -// MaxMsgLen int `default:"1024" yaml:"max_msg_len" json:"max_msg_len,omitempty"` -// SessionName string `default:"rpc" yaml:"session_name" json:"session_name,omitempty"` -// } -// -// // ServerConfig -// //Config holds supported types by the multiconfig package -// ServerConfig struct { -// // session -// SessionTimeout string `default:"60s" yaml:"session_timeout" json:"session_timeout,omitempty"` -// sessionTimeout time.Duration -// SessionNumber int `default:"1000" yaml:"session_number" json:"session_number,omitempty"` -// -// // grpool -// GrPoolSize int `default:"0" yaml:"gr_pool_size" json:"gr_pool_size,omitempty"` -// QueueLen int `default:"0" yaml:"queue_len" json:"queue_len,omitempty"` -// QueueNumber int `default:"0" yaml:"queue_number" json:"queue_number,omitempty"` -// -// // session tcp parameters -// GettySessionParam GettySessionParam `required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"` -// } -// -// // ClientConfig -// //Config holds supported types by the multiconfig package -// ClientConfig struct { -// ReconnectInterval int `default:"0" yaml:"reconnect_interval" json:"reconnect_interval,omitempty"` -// -// // session pool -// ConnectionNum int `default:"16" yaml:"connection_number" json:"connection_number,omitempty"` -// -// // heartbeat -// HeartbeatPeriod string `default:"15s" yaml:"heartbeat_period" json:"heartbeat_period,omitempty"` -// heartbeatPeriod time.Duration -// -// // session -// SessionTimeout string `default:"60s" yaml:"session_timeout" json:"session_timeout,omitempty"` -// sessionTimeout time.Duration -// -// // Connection Pool -// PoolSize int `default:"2" yaml:"pool_size" json:"pool_size,omitempty"` -// PoolTTL int `default:"180" yaml:"pool_ttl" json:"pool_ttl,omitempty"` -// -// // grpool -// GrPoolSize int `default:"0" yaml:"gr_pool_size" json:"gr_pool_size,omitempty"` -// QueueLen int `default:"0" yaml:"queue_len" json:"queue_len,omitempty"` -// QueueNumber int `default:"0" yaml:"queue_number" json:"queue_number,omitempty"` -// -// // session tcp parameters -// GettySessionParam GettySessionParam `required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"` -// } -//) -// -//// GetDefaultClientConfig ... -//func GetDefaultClientConfig() ClientConfig { -// return ClientConfig{ -// ReconnectInterval: 0, -// ConnectionNum: 16, -// HeartbeatPeriod: "30s", -// SessionTimeout: "180s", -// PoolSize: 4, -// PoolTTL: 600, -// GrPoolSize: 200, -// QueueLen: 64, -// QueueNumber: 10, -// GettySessionParam: GettySessionParam{ -// CompressEncoding: false, -// TcpNoDelay: true, -// TcpKeepAlive: true, -// KeepAlivePeriod: "180s", -// TcpRBufSize: 262144, -// TcpWBufSize: 65536, -// PkgWQSize: 512, -// TcpReadTimeout: "1s", -// TcpWriteTimeout: "5s", -// WaitTimeout: "1s", -// MaxMsgLen: 102400, -// SessionName: "client", -// }} -//} -// -//// GetDefaultServerConfig ... -//func GetDefaultServerConfig() ServerConfig { -// return ServerConfig{ -// SessionTimeout: "180s", -// SessionNumber: 700, -// GrPoolSize: 120, -// QueueNumber: 6, -// QueueLen: 64, -// GettySessionParam: GettySessionParam{ -// CompressEncoding: false, -// TcpNoDelay: true, -// TcpKeepAlive: true, -// KeepAlivePeriod: "180s", -// TcpRBufSize: 262144, -// TcpWBufSize: 65536, -// PkgWQSize: 512, -// TcpReadTimeout: "1s", -// TcpWriteTimeout: "5s", -// WaitTimeout: "1s", -// MaxMsgLen: 102400, -// SessionName: "server", -// }, -// } -//} -// -//// CheckValidity ... -//func (c *GettySessionParam) CheckValidity() error { -// var err error -// -// if c.keepAlivePeriod, err = time.ParseDuration(c.KeepAlivePeriod); err != nil { -// return perrors.WithMessagef(err, "time.ParseDuration(KeepAlivePeriod{%#v})", c.KeepAlivePeriod) -// } -// -// if c.tcpReadTimeout, err = time.ParseDuration(c.TcpReadTimeout); err != nil { -// return perrors.WithMessagef(err, "time.ParseDuration(TcpReadTimeout{%#v})", c.TcpReadTimeout) -// } -// -// if c.tcpWriteTimeout, err = time.ParseDuration(c.TcpWriteTimeout); err != nil { -// return perrors.WithMessagef(err, "time.ParseDuration(TcpWriteTimeout{%#v})", c.TcpWriteTimeout) -// } -// -// if c.waitTimeout, err = time.ParseDuration(c.WaitTimeout); err != nil { -// return perrors.WithMessagef(err, "time.ParseDuration(WaitTimeout{%#v})", c.WaitTimeout) -// } -// -// return nil -//} -// -//// CheckValidity ... -//func (c *ClientConfig) CheckValidity() error { -// var err error -// -// c.ReconnectInterval = c.ReconnectInterval * 1e6 -// -// if c.heartbeatPeriod, err = time.ParseDuration(c.HeartbeatPeriod); err != nil { -// return perrors.WithMessagef(err, "time.ParseDuration(HeartbeatPeroid{%#v})", c.HeartbeatPeriod) -// } -// -// if c.heartbeatPeriod >= time.Duration(getty.MaxWheelTimeSpan) { -// return perrors.WithMessagef(err, "heartbeat_period %s should be less than %s", -// c.HeartbeatPeriod, time.Duration(getty.MaxWheelTimeSpan)) -// } -// -// if c.sessionTimeout, err = time.ParseDuration(c.SessionTimeout); err != nil { -// return perrors.WithMessagef(err, "time.ParseDuration(SessionTimeout{%#v})", c.SessionTimeout) -// } -// -// return perrors.WithStack(c.GettySessionParam.CheckValidity()) -//} -// -//// CheckValidity ... -//func (c *ServerConfig) CheckValidity() error { -// var err error -// -// if c.sessionTimeout, err = time.ParseDuration(c.SessionTimeout); err != nil { -// return perrors.WithMessagef(err, "time.ParseDuration(SessionTimeout{%#v})", c.SessionTimeout) -// } -// -// if c.sessionTimeout >= time.Duration(getty.MaxWheelTimeSpan) { -// return perrors.WithMessagef(err, "session_timeout %s should be less than %s", -// c.SessionTimeout, time.Duration(getty.MaxWheelTimeSpan)) -// } -// -// return perrors.WithStack(c.GettySessionParam.CheckValidity()) -//} diff --git a/protocol/dubbo/dubbo_codec.go b/protocol/dubbo/dubbo_codec.go index 899148a8e06226a6318564c42367b4fee025eff5..c1f8231385dd788e3900eeb8db7f7b62d08bc498 100644 --- a/protocol/dubbo/dubbo_codec.go +++ b/protocol/dubbo/dubbo_codec.go @@ -4,6 +4,9 @@ import ( "bufio" "bytes" "fmt" + "strconv" + "time" + hessian "github.com/apache/dubbo-go-hessian2" "github.com/apache/dubbo-go/common/constant" "github.com/apache/dubbo-go/common/logger" @@ -11,8 +14,6 @@ import ( "github.com/apache/dubbo-go/protocol/invocation" "github.com/apache/dubbo-go/remoting" perrors "github.com/pkg/errors" - "strconv" - "time" ) //SerialID serial ID @@ -171,8 +172,9 @@ func (c *DubboCodec) EncodeResponse(response *remoting.Response) (*bytes.Buffer, } if !response.IsHeartbeat() { resp.Body = &hessian.Response{ - RspObj: response.Result.(protocol.RPCResult).Rest, - Exception: response.Result.(protocol.RPCResult).Err, + RspObj: response.Result.(protocol.RPCResult).Rest, + Exception: response.Result.(protocol.RPCResult).Err, + Attachments: response.Result.(protocol.RPCResult).Attrs, } } @@ -190,7 +192,29 @@ func (c *DubboCodec) EncodeResponse(response *remoting.Response) (*bytes.Buffer, return bytes.NewBuffer(pkg), nil } -func (c *DubboCodec) DecodeRequest(data []byte) (*remoting.Request, int, error) { +func (c *DubboCodec) Decode(data []byte) (remoting.DecodeResult, int, error) { + if c.isRequest(data) { + req, len, err := c.decodeRequest(data) + if err != nil { + return remoting.DecodeResult{}, len, err + } + return remoting.DecodeResult{IsRequest: true, Result: req}, len, err + } else { + resp, len, err := c.decodeResponse(data) + if err != nil { + return remoting.DecodeResult{}, len, err + } + return remoting.DecodeResult{IsRequest: false, Result: resp}, len, err + } +} +func (c *DubboCodec) isRequest(data []byte) bool { + if data[2]&byte(0x80) == 0x00 { + return false + } + return true +} + +func (c *DubboCodec) decodeRequest(data []byte) (*remoting.Request, int, error) { pkg := &DubboPackage{ Body: make([]interface{}, 7), } @@ -201,7 +225,7 @@ func (c *DubboCodec) DecodeRequest(data []byte) (*remoting.Request, int, error) originErr := perrors.Cause(err) if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { //FIXME - return request, 0, originErr + return nil, 0, originErr } logger.Errorf("pkg.Unmarshal(len(@data):%d) = error:%+v", buf.Len(), err) @@ -274,7 +298,7 @@ func (c *DubboCodec) DecodeRequest(data []byte) (*remoting.Request, int, error) return request, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil } -func (c *DubboCodec) DecodeResponse(data []byte) (*remoting.Response, int, error) { +func (c *DubboCodec) decodeResponse(data []byte) (*remoting.Response, int, error) { pkg := &DubboPackage{} buf := bytes.NewBuffer(data) response := &remoting.Response{} @@ -282,11 +306,11 @@ func (c *DubboCodec) DecodeResponse(data []byte) (*remoting.Response, int, error if err != nil { originErr := perrors.Cause(err) if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { - return response, 0, nil + return nil, 0, originErr } logger.Errorf("pkg.Unmarshal(len(@data):%d) = error:%+v", buf.Len(), err) - return response, 0, perrors.WithStack(err) + return nil, 0, perrors.WithStack(err) } response = &remoting.Response{ Id: pkg.Header.ID, @@ -316,6 +340,9 @@ func (c *DubboCodec) DecodeResponse(data []byte) (*remoting.Response, int, error if pkg.Header.Type&hessian.PackageRequest == 0x00 { if pkg.Err != nil { rpcResult.Err = pkg.Err + } else if pkg.Body.(*hessian.Response).Exception != nil { + rpcResult.Err = pkg.Body.(*hessian.Response).Exception + response.Error = rpcResult.Err } rpcResult.Attrs = pkg.Body.(*hessian.Response).Attachments rpcResult.Rest = pkg.Body.(*hessian.Response).RspObj diff --git a/protocol/dubbo/dubbo_codec_test.go b/protocol/dubbo/dubbo_codec_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f401318d86115f58578a6470227ea6e6afe811a7 --- /dev/null +++ b/protocol/dubbo/dubbo_codec_test.go @@ -0,0 +1 @@ +package dubbo diff --git a/protocol/dubbo/dubbo_invoker_test.go b/protocol/dubbo/dubbo_invoker_test.go index 1a64301f8200a4264001284cca1af3f0f1e07814..ddb7b783d121c068d99ba20b92cb163549a73756 100644 --- a/protocol/dubbo/dubbo_invoker_test.go +++ b/protocol/dubbo/dubbo_invoker_test.go @@ -18,35 +18,31 @@ package dubbo import ( + "bytes" "context" "sync" "testing" "time" -) -import ( - "github.com/opentracing/opentracing-go" - "github.com/stretchr/testify/assert" -) + "github.com/apache/dubbo-go/remoting" -import ( + "github.com/apache/dubbo-go/remoting/getty" + + hessian "github.com/apache/dubbo-go-hessian2" "github.com/apache/dubbo-go/common" "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/proxy/proxy_factory" + "github.com/apache/dubbo-go/protocol" "github.com/apache/dubbo-go/protocol/invocation" + "github.com/opentracing/opentracing-go" + perrors "github.com/pkg/errors" + "github.com/stretchr/testify/assert" ) func TestDubboInvoker_Invoke(t *testing.T) { proto, url := InitTest(t) - c := &Client{ - pendingResponses: new(sync.Map), - conf: *clientConf, - opts: Options{ - ConnectTimeout: 3 * time.Second, - RequestTimeout: 6 * time.Second, - }, - } - c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) + c := getExchangeClient(url) invoker := NewDubboInvoker(url, c) user := &User{} @@ -58,7 +54,9 @@ func TestDubboInvoker_Invoke(t *testing.T) { res := invoker.Invoke(context.Background(), inv) assert.NoError(t, res.Error()) assert.Equal(t, User{Id: "1", Name: "username"}, *res.Result().(*User)) - assert.Equal(t, "test_value", res.Attachments()["test_key"]) // test attachments for request/response + //result will not contain attachment + // attachment in result it is useless. + //assert.Equal(t, "test_value", res.Attachments()["test_key"]) // test attachments for request/response // CallOneway inv.SetAttachments(constant.ASYNC_KEY, "true") @@ -69,8 +67,10 @@ func TestDubboInvoker_Invoke(t *testing.T) { lock := sync.Mutex{} lock.Lock() inv.SetCallBack(func(response common.CallbackResponse) { - r := response.(AsyncCallbackResponse) - assert.Equal(t, User{Id: "1", Name: "username"}, *r.Reply.(*Response).reply.(*User)) + r := response.(remoting.AsyncCallbackResponse) + rst := *r.Reply.(*remoting.Response).Result.(*protocol.RPCResult) + assert.Equal(t, User{Id: "1", Name: "username"}, *(rst.Rest.(*User))) + //assert.Equal(t, User{Id: "1", Name: "username"}, *r.Reply.(*Response).reply.(*User)) lock.Unlock() }) res = invoker.Invoke(context.Background(), inv) @@ -92,3 +92,142 @@ func TestDubboInvoker_Invoke(t *testing.T) { proto.Destroy() lock.Unlock() } + +func InitTest(t *testing.T) (protocol.Protocol, common.URL) { + + hessian.RegisterPOJO(&User{}) + + methods, err := common.ServiceMap.Register("dubbo", &UserProvider{}) + assert.NoError(t, err) + assert.Equal(t, "GetBigPkg,GetUser,GetUser0,GetUser1,GetUser2,GetUser3,GetUser4,GetUser5,GetUser6", methods) + + // config + getty.SetClientConf(getty.ClientConfig{ + ConnectionNum: 2, + HeartbeatPeriod: "5s", + SessionTimeout: "20s", + PoolTTL: 600, + PoolSize: 64, + GettySessionParam: getty.GettySessionParam{ + CompressEncoding: false, + TcpNoDelay: true, + TcpKeepAlive: true, + KeepAlivePeriod: "120s", + TcpRBufSize: 262144, + TcpWBufSize: 65536, + PkgWQSize: 512, + TcpReadTimeout: "4s", + TcpWriteTimeout: "5s", + WaitTimeout: "1s", + MaxMsgLen: 10240000000, + SessionName: "client", + }, + }) + getty.SetServerConfig(getty.ServerConfig{ + SessionNumber: 700, + SessionTimeout: "20s", + GettySessionParam: getty.GettySessionParam{ + CompressEncoding: false, + TcpNoDelay: true, + TcpKeepAlive: true, + KeepAlivePeriod: "120s", + TcpRBufSize: 262144, + TcpWBufSize: 65536, + PkgWQSize: 512, + TcpReadTimeout: "1s", + TcpWriteTimeout: "5s", + WaitTimeout: "1s", + MaxMsgLen: 10240000000, + SessionName: "server", + }}) + + // Export + proto := GetProtocol() + url, err := common.NewURL("dubbo://127.0.0.1:20702/UserProvider?anyhost=true&" + + "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" + + "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&" + + "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" + + "side=provider&timeout=3000×tamp=1556509797245&bean.name=UserProvider") + assert.NoError(t, err) + proto.Export(&proxy_factory.ProxyInvoker{ + BaseInvoker: *protocol.NewBaseInvoker(url), + }) + + time.Sleep(time.Second * 2) + + return proto, url +} + +////////////////////////////////// +// provider +////////////////////////////////// + +type ( + User struct { + Id string `json:"id"` + Name string `json:"name"` + } + + UserProvider struct { + user map[string]User + } +) + +// size:4801228 +func (u *UserProvider) GetBigPkg(ctx context.Context, req []interface{}, rsp *User) error { + argBuf := new(bytes.Buffer) + for i := 0; i < 400; i++ { + argBuf.WriteString("击鼓其镗,踊跃用兵。土国城漕,我独南行。从孙子仲,平陈与宋。不我以归,忧心有忡。爰居爰处?爰丧其马?于以求之?于林之下。死生契阔,与子成说。执子之手,与子偕老。于嗟阔兮,不我活兮。于嗟洵兮,不我信兮。") + argBuf.WriteString("击鼓其镗,踊跃用兵。土国城漕,我独南行。从孙子仲,平陈与宋。不我以归,忧心有忡。爰居爰处?爰丧其马?于以求之?于林之下。死生契阔,与子成说。执子之手,与子偕老。于嗟阔兮,不我活兮。于嗟洵兮,不我信兮。") + } + rsp.Id = argBuf.String() + rsp.Name = argBuf.String() + return nil +} + +func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error { + rsp.Id = req[0].(string) + rsp.Name = req[1].(string) + return nil +} + +func (u *UserProvider) GetUser0(id string, k *User, name string) (User, error) { + return User{Id: id, Name: name}, nil +} + +func (u *UserProvider) GetUser1() error { + return nil +} + +func (u *UserProvider) GetUser2() error { + return perrors.New("error") +} + +func (u *UserProvider) GetUser3(rsp *[]interface{}) error { + *rsp = append(*rsp, User{Id: "1", Name: "username"}) + return nil +} + +func (u *UserProvider) GetUser4(ctx context.Context, req []interface{}) ([]interface{}, error) { + + return []interface{}{User{Id: req[0].([]interface{})[0].(string), Name: req[0].([]interface{})[1].(string)}}, nil +} + +func (u *UserProvider) GetUser5(ctx context.Context, req []interface{}) (map[interface{}]interface{}, error) { + return map[interface{}]interface{}{"key": User{Id: req[0].(map[interface{}]interface{})["id"].(string), Name: req[0].(map[interface{}]interface{})["name"].(string)}}, nil +} + +func (u *UserProvider) GetUser6(id int64) (*User, error) { + if id == 0 { + return nil, nil + } + return &User{Id: "1"}, nil +} + +func (u *UserProvider) Reference() string { + return "UserProvider" +} + +func (u User) JavaClassName() string { + return "com.ikurento.user.User" +} diff --git a/protocol/dubbo/dubbo_protocol.go b/protocol/dubbo/dubbo_protocol.go index 20e54fa2ee95170ed7ca94b2ccd4e0d5d9a29922..3bf03419239e85a5d71baded13965cb78f158231 100644 --- a/protocol/dubbo/dubbo_protocol.go +++ b/protocol/dubbo/dubbo_protocol.go @@ -18,19 +18,20 @@ package dubbo import ( + "context" "fmt" - "github.com/apache/dubbo-go/protocol/invocation" - "github.com/apache/dubbo-go/remoting" - "github.com/apache/dubbo-go/remoting/getty" "sync" -) -import ( "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" "github.com/apache/dubbo-go/common/extension" "github.com/apache/dubbo-go/common/logger" "github.com/apache/dubbo-go/config" "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/remoting" + "github.com/apache/dubbo-go/remoting/getty" + "github.com/opentracing/opentracing-go" ) // dubbo protocol constant @@ -154,14 +155,8 @@ func doHandleRequest(rpcInvocation *invocation.RPCInvocation) protocol.RPCResult } invoker := exporter.(protocol.Exporter).GetInvoker() if invoker != nil { - //attachments := rpcInvocation.Attachments() - //attachments[constant.LOCAL_ADDR] = session.LocalAddr() - //attachments[constant.REMOTE_ADDR] = session.RemoteAddr() - // - //args := p.Body.(map[string]interface{})["args"].([]interface{}) - //inv := invocation.NewRPCInvocation(p.Service.Method, args, attachments) // FIXME - ctx := getty.RebuildCtx(rpcInvocation) + ctx := rebuildCtx(rpcInvocation) invokeResult := invoker.Invoke(ctx, rpcInvocation) if err := invokeResult.Error(); err != nil { @@ -200,3 +195,18 @@ func getExchangeClient(url common.URL) *remoting.ExchangeClient { } return exchangeClient } + +// rebuildCtx rebuild the context by attachment. +// Once we decided to transfer more context's key-value, we should change this. +// now we only support rebuild the tracing context +func rebuildCtx(inv *invocation.RPCInvocation) context.Context { + ctx := context.WithValue(context.Background(), "attachment", inv.Attachments()) + + // actually, if user do not use any opentracing framework, the err will not be nil. + spanCtx, err := opentracing.GlobalTracer().Extract(opentracing.TextMap, + opentracing.TextMapCarrier(inv.Attachments())) + if err == nil { + ctx = context.WithValue(ctx, constant.TRACING_REMOTE_SPAN_CTX, spanCtx) + } + return ctx +} diff --git a/protocol/dubbo/dubbo_protocol_test.go b/protocol/dubbo/dubbo_protocol_test.go index 5fdcc69b5c6ba409cf68954f95c2adf581297e4a..932e94862dd1a5c92a1f416482e8b61e574cc85c 100644 --- a/protocol/dubbo/dubbo_protocol_test.go +++ b/protocol/dubbo/dubbo_protocol_test.go @@ -16,84 +16,80 @@ */ package dubbo -// -//import ( -// "testing" -//) -// -//import ( -// "github.com/stretchr/testify/assert" -//) -// -//import ( -// "github.com/apache/dubbo-go/common" -// "github.com/apache/dubbo-go/common/constant" -// "github.com/apache/dubbo-go/protocol" -//) -// -//func TestDubboProtocol_Export(t *testing.T) { -// // Export -// proto := GetProtocol() -// srvConf = &ServerConfig{} -// url, err := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" + -// "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" + -// "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&" + -// "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" + -// "side=provider&timeout=3000×tamp=1556509797245") -// assert.NoError(t, err) -// exporter := proto.Export(protocol.NewBaseInvoker(url)) -// -// // make sure url -// eq := exporter.GetInvoker().GetUrl().URLEqual(url) -// assert.True(t, eq) -// -// // second service: the same path and the different version -// url2, err := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&"+ -// "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"+ -// "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"+ -// "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"+ -// "side=provider&timeout=3000×tamp=1556509797245", common.WithParamsValue(constant.VERSION_KEY, "v1.1")) -// assert.NoError(t, err) -// exporter2 := proto.Export(protocol.NewBaseInvoker(url2)) -// // make sure url -// eq2 := exporter2.GetInvoker().GetUrl().URLEqual(url2) -// assert.True(t, eq2) -// -// // make sure exporterMap after 'Unexport' -// _, ok := proto.(*DubboProtocol).ExporterMap().Load(url.ServiceKey()) -// assert.True(t, ok) -// exporter.Unexport() -// _, ok = proto.(*DubboProtocol).ExporterMap().Load(url.ServiceKey()) -// assert.False(t, ok) -// -// // make sure serverMap after 'Destroy' -// _, ok = proto.(*DubboProtocol).serverMap[url.Location] -// assert.True(t, ok) -// proto.Destroy() -// _, ok = proto.(*DubboProtocol).serverMap[url.Location] -// assert.False(t, ok) -//} -// -//func TestDubboProtocol_Refer(t *testing.T) { -// // Refer -// proto := GetProtocol() -// url, err := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" + -// "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" + -// "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&" + -// "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" + -// "side=provider&timeout=3000×tamp=1556509797245") -// assert.NoError(t, err) -// clientConf = &ClientConfig{} -// invoker := proto.Refer(url) -// -// // make sure url -// eq := invoker.GetUrl().URLEqual(url) -// assert.True(t, eq) -// -// // make sure invokers after 'Destroy' -// invokersLen := len(proto.(*DubboProtocol).Invokers()) -// assert.Equal(t, 1, invokersLen) -// proto.Destroy() -// invokersLen = len(proto.(*DubboProtocol).Invokers()) -// assert.Equal(t, 0, invokersLen) -//} + +import ( + "testing" + + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/remoting/getty" + "github.com/stretchr/testify/assert" +) + +func TestDubboProtocol_Export(t *testing.T) { + // Export + proto := GetProtocol() + getty.SetServerConfig(getty.ServerConfig{}) + url, err := common.NewURL("dubbo://127.0.0.1:20080/com.ikurento.user.UserProvider?anyhost=true&" + + "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" + + "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&" + + "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" + + "side=provider&timeout=3000×tamp=1556509797245") + assert.NoError(t, err) + exporter := proto.Export(protocol.NewBaseInvoker(url)) + + // make sure url + eq := exporter.GetInvoker().GetUrl().URLEqual(url) + assert.True(t, eq) + + // second service: the same path and the different version + url2, err := common.NewURL("dubbo://127.0.0.1:20080/com.ikurento.user.UserProvider?anyhost=true&"+ + "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"+ + "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"+ + "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"+ + "side=provider&timeout=3000×tamp=1556509797245", common.WithParamsValue(constant.VERSION_KEY, "v1.1")) + assert.NoError(t, err) + exporter2 := proto.Export(protocol.NewBaseInvoker(url2)) + // make sure url + eq2 := exporter2.GetInvoker().GetUrl().URLEqual(url2) + assert.True(t, eq2) + + // make sure exporterMap after 'Unexport' + _, ok := proto.(*DubboProtocol).ExporterMap().Load(url.ServiceKey()) + assert.True(t, ok) + exporter.Unexport() + _, ok = proto.(*DubboProtocol).ExporterMap().Load(url.ServiceKey()) + assert.False(t, ok) + + // make sure serverMap after 'Destroy' + _, ok = proto.(*DubboProtocol).serverMap[url.Location] + assert.True(t, ok) + proto.Destroy() + _, ok = proto.(*DubboProtocol).serverMap[url.Location] + assert.False(t, ok) +} + +func TestDubboProtocol_Refer(t *testing.T) { + // Refer + proto := GetProtocol() + url, err := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" + + "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" + + "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&" + + "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" + + "side=provider&timeout=3000×tamp=1556509797245") + assert.NoError(t, err) + getty.SetClientConf(getty.ClientConfig{}) + invoker := proto.Refer(url) + + // make sure url + eq := invoker.GetUrl().URLEqual(url) + assert.True(t, eq) + + // make sure invokers after 'Destroy' + invokersLen := len(proto.(*DubboProtocol).Invokers()) + assert.Equal(t, 1, invokersLen) + proto.Destroy() + invokersLen = len(proto.(*DubboProtocol).Invokers()) + assert.Equal(t, 0, invokersLen) +} diff --git a/protocol/dubbo/listener.go b/protocol/dubbo/listener.go deleted file mode 100644 index 3d4db11f3dd80055cee259741f763c514c0a32c1..0000000000000000000000000000000000000000 --- a/protocol/dubbo/listener.go +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "context" -// "fmt" -// "net/url" -// "sync" -// "sync/atomic" -// "time" -//) -// -//import ( -// "github.com/apache/dubbo-go-hessian2" -// "github.com/dubbogo/getty" -// "github.com/opentracing/opentracing-go" -// perrors "github.com/pkg/errors" -//) -// -//import ( -// "github.com/apache/dubbo-go/common" -// "github.com/apache/dubbo-go/common/constant" -// "github.com/apache/dubbo-go/common/logger" -// "github.com/apache/dubbo-go/protocol" -// "github.com/apache/dubbo-go/protocol/invocation" -//) -// -//// todo: WritePkg_Timeout will entry *.yml -//const ( -// // WritePkg_Timeout ... -// WritePkg_Timeout = 5 * time.Second -//) -// -//var ( -// errTooManySessions = perrors.New("too many sessions") -//) -// -//type rpcSession struct { -// session getty.Session -// reqNum int32 -//} -// -//func (s *rpcSession) AddReqNum(num int32) { -// atomic.AddInt32(&s.reqNum, num) -//} -// -//func (s *rpcSession) GetReqNum() int32 { -// return atomic.LoadInt32(&s.reqNum) -//} -// -//// ////////////////////////////////////////// -//// RpcClientHandler -//// ////////////////////////////////////////// -// -//// RpcClientHandler ... -//type RpcClientHandler struct { -// conn *gettyRPCClient -//} -// -//// NewRpcClientHandler ... -//func NewRpcClientHandler(client *gettyRPCClient) *RpcClientHandler { -// return &RpcClientHandler{conn: client} -//} -// -//// OnOpen ... -//func (h *RpcClientHandler) OnOpen(session getty.Session) error { -// h.conn.addSession(session) -// return nil -//} -// -//// OnError ... -//func (h *RpcClientHandler) OnError(session getty.Session, err error) { -// logger.Infof("session{%s} got error{%v}, will be closed.", session.Stat(), err) -// h.conn.removeSession(session) -//} -// -//// OnClose ... -//func (h *RpcClientHandler) OnClose(session getty.Session) { -// logger.Infof("session{%s} is closing......", session.Stat()) -// h.conn.removeSession(session) -//} -// -//// OnMessage ... -//func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) { -// p, ok := pkg.(*DubboPackage) -// if !ok { -// logger.Errorf("illegal package") -// return -// } -// -// if p.Header.Type&hessian.PackageHeartbeat != 0x00 { -// if p.Header.Type&hessian.PackageResponse != 0x00 { -// logger.Debugf("get rpc heartbeat response{header: %#v, body: %#v}", p.Header, p.Body) -// if p.Err != nil { -// logger.Errorf("rpc heartbeat response{error: %#v}", p.Err) -// } -// h.conn.pool.rpcClient.removePendingResponse(SequenceType(p.Header.ID)) -// } else { -// logger.Debugf("get rpc heartbeat request{header: %#v, service: %#v, body: %#v}", p.Header, p.Service, p.Body) -// p.Header.ResponseStatus = hessian.Response_OK -// reply(session, p, hessian.PackageHeartbeat) -// } -// return -// } -// logger.Debugf("get rpc response{header: %#v, body: %#v}", p.Header, p.Body) -// -// h.conn.updateSession(session) -// -// pendingResponse := h.conn.pool.rpcClient.removePendingResponse(SequenceType(p.Header.ID)) -// if pendingResponse == nil { -// logger.Errorf("failed to get pending response context for response package %s", *p) -// return -// } -// -// if p.Err != nil { -// pendingResponse.err = p.Err -// } -// -// pendingResponse.response.atta = p.Body.(*Response).atta -// -// if pendingResponse.callback == nil { -// pendingResponse.done <- struct{}{} -// } else { -// pendingResponse.callback(pendingResponse.GetCallResponse()) -// } -//} -// -//// OnCron ... -//func (h *RpcClientHandler) OnCron(session getty.Session) { -// rpcSession, err := h.conn.getClientRpcSession(session) -// if err != nil { -// logger.Errorf("client.getClientSession(session{%s}) = error{%v}", -// session.Stat(), perrors.WithStack(err)) -// return -// } -// if h.conn.pool.rpcClient.conf.sessionTimeout.Nanoseconds() < time.Since(session.GetActive()).Nanoseconds() { -// logger.Warnf("session{%s} timeout{%s}, reqNum{%d}", -// session.Stat(), time.Since(session.GetActive()).String(), rpcSession.reqNum) -// h.conn.removeSession(session) // -> h.conn.close() -> h.conn.pool.remove(h.conn) -// return -// } -// -// h.conn.pool.rpcClient.heartbeat(session) -//} -// -//// ////////////////////////////////////////// -//// RpcServerHandler -//// ////////////////////////////////////////// -// -//// RpcServerHandler ... -//type RpcServerHandler struct { -// maxSessionNum int -// sessionTimeout time.Duration -// sessionMap map[getty.Session]*rpcSession -// rwlock sync.RWMutex -//} -// -//// NewRpcServerHandler ... -//func NewRpcServerHandler(maxSessionNum int, sessionTimeout time.Duration) *RpcServerHandler { -// return &RpcServerHandler{ -// maxSessionNum: maxSessionNum, -// sessionTimeout: sessionTimeout, -// sessionMap: make(map[getty.Session]*rpcSession), -// } -//} -// -//// OnOpen ... -//func (h *RpcServerHandler) OnOpen(session getty.Session) error { -// var err error -// h.rwlock.RLock() -// if h.maxSessionNum <= len(h.sessionMap) { -// err = errTooManySessions -// } -// h.rwlock.RUnlock() -// if err != nil { -// return perrors.WithStack(err) -// } -// -// logger.Infof("got session:%s", session.Stat()) -// h.rwlock.Lock() -// h.sessionMap[session] = &rpcSession{session: session} -// h.rwlock.Unlock() -// return nil -//} -// -//// OnError ... -//func (h *RpcServerHandler) OnError(session getty.Session, err error) { -// logger.Infof("session{%s} got error{%v}, will be closed.", session.Stat(), err) -// h.rwlock.Lock() -// delete(h.sessionMap, session) -// h.rwlock.Unlock() -//} -// -//// OnClose ... -//func (h *RpcServerHandler) OnClose(session getty.Session) { -// logger.Infof("session{%s} is closing......", session.Stat()) -// h.rwlock.Lock() -// delete(h.sessionMap, session) -// h.rwlock.Unlock() -//} -// -//// OnMessage ... -//func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) { -// h.rwlock.Lock() -// if _, ok := h.sessionMap[session]; ok { -// h.sessionMap[session].reqNum++ -// } -// h.rwlock.Unlock() -// -// p, ok := pkg.(*DubboPackage) -// if !ok { -// logger.Errorf("illegal package{%#v}", pkg) -// return -// } -// p.Header.ResponseStatus = hessian.Response_OK -// -// // heartbeat -// if p.Header.Type&hessian.PackageHeartbeat != 0x00 { -// logger.Debugf("get rpc heartbeat request{header: %#v, service: %#v, body: %#v}", p.Header, p.Service, p.Body) -// reply(session, p, hessian.PackageHeartbeat) -// return -// } -// -// twoway := true -// // not twoway -// if p.Header.Type&hessian.PackageRequest_TwoWay == 0x00 { -// twoway = false -// } -// -// defer func() { -// if e := recover(); e != nil { -// p.Header.ResponseStatus = hessian.Response_SERVER_ERROR -// if err, ok := e.(error); ok { -// logger.Errorf("OnMessage panic: %+v", perrors.WithStack(err)) -// p.Body = perrors.WithStack(err) -// } else if err, ok := e.(string); ok { -// logger.Errorf("OnMessage panic: %+v", perrors.New(err)) -// p.Body = perrors.New(err) -// } else { -// logger.Errorf("OnMessage panic: %+v, this is impossible.", e) -// p.Body = e -// } -// -// if !twoway { -// return -// } -// reply(session, p, hessian.PackageResponse) -// } -// -// }() -// -// u := common.NewURLWithOptions(common.WithPath(p.Service.Path), common.WithParams(url.Values{}), -// common.WithParamsValue(constant.GROUP_KEY, p.Service.Group), -// common.WithParamsValue(constant.INTERFACE_KEY, p.Service.Interface), -// common.WithParamsValue(constant.VERSION_KEY, p.Service.Version)) -// exporter, _ := dubboProtocol.ExporterMap().Load(u.ServiceKey()) -// if exporter == nil { -// err := fmt.Errorf("don't have this exporter, key: %s", u.ServiceKey()) -// logger.Errorf(err.Error()) -// p.Header.ResponseStatus = hessian.Response_OK -// p.Body = err -// reply(session, p, hessian.PackageResponse) -// return -// } -// invoker := exporter.(protocol.Exporter).GetInvoker() -// if invoker != nil { -// attachments := p.Body.(map[string]interface{})["attachments"].(map[string]string) -// attachments[constant.LOCAL_ADDR] = session.LocalAddr() -// attachments[constant.REMOTE_ADDR] = session.RemoteAddr() -// -// args := p.Body.(map[string]interface{})["args"].([]interface{}) -// inv := invocation.NewRPCInvocation(p.Service.Method, args, attachments) -// -// ctx := rebuildCtx(inv) -// -// result := invoker.Invoke(ctx, inv) -// if err := result.Error(); err != nil { -// p.Header.ResponseStatus = hessian.Response_OK -// p.Body = hessian.NewResponse(nil, err, result.Attachments()) -// } else { -// res := result.Result() -// p.Header.ResponseStatus = hessian.Response_OK -// p.Body = hessian.NewResponse(res, nil, result.Attachments()) -// } -// } -// -// if !twoway { -// return -// } -// reply(session, p, hessian.PackageResponse) -//} -// -//// OnCron ... -//func (h *RpcServerHandler) OnCron(session getty.Session) { -// var ( -// flag bool -// active time.Time -// ) -// -// h.rwlock.RLock() -// if _, ok := h.sessionMap[session]; ok { -// active = session.GetActive() -// if h.sessionTimeout.Nanoseconds() < time.Since(active).Nanoseconds() { -// flag = true -// logger.Warnf("session{%s} timeout{%s}, reqNum{%d}", -// session.Stat(), time.Since(active).String(), h.sessionMap[session].reqNum) -// } -// } -// h.rwlock.RUnlock() -// -// if flag { -// h.rwlock.Lock() -// delete(h.sessionMap, session) -// h.rwlock.Unlock() -// session.Close() -// } -//} -// -//// rebuildCtx rebuild the context by attachment. -//// Once we decided to transfer more context's key-value, we should change this. -//// now we only support rebuild the tracing context -//func rebuildCtx(inv *invocation.RPCInvocation) context.Context { -// ctx := context.Background() -// -// // actually, if user do not use any opentracing framework, the err will not be nil. -// spanCtx, err := opentracing.GlobalTracer().Extract(opentracing.TextMap, -// opentracing.TextMapCarrier(inv.Attachments())) -// if err == nil { -// ctx = context.WithValue(ctx, constant.TRACING_REMOTE_SPAN_CTX, spanCtx) -// } -// return ctx -//} -// -//func reply(session getty.Session, req *DubboPackage, tp hessian.PackageType) { -// resp := &DubboPackage{ -// Header: hessian.DubboHeader{ -// SerialID: req.Header.SerialID, -// Type: tp, -// ID: req.Header.ID, -// ResponseStatus: req.Header.ResponseStatus, -// }, -// } -// -// if req.Header.Type&hessian.PackageRequest != 0x00 { -// resp.Body = req.Body -// } else { -// resp.Body = nil -// } -// -// if err := session.WritePkg(resp, WritePkg_Timeout); err != nil { -// logger.Errorf("WritePkg error: %#v, %#v", perrors.WithStack(err), req.Header) -// } -//} diff --git a/protocol/dubbo/listener_test.go b/protocol/dubbo/listener_test.go deleted file mode 100644 index 1057dbfa368a4abbbbba86532f055f44c0e2f8ba..0000000000000000000000000000000000000000 --- a/protocol/dubbo/listener_test.go +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "testing" -//) -// -//import ( -// "github.com/opentracing/opentracing-go" -// "github.com/opentracing/opentracing-go/mocktracer" -// "github.com/stretchr/testify/assert" -//) -// -//import ( -// "github.com/apache/dubbo-go/common/constant" -// "github.com/apache/dubbo-go/protocol/invocation" -//) -// -//// test rebuild the ctx -//func TestRebuildCtx(t *testing.T) { -// opentracing.SetGlobalTracer(mocktracer.New()) -// attach := make(map[string]string, 10) -// attach[constant.VERSION_KEY] = "1.0" -// attach[constant.GROUP_KEY] = "MyGroup" -// inv := invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach) -// -// // attachment doesn't contains any tracing key-value pair, -// ctx := rebuildCtx(inv) -// assert.NotNil(t, ctx) -// assert.Nil(t, ctx.Value(constant.TRACING_REMOTE_SPAN_CTX)) -// -// span, ctx := opentracing.StartSpanFromContext(ctx, "Test-Client") -// -// opentracing.GlobalTracer().Inject(span.Context(), opentracing.TextMap, -// opentracing.TextMapCarrier(inv.Attachments())) -// // rebuild the context success -// inv = invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach) -// ctx = rebuildCtx(inv) -// span.Finish() -// assert.NotNil(t, ctx) -// assert.NotNil(t, ctx.Value(constant.TRACING_REMOTE_SPAN_CTX)) -//} diff --git a/protocol/dubbo/pool.go b/protocol/dubbo/pool.go deleted file mode 100644 index 3dda895d55cfbfba12666c0f64e6088cf3929335..0000000000000000000000000000000000000000 --- a/protocol/dubbo/pool.go +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "fmt" -// "math/rand" -// "net" -// "sync" -// "sync/atomic" -// "time" -//) -// -//import ( -// "github.com/dubbogo/getty" -// perrors "github.com/pkg/errors" -//) -// -//import ( -// "github.com/apache/dubbo-go/common/logger" -//) -// -//type gettyRPCClient struct { -// once sync.Once -// protocol string -// addr string -// active int64 // zero, not create or be destroyed -// -// pool *gettyRPCClientPool -// -// lock sync.RWMutex -// gettyClient getty.Client -// sessions []*rpcSession -//} -// -//var ( -// errClientPoolClosed = perrors.New("client pool closed") -//) -// -//func newGettyRPCClientConn(pool *gettyRPCClientPool, protocol, addr string) (*gettyRPCClient, error) { -// c := &gettyRPCClient{ -// protocol: protocol, -// addr: addr, -// pool: pool, -// gettyClient: getty.NewTCPClient( -// getty.WithServerAddress(addr), -// getty.WithConnectionNumber((int)(pool.rpcClient.conf.ConnectionNum)), -// getty.WithReconnectInterval(pool.rpcClient.conf.ReconnectInterval), -// ), -// } -// go c.gettyClient.RunEventLoop(c.newSession) -// idx := 1 -// times := int(pool.rpcClient.opts.ConnectTimeout / 1e6) -// for { -// idx++ -// if c.isAvailable() { -// break -// } -// -// if idx > times { -// c.gettyClient.Close() -// return nil, perrors.New(fmt.Sprintf("failed to create client connection to %s in %f seconds", addr, float32(times)/1000)) -// } -// time.Sleep(1e6) -// } -// logger.Debug("client init ok") -// c.updateActive(time.Now().Unix()) -// -// return c, nil -//} -// -//func (c *gettyRPCClient) updateActive(active int64) { -// atomic.StoreInt64(&c.active, active) -//} -// -//func (c *gettyRPCClient) getActive() int64 { -// return atomic.LoadInt64(&c.active) -//} -// -//func (c *gettyRPCClient) newSession(session getty.Session) error { -// var ( -// ok bool -// tcpConn *net.TCPConn -// conf ClientConfig -// ) -// -// conf = c.pool.rpcClient.conf -// if conf.GettySessionParam.CompressEncoding { -// session.SetCompressType(getty.CompressZip) -// } -// -// if tcpConn, ok = session.Conn().(*net.TCPConn); !ok { -// panic(fmt.Sprintf("%s, session.conn{%#v} is not tcp connection\n", session.Stat(), session.Conn())) -// } -// -// tcpConn.SetNoDelay(conf.GettySessionParam.TcpNoDelay) -// tcpConn.SetKeepAlive(conf.GettySessionParam.TcpKeepAlive) -// if conf.GettySessionParam.TcpKeepAlive { -// tcpConn.SetKeepAlivePeriod(conf.GettySessionParam.keepAlivePeriod) -// } -// tcpConn.SetReadBuffer(conf.GettySessionParam.TcpRBufSize) -// tcpConn.SetWriteBuffer(conf.GettySessionParam.TcpWBufSize) -// -// session.SetName(conf.GettySessionParam.SessionName) -// session.SetMaxMsgLen(conf.GettySessionParam.MaxMsgLen) -// session.SetPkgHandler(NewRpcClientPackageHandler(c.pool.rpcClient)) -// session.SetEventListener(NewRpcClientHandler(c)) -// session.SetWQLen(conf.GettySessionParam.PkgWQSize) -// session.SetReadTimeout(conf.GettySessionParam.tcpReadTimeout) -// session.SetWriteTimeout(conf.GettySessionParam.tcpWriteTimeout) -// session.SetCronPeriod((int)(conf.heartbeatPeriod.Nanoseconds() / 1e6)) -// session.SetWaitTime(conf.GettySessionParam.waitTimeout) -// logger.Debugf("client new session:%s\n", session.Stat()) -// -// session.SetTaskPool(clientGrpool) -// -// return nil -//} -// -//func (c *gettyRPCClient) selectSession() getty.Session { -// c.lock.RLock() -// defer c.lock.RUnlock() -// -// if c.sessions == nil { -// return nil -// } -// -// count := len(c.sessions) -// if count == 0 { -// return nil -// } -// return c.sessions[rand.Int31n(int32(count))].session -//} -// -//func (c *gettyRPCClient) addSession(session getty.Session) { -// logger.Debugf("add session{%s}", session.Stat()) -// if session == nil { -// return -// } -// -// c.lock.Lock() -// defer c.lock.Unlock() -// if c.sessions == nil { -// c.sessions = make([]*rpcSession, 0, 16) -// } -// c.sessions = append(c.sessions, &rpcSession{session: session}) -//} -// -//func (c *gettyRPCClient) removeSession(session getty.Session) { -// if session == nil { -// return -// } -// -// var removeFlag bool -// func() { -// c.lock.Lock() -// defer c.lock.Unlock() -// if c.sessions == nil { -// return -// } -// -// for i, s := range c.sessions { -// if s.session == session { -// c.sessions = append(c.sessions[:i], c.sessions[i+1:]...) -// logger.Debugf("delete session{%s}, its index{%d}", session.Stat(), i) -// break -// } -// } -// logger.Infof("after remove session{%s}, left session number:%d", session.Stat(), len(c.sessions)) -// if len(c.sessions) == 0 { -// removeFlag = true -// } -// }() -// if removeFlag { -// c.pool.safeRemove(c) -// c.close() -// } -//} -// -//func (c *gettyRPCClient) updateSession(session getty.Session) { -// if session == nil { -// return -// } -// -// var rs *rpcSession -// func() { -// c.lock.RLock() -// defer c.lock.RUnlock() -// if c.sessions == nil { -// return -// } -// -// for i, s := range c.sessions { -// if s.session == session { -// rs = c.sessions[i] -// break -// } -// } -// }() -// if rs != nil { -// rs.AddReqNum(1) -// } -//} -// -//func (c *gettyRPCClient) getClientRpcSession(session getty.Session) (rpcSession, error) { -// var ( -// err error -// rpcSession rpcSession -// ) -// c.lock.RLock() -// defer c.lock.RUnlock() -// if c.sessions == nil { -// return rpcSession, errClientClosed -// } -// -// err = errSessionNotExist -// for _, s := range c.sessions { -// if s.session == session { -// rpcSession = *s -// err = nil -// break -// } -// } -// -// return rpcSession, perrors.WithStack(err) -//} -// -//func (c *gettyRPCClient) isAvailable() bool { -// if c.selectSession() == nil { -// return false -// } -// -// return true -//} -// -//func (c *gettyRPCClient) close() error { -// closeErr := perrors.Errorf("close gettyRPCClient{%#v} again", c) -// c.once.Do(func() { -// var ( -// gettyClient getty.Client -// sessions []*rpcSession -// ) -// func() { -// c.lock.Lock() -// defer c.lock.Unlock() -// -// gettyClient = c.gettyClient -// c.gettyClient = nil -// -// sessions = make([]*rpcSession, 0, len(c.sessions)) -// for _, s := range c.sessions { -// sessions = append(sessions, s) -// } -// c.sessions = c.sessions[:0] -// }() -// -// c.updateActive(0) -// -// go func() { -// if gettyClient != nil { -// gettyClient.Close() -// } -// for _, s := range sessions { -// logger.Infof("close client session{%s, last active:%s, request number:%d}", -// s.session.Stat(), s.session.GetActive().String(), s.GetReqNum()) -// s.session.Close() -// } -// }() -// -// closeErr = nil -// }) -// return closeErr -//} -// -//type gettyRPCClientPool struct { -// rpcClient *Client -// size int // size of []*gettyRPCClient -// ttl int64 // ttl of every gettyRPCClient, it is checked when getConn -// -// sync.Mutex -// conns []*gettyRPCClient -//} -// -//func newGettyRPCClientConnPool(rpcClient *Client, size int, ttl time.Duration) *gettyRPCClientPool { -// return &gettyRPCClientPool{ -// rpcClient: rpcClient, -// size: size, -// ttl: int64(ttl.Seconds()), -// conns: make([]*gettyRPCClient, 0, 16), -// } -//} -// -//func (p *gettyRPCClientPool) close() { -// p.Lock() -// conns := p.conns -// p.conns = nil -// p.Unlock() -// for _, conn := range conns { -// conn.close() -// } -//} -// -//func (p *gettyRPCClientPool) getGettyRpcClient(protocol, addr string) (*gettyRPCClient, error) { -// conn, err := p.get() -// if err == nil && conn == nil { -// // create new conn -// rpcClientConn, err := newGettyRPCClientConn(p, protocol, addr) -// return rpcClientConn, perrors.WithStack(err) -// } -// return conn, perrors.WithStack(err) -//} -// -//func (p *gettyRPCClientPool) get() (*gettyRPCClient, error) { -// now := time.Now().Unix() -// -// p.Lock() -// defer p.Unlock() -// if p.conns == nil { -// return nil, errClientPoolClosed -// } -// -// for len(p.conns) > 0 { -// conn := p.conns[len(p.conns)-1] -// p.conns = p.conns[:len(p.conns)-1] -// -// if d := now - conn.getActive(); d > p.ttl { -// p.remove(conn) -// go conn.close() -// continue -// } -// conn.updateActive(now) //update active time -// return conn, nil -// } -// return nil, nil -//} -// -//func (p *gettyRPCClientPool) put(conn *gettyRPCClient) { -// if conn == nil || conn.getActive() == 0 { -// return -// } -// -// p.Lock() -// defer p.Unlock() -// -// if p.conns == nil { -// return -// } -// -// // check whether @conn has existed in p.conns or not. -// for i := range p.conns { -// if p.conns[i] == conn { -// return -// } -// } -// -// if len(p.conns) >= p.size { -// // delete @conn from client pool -// // p.remove(conn) -// conn.close() -// return -// } -// p.conns = append(p.conns, conn) -//} -// -//func (p *gettyRPCClientPool) remove(conn *gettyRPCClient) { -// if conn == nil || conn.getActive() == 0 { -// return -// } -// -// if p.conns == nil { -// return -// } -// -// if len(p.conns) > 0 { -// for idx, c := range p.conns { -// if conn == c { -// p.conns = append(p.conns[:idx], p.conns[idx+1:]...) -// break -// } -// } -// } -//} -// -//func (p *gettyRPCClientPool) safeRemove(conn *gettyRPCClient) { -// p.Lock() -// defer p.Unlock() -// -// p.remove(conn) -//} diff --git a/protocol/dubbo/readwriter.go b/protocol/dubbo/readwriter.go deleted file mode 100644 index 00b79e47f378c5cfd94a88d39338f521c1caf2d1..0000000000000000000000000000000000000000 --- a/protocol/dubbo/readwriter.go +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "bytes" -// "reflect" -//) -// -//import ( -// "github.com/apache/dubbo-go-hessian2" -// "github.com/dubbogo/getty" -// perrors "github.com/pkg/errors" -//) -// -//import ( -// "github.com/apache/dubbo-go/common" -// "github.com/apache/dubbo-go/common/constant" -// "github.com/apache/dubbo-go/common/logger" -//) -// -////////////////////////////////////////////// -//// RpcClientPackageHandler -////////////////////////////////////////////// -// -//// RpcClientPackageHandler ... -//type RpcClientPackageHandler struct { -// client *Client -//} -// -//// NewRpcClientPackageHandler ... -//func NewRpcClientPackageHandler(client *Client) *RpcClientPackageHandler { -// return &RpcClientPackageHandler{client: client} -//} -// -//func (p *RpcClientPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) { -// pkg := &DubboPackage{} -// -// buf := bytes.NewBuffer(data) -// err := pkg.Unmarshal(buf, p.client) -// if err != nil { -// originErr := perrors.Cause(err) -// if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { -// return nil, 0, nil -// } -// -// logger.Errorf("pkg.Unmarshal(ss:%+v, len(@data):%d) = error:%+v", ss, len(data), err) -// -// return nil, 0, perrors.WithStack(err) -// } -// -// if pkg.Header.Type&hessian.PackageRequest == 0x00 { -// pkg.Err = pkg.Body.(*hessian.Response).Exception -// pkg.Body = NewResponse(pkg.Body.(*hessian.Response).RspObj, pkg.Body.(*hessian.Response).Attachments) -// } -// -// return pkg, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil -//} -// -//func (p *RpcClientPackageHandler) Write(ss getty.Session, pkg interface{}) ([]byte, error) { -// req, ok := pkg.(*DubboPackage) -// if !ok { -// logger.Errorf("illegal pkg:%+v\n", pkg) -// return nil, perrors.New("invalid rpc request") -// } -// -// buf, err := req.Marshal() -// if err != nil { -// logger.Warnf("binary.Write(req{%#v}) = err{%#v}", req, perrors.WithStack(err)) -// return nil, perrors.WithStack(err) -// } -// -// return buf.Bytes(), nil -//} -// -////////////////////////////////////////////// -//// RpcServerPackageHandler -////////////////////////////////////////////// -// -//var ( -// rpcServerPkgHandler = &RpcServerPackageHandler{} -//) -// -//// RpcServerPackageHandler ... -//type RpcServerPackageHandler struct{} -// -//func (p *RpcServerPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) { -// pkg := &DubboPackage{ -// Body: make([]interface{}, 7), -// } -// -// buf := bytes.NewBuffer(data) -// err := pkg.Unmarshal(buf) -// if err != nil { -// originErr := perrors.Cause(err) -// if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { -// return nil, 0, nil -// } -// -// logger.Errorf("pkg.Unmarshal(ss:%+v, len(@data):%d) = error:%+v", ss, len(data), err) -// -// return nil, 0, perrors.WithStack(err) -// } -// -// if pkg.Header.Type&hessian.PackageHeartbeat == 0x00 { -// // convert params of request -// req := pkg.Body.([]interface{}) // length of body should be 7 -// if len(req) > 0 { -// var dubboVersion, argsTypes string -// var args []interface{} -// var attachments map[string]string -// if req[0] != nil { -// dubboVersion = req[0].(string) -// } -// if req[1] != nil { -// pkg.Service.Path = req[1].(string) -// } -// if req[2] != nil { -// pkg.Service.Version = req[2].(string) -// } -// if req[3] != nil { -// pkg.Service.Method = req[3].(string) -// } -// if req[4] != nil { -// argsTypes = req[4].(string) -// } -// if req[5] != nil { -// args = req[5].([]interface{}) -// } -// if req[6] != nil { -// attachments = req[6].(map[string]string) -// } -// if pkg.Service.Path == "" && len(attachments[constant.PATH_KEY]) > 0 { -// pkg.Service.Path = attachments[constant.PATH_KEY] -// } -// if _, ok := attachments[constant.INTERFACE_KEY]; ok { -// pkg.Service.Interface = attachments[constant.INTERFACE_KEY] -// } else { -// pkg.Service.Interface = pkg.Service.Path -// } -// if len(attachments[constant.GROUP_KEY]) > 0 { -// pkg.Service.Group = attachments[constant.GROUP_KEY] -// } -// pkg.Body = map[string]interface{}{ -// "dubboVersion": dubboVersion, -// "argsTypes": argsTypes, -// "args": args, -// "service": common.ServiceMap.GetService(DUBBO, pkg.Service.Path), // path as a key -// "attachments": attachments, -// } -// } -// } -// -// return pkg, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil -//} -// -//func (p *RpcServerPackageHandler) Write(ss getty.Session, pkg interface{}) ([]byte, error) { -// res, ok := pkg.(*DubboPackage) -// if !ok { -// logger.Errorf("illegal pkg:%+v\n, it is %+v", pkg, reflect.TypeOf(pkg)) -// return nil, perrors.New("invalid rpc response") -// } -// -// buf, err := res.Marshal() -// if err != nil { -// logger.Warnf("binary.Write(res{%#v}) = err{%#v}", res, perrors.WithStack(err)) -// return nil, perrors.WithStack(err) -// } -// -// return buf.Bytes(), nil -//} diff --git a/protocol/dubbo/server.go b/protocol/dubbo/server.go deleted file mode 100644 index 35a162cc37be441a2281ae71d89fb371bda2636a..0000000000000000000000000000000000000000 --- a/protocol/dubbo/server.go +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 dubbo -// -//import ( -// "fmt" -// "net" -//) -// -//import ( -// "github.com/dubbogo/getty" -// "github.com/dubbogo/gost/sync" -// "gopkg.in/yaml.v2" -//) -// -//import ( -// "github.com/apache/dubbo-go/common" -// "github.com/apache/dubbo-go/common/logger" -// "github.com/apache/dubbo-go/config" -//) -// -//var ( -// srvConf *ServerConfig -// srvGrpool *gxsync.TaskPool -//) -// -//func init() { -// -// // load clientconfig from provider_config -// // default use dubbo -// providerConfig := config.GetProviderConfig() -// if providerConfig.ApplicationConfig == nil { -// return -// } -// protocolConf := providerConfig.ProtocolConf -// defaultServerConfig := GetDefaultServerConfig() -// if protocolConf == nil { -// logger.Info("protocol_conf default use dubbo config") -// } else { -// dubboConf := protocolConf.(map[interface{}]interface{})[DUBBO] -// if dubboConf == nil { -// logger.Warnf("dubboConf is nil") -// return -// } -// -// dubboConfByte, err := yaml.Marshal(dubboConf) -// if err != nil { -// panic(err) -// } -// err = yaml.Unmarshal(dubboConfByte, &defaultServerConfig) -// if err != nil { -// panic(err) -// } -// } -// srvConf = &defaultServerConfig -// if err := srvConf.CheckValidity(); err != nil { -// panic(err) -// } -// SetServerGrpool() -//} -// -//// SetServerConfig ... -//func SetServerConfig(s ServerConfig) { -// srvConf = &s -// err := srvConf.CheckValidity() -// if err != nil { -// logger.Warnf("[ServerConfig CheckValidity] error: %v", err) -// return -// } -// SetServerGrpool() -//} -// -//// GetServerConfig ... -//func GetServerConfig() ServerConfig { -// return *srvConf -//} -// -//// SetServerGrpool ... -//func SetServerGrpool() { -// if srvConf.GrPoolSize > 1 { -// srvGrpool = gxsync.NewTaskPool(gxsync.WithTaskPoolTaskPoolSize(srvConf.GrPoolSize), gxsync.WithTaskPoolTaskQueueLength(srvConf.QueueLen), -// gxsync.WithTaskPoolTaskQueueNumber(srvConf.QueueNumber)) -// } -//} -// -//// Server ... -//type Server struct { -// conf ServerConfig -// tcpServer getty.Server -// rpcHandler *RpcServerHandler -//} -// -//// NewServer ... -//func NewServer() *Server { -// -// s := &Server{ -// conf: *srvConf, -// } -// -// s.rpcHandler = NewRpcServerHandler(s.conf.SessionNumber, s.conf.sessionTimeout) -// -// return s -//} -// -//func (s *Server) newSession(session getty.Session) error { -// var ( -// ok bool -// tcpConn *net.TCPConn -// ) -// conf := s.conf -// -// if conf.GettySessionParam.CompressEncoding { -// session.SetCompressType(getty.CompressZip) -// } -// -// if tcpConn, ok = session.Conn().(*net.TCPConn); !ok { -// panic(fmt.Sprintf("%s, session.conn{%#v} is not tcp connection\n", session.Stat(), session.Conn())) -// } -// -// tcpConn.SetNoDelay(conf.GettySessionParam.TcpNoDelay) -// tcpConn.SetKeepAlive(conf.GettySessionParam.TcpKeepAlive) -// if conf.GettySessionParam.TcpKeepAlive { -// tcpConn.SetKeepAlivePeriod(conf.GettySessionParam.keepAlivePeriod) -// } -// tcpConn.SetReadBuffer(conf.GettySessionParam.TcpRBufSize) -// tcpConn.SetWriteBuffer(conf.GettySessionParam.TcpWBufSize) -// -// session.SetName(conf.GettySessionParam.SessionName) -// session.SetMaxMsgLen(conf.GettySessionParam.MaxMsgLen) -// session.SetPkgHandler(rpcServerPkgHandler) -// session.SetEventListener(s.rpcHandler) -// session.SetWQLen(conf.GettySessionParam.PkgWQSize) -// session.SetReadTimeout(conf.GettySessionParam.tcpReadTimeout) -// session.SetWriteTimeout(conf.GettySessionParam.tcpWriteTimeout) -// session.SetCronPeriod((int)(conf.sessionTimeout.Nanoseconds() / 1e6)) -// session.SetWaitTime(conf.GettySessionParam.waitTimeout) -// logger.Debugf("app accepts new session:%s\n", session.Stat()) -// -// session.SetTaskPool(srvGrpool) -// -// return nil -//} -// -//// Start ... -//func (s *Server) Start(url common.URL) { -// var ( -// addr string -// tcpServer getty.Server -// ) -// -// addr = url.Location -// tcpServer = getty.NewTCPServer( -// getty.WithLocalAddress(addr), -// ) -// tcpServer.RunEventLoop(s.newSession) -// logger.Debugf("s bind addr{%s} ok!", addr) -// s.tcpServer = tcpServer -// -//} -// -//// Stop ... -//func (s *Server) Stop() { -// s.tcpServer.Close() -//} diff --git a/remoting/codec.go b/remoting/codec.go index 972a00d12b5bf0241cc994e18f16104fff618931..1c1e0257626801586e9445c4a0ac4aec6631d4d5 100644 --- a/remoting/codec.go +++ b/remoting/codec.go @@ -7,8 +7,12 @@ import ( type Codec interface { EncodeRequest(request *Request) (*bytes.Buffer, error) EncodeResponse(response *Response) (*bytes.Buffer, error) - DecodeRequest(data []byte) (*Request, int, error) - DecodeResponse(data []byte) (*Response, int, error) + Decode(data []byte) (DecodeResult, int, error) +} + +type DecodeResult struct { + IsRequest bool + Result interface{} } var ( diff --git a/remoting/exchange.go b/remoting/exchange.go index 498022926d0ee386f7b990db7ec414c83dd1b98c..eaa19f7195e205299217c5089b5cf012818d8155 100644 --- a/remoting/exchange.go +++ b/remoting/exchange.go @@ -1,9 +1,10 @@ package remoting import ( + "time" + "github.com/apache/dubbo-go/common" "go.uber.org/atomic" - "time" ) var ( @@ -88,7 +89,7 @@ type PendingResponse struct { Err error start time.Time ReadStart time.Time - callback common.AsyncCallback + Callback common.AsyncCallback response *Response Reply interface{} Done chan struct{} @@ -104,6 +105,10 @@ func NewPendingResponse(id int64) *PendingResponse { } } +func (r *PendingResponse) SetResponse(response *Response) { + r.response = response +} + // GetCallResponse ... func (r PendingResponse) GetCallResponse() common.CallbackResponse { return AsyncCallbackResponse{ diff --git a/remoting/exchange_client.go b/remoting/exchange_client.go index aff8bba22d2970f5f116c453dfac1da8750bd846..2a0e6cfd799f4b75de59b2dd8eed7a3426e66036 100644 --- a/remoting/exchange_client.go +++ b/remoting/exchange_client.go @@ -1,11 +1,12 @@ package remoting import ( + "sync" + "time" + "github.com/apache/dubbo-go/common" "github.com/apache/dubbo-go/common/logger" "github.com/apache/dubbo-go/protocol" - "sync" - "time" ) var ( @@ -24,9 +25,10 @@ type Client interface { SetExchangeClient(client *ExchangeClient) SetResponseHandler(responseHandler ResponseHandler) //invoke once for connection + //ConfigClient() Connect(url common.URL) Close() - Request(request *Request, timeout time.Duration, callback common.AsyncCallback, response *PendingResponse) error + Request(request *Request, timeout time.Duration, response *PendingResponse) error } type ResponseHandler interface { @@ -58,7 +60,7 @@ func (client *ExchangeClient) Request(invocation *protocol.Invocation, url commo AddPendingResponse(rsp) //rsp.callback = invo - err := client.client.Request(request, timeout, nil, rsp) + err := client.client.Request(request, timeout, rsp) if err != nil { result.Err = err return err @@ -77,11 +79,11 @@ func (client *ExchangeClient) AsyncRequest(invocation *protocol.Invocation, url rsp := NewPendingResponse(request.Id) rsp.response = NewResponse(request.Id, "2.0.2") - rsp.callback = callback + rsp.Callback = callback rsp.Reply = (*invocation).Reply() AddPendingResponse(rsp) - err := client.client.Request(request, timeout, nil, rsp) + err := client.client.Request(request, timeout, rsp) if err != nil { result.Err = err return err @@ -93,16 +95,15 @@ func (client *ExchangeClient) AsyncRequest(invocation *protocol.Invocation, url // oneway func (client *ExchangeClient) Send(invocation *protocol.Invocation, timeout time.Duration) error { - requestId := int64(SequenceId()) request := NewRequest("2.0.2") request.Data = invocation request.Event = false request.TwoWay = false rsp := NewPendingResponse(request.Id) - rsp.response = NewResponse(requestId, "2.0.2") + rsp.response = NewResponse(request.Id, "2.0.2") - err := client.client.Request(request, timeout, nil, rsp) + err := client.client.Request(request, timeout, rsp) if err != nil { return err } @@ -124,10 +125,11 @@ func (client *ExchangeClient) Handler(response *Response) { pendingResponse.response = response - if pendingResponse.callback == nil { + if pendingResponse.Callback == nil { + pendingResponse.Err = pendingResponse.response.Error pendingResponse.Done <- struct{}{} } else { - pendingResponse.callback(pendingResponse.GetCallResponse()) + pendingResponse.Callback(pendingResponse.GetCallResponse()) } } diff --git a/remoting/getty/client.go b/remoting/getty/client.go deleted file mode 100644 index b76033c6e9f13b33915c184f2af99f58baa36586..0000000000000000000000000000000000000000 --- a/remoting/getty/client.go +++ /dev/null @@ -1,364 +0,0 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You under the Apache License, Version 2.0 -* (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* 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 getty -// -//import ( -// "github.com/apache/dubbo-go/remoting" -// "math/rand" -// "strings" -// "sync" -// "time" -//) -// -//import ( -// hessian "github.com/apache/dubbo-go-hessian2" -// "github.com/dubbogo/getty" -// gxsync "github.com/dubbogo/gost/sync" -// perrors "github.com/pkg/errors" -// "go.uber.org/atomic" -// "gopkg.in/yaml.v2" -//) -// -//import ( -// "github.com/apache/dubbo-go/common" -// "github.com/apache/dubbo-go/common/constant" -// "github.com/apache/dubbo-go/common/logger" -// "github.com/apache/dubbo-go/config" -//) -// -//var ( -// errInvalidCodecType = perrors.New("illegal CodecType") -// errInvalidAddress = perrors.New("remote address invalid or empty") -// errSessionNotExist = perrors.New("session not exist") -// errClientClosed = perrors.New("client closed") -// errClientReadTimeout = perrors.New("client read timeout") -// -// clientConf *ClientConfig -// clientGrpool *gxsync.TaskPool -//) -// -//func init() { -// -// // load clientconfig from consumer_config -// // default use dubbo -// consumerConfig := config.GetConsumerConfig() -// if consumerConfig.ApplicationConfig == nil { -// return -// } -// protocolConf := config.GetConsumerConfig().ProtocolConf -// defaultClientConfig := GetDefaultClientConfig() -// if protocolConf == nil { -// logger.Info("protocol_conf default use dubbo config") -// } else { -// dubboConf := protocolConf.(map[interface{}]interface{})[DUBBO] -// if dubboConf == nil { -// logger.Warnf("dubboConf is nil") -// return -// } -// dubboConfByte, err := yaml.Marshal(dubboConf) -// if err != nil { -// panic(err) -// } -// err = yaml.Unmarshal(dubboConfByte, &defaultClientConfig) -// if err != nil { -// panic(err) -// } -// } -// clientConf = &defaultClientConfig -// if err := clientConf.CheckValidity(); err != nil { -// logger.Warnf("[CheckValidity] error: %v", err) -// return -// } -// setClientGrpool() -// -// rand.Seed(time.Now().UnixNano()) -//} -// -//// SetClientConf ... -//func SetClientConf(c ClientConfig) { -// clientConf = &c -// err := clientConf.CheckValidity() -// if err != nil { -// logger.Warnf("[ClientConfig CheckValidity] error: %v", err) -// return -// } -// setClientGrpool() -//} -// -//// GetClientConf ... -//func GetClientConf() ClientConfig { -// return *clientConf -//} -// -//func setClientGrpool() { -// if clientConf.GrPoolSize > 1 { -// clientGrpool = gxsync.NewTaskPool(gxsync.WithTaskPoolTaskPoolSize(clientConf.GrPoolSize), gxsync.WithTaskPoolTaskQueueLength(clientConf.QueueLen), -// gxsync.WithTaskPoolTaskQueueNumber(clientConf.QueueNumber)) -// } -//} -// -//// Options ... -//type Options struct { -// // connect timeout -// ConnectTimeout time.Duration -// // request timeout -// RequestTimeout time.Duration -//} -// -////AsyncCallbackResponse async response for dubbo -//type AsyncCallbackResponse struct { -// common.CallbackResponse -// Opts Options -// Cause error -// Start time.Time // invoke(call) start time == write start time -// ReadStart time.Time // read start time, write duration = ReadStart - Start -// Reply interface{} -//} -// -//// Client ... -//type Client struct { -// opts Options -// conf ClientConfig -// pool *gettyRPCClientPool -// sequence atomic.Uint64 -// -// pendingResponses *sync.Map -//} -// -//// NewClient ... -//func NewClient(opt Options) *Client { -// -// switch { -// case opt.ConnectTimeout == 0: -// opt.ConnectTimeout = 3 * time.Second -// fallthrough -// case opt.RequestTimeout == 0: -// opt.RequestTimeout = 3 * time.Second -// } -// -// // make sure that client request sequence is an odd number -// initSequence := uint64(rand.Int63n(time.Now().UnixNano())) -// if initSequence%2 == 0 { -// initSequence++ -// } -// -// c := &Client{ -// opts: opt, -// pendingResponses: new(sync.Map), -// conf: *clientConf, -// } -// c.sequence.Store(initSequence) -// c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) -// -// return c -//} -// -////// Request ... -////type Request struct { -//// addr string -//// svcUrl common.URL -//// method string -//// args interface{} -//// atta map[string]string -////} -//// -////// NewRequest ... -////func NewRequest(addr string, svcUrl common.URL, method string, args interface{}, atta map[string]string) *Request { -//// return &Request{ -//// addr: addr, -//// svcUrl: svcUrl, -//// method: method, -//// args: args, -//// atta: atta, -//// } -////} -//// -////// Response ... -////type Response struct { -//// reply interface{} -//// atta map[string]string -////} -//// -////// NewResponse ... -////func NewResponse(reply interface{}, atta map[string]string) *Response { -//// return &Response{ -//// reply: reply, -//// atta: atta, -//// } -////} -// -//// CallOneway call one way -////func (c *Client) CallOneway(request *Request) error { -//// -//// return perrors.WithStack(c.call(CT_OneWay, request, NewResponse(nil, nil), nil)) -////} -//// -////// Call if @response is nil, the transport layer will get the response without notify the invoker. -////func (c *Client) Call(request *Request, response *Response) error { -//// -//// ct := CT_TwoWay -//// if response.reply == nil { -//// ct = CT_OneWay -//// } -//// -//// return perrors.WithStack(c.call(ct, request, response, nil)) -////} -//// -////// AsyncCall ... -////func (c *Client) AsyncCall(request *Request, callback common.AsyncCallback, response *Response) error { -//// -//// return perrors.WithStack(c.call(CT_TwoWay, request, response, callback)) -////} -// -//func (c *Client) call(ct CallType, request *Request, response *Response, callback common.AsyncCallback) error { -// -// p := &DubboPackage{} -// p.Service.Path = strings.TrimPrefix(request.svcUrl.Path, "/") -// p.Service.Interface = request.svcUrl.GetParam(constant.INTERFACE_KEY, "") -// p.Service.Version = request.svcUrl.GetParam(constant.VERSION_KEY, "") -// p.Service.Group = request.svcUrl.GetParam(constant.GROUP_KEY, "") -// p.Service.Method = request.method -// -// p.Service.Timeout = c.opts.RequestTimeout -// var timeout = request.svcUrl.GetParam(strings.Join([]string{constant.METHOD_KEYS, request.method + constant.RETRIES_KEY}, "."), "") -// if len(timeout) != 0 { -// if t, err := time.ParseDuration(timeout); err == nil { -// p.Service.Timeout = t -// } -// } -// -// p.Header.SerialID = byte(S_Dubbo) -// p.Body = hessian.NewRequest(request.args, request.atta) -// -// var rsp *PendingResponse -// if ct != CT_OneWay { -// p.Header.Type = hessian.PackageRequest_TwoWay -// rsp = NewPendingResponse() -// rsp.response = response -// rsp.callback = callback -// } else { -// p.Header.Type = hessian.PackageRequest -// } -// -// var ( -// err error -// session getty.Session -// conn *gettyRPCClient -// ) -// conn, session, err = c.selectSession(request.addr) -// if err != nil { -// return perrors.WithStack(err) -// } -// if session == nil { -// return errSessionNotExist -// } -// defer func() { -// if err == nil { -// c.pool.put(conn) -// return -// } -// conn.close() -// }() -// -// if err = c.transfer(session, p, rsp); err != nil { -// return perrors.WithStack(err) -// } -// -// if ct == CT_OneWay || callback != nil { -// return nil -// } -// -// select { -// case <-getty.GetTimeWheel().After(c.opts.RequestTimeout): -// c.removePendingResponse(SequenceType(rsp.seq)) -// return perrors.WithStack(errClientReadTimeout) -// case <-rsp.done: -// err = rsp.err -// } -// -// return perrors.WithStack(err) -//} -// -//// Close ... -//func (c *Client) Close() { -// if c.pool != nil { -// c.pool.close() -// } -// c.pool = nil -//} -// -//func (c *Client) selectSession(addr string) (*gettyRPCClient, getty.Session, error) { -// rpcClient, err := c.pool.getGettyRpcClient(DUBBO, addr) -// if err != nil { -// return nil, nil, perrors.WithStack(err) -// } -// return rpcClient, rpcClient.selectSession(), nil -//} -// -//func (c *Client) heartbeat(session getty.Session) error { -// req := remoting.NewRequest("2.0.2") -// req.TwoWay = true -// req.Event = true -// resp := remoting.NewPendingResponse() -// return c.transfer(session, req, 3 * time.Second, resp) -//} -// -//func (c *Client) transfer(session getty.Session, request *remoting.Request, timeout time.Duration, -// rsp *remoting.PendingResponse) error { -// -// //sequence = c.sequence.Add(1) -// // -// //if pkg == nil { -// // pkg = &DubboPackage{} -// // pkg.Body = hessian.NewRequest([]interface{}{}, nil) -// // pkg.Body = []interface{}{} -// // pkg.Header.Type = hessian.PackageHeartbeat -// // pkg.Header.SerialID = byte(S_Dubbo) -// //} -// //pkg.Header.ID = int64(sequence) -// -// // cond1 -// //if rsp != nil { -// // c.addPendingResponse(rsp) -// //} -// -// err := session.WritePkg(request, timeout) -// if rsp != nil { // cond2 -// // cond2 should not merged with cond1. cause the response package may be returned very -// // soon and it will be handled by other goroutine. -// rsp.ReadStart = time.Now() -// } -// -// return perrors.WithStack(err) -//} -// -//// -////func (c *Client) addPendingResponse(pr *PendingResponse) { -//// c.pendingResponses.Store(SequenceType(pr.seq), pr) -////} -//// -////func (c *Client) removePendingResponse(seq SequenceType) *PendingResponse { -//// if c.pendingResponses == nil { -//// return nil -//// } -//// if presp, ok := c.pendingResponses.Load(seq); ok { -//// c.pendingResponses.Delete(seq) -//// return presp.(*PendingResponse) -//// } -//// return nil -////} diff --git a/remoting/getty/client_test.go b/remoting/getty/client_test.go deleted file mode 100644 index d0a4c97e47ed21d8518e6f817bc134f5b62342f3..0000000000000000000000000000000000000000 --- a/remoting/getty/client_test.go +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 getty -// -//import ( -// "bytes" -// "context" -// "sync" -// "testing" -// "time" -//) -// -//import ( -// hessian "github.com/apache/dubbo-go-hessian2" -// perrors "github.com/pkg/errors" -// "github.com/stretchr/testify/assert" -//) -// -//import ( -// "github.com/apache/dubbo-go/common" -// "github.com/apache/dubbo-go/common/proxy/proxy_factory" -// "github.com/apache/dubbo-go/protocol" -//) -// -//func TestClient_CallOneway(t *testing.T) { -// proto, url := InitTest(t) -// -// c := &Client{ -// pendingResponses: new(sync.Map), -// conf: *clientConf, -// opts: Options{ -// ConnectTimeout: 3e9, -// RequestTimeout: 6e9, -// }, -// } -// c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) -// -// //user := &User{} -// err := c.CallOneway(NewRequest("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, nil)) -// assert.NoError(t, err) -// -// // destroy -// proto.Destroy() -//} -// -//func TestClient_Call(t *testing.T) { -// proto, url := InitTest(t) -// -// c := &Client{ -// pendingResponses: new(sync.Map), -// conf: *clientConf, -// opts: Options{ -// ConnectTimeout: 3e9, -// RequestTimeout: 10e9, -// }, -// } -// c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) -// -// var ( -// user *User -// err error -// ) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetBigPkg", []interface{}{nil}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.NotEqual(t, "", user.Id) -// assert.NotEqual(t, "", user.Name) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{Id: "1", Name: "username"}, *user) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser0", []interface{}{"1", nil, "username"}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{Id: "1", Name: "username"}, *user) -// -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser1", []interface{}{}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser2", []interface{}{}, nil), NewResponse(user, nil)) -// assert.EqualError(t, err, "error") -// -// user2 := []interface{}{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser3", []interface{}{}, nil), NewResponse(&user2, nil)) -// assert.NoError(t, err) -// assert.Equal(t, &User{Id: "1", Name: "username"}, user2[0]) -// -// user2 = []interface{}{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser4", []interface{}{[]interface{}{"1", "username"}}, nil), NewResponse(&user2, nil)) -// assert.NoError(t, err) -// assert.Equal(t, &User{Id: "1", Name: "username"}, user2[0]) -// -// user3 := map[interface{}]interface{}{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser5", []interface{}{map[interface{}]interface{}{"id": "1", "name": "username"}}, nil), NewResponse(&user3, nil)) -// assert.NoError(t, err) -// assert.NotNil(t, user3) -// assert.Equal(t, &User{Id: "1", Name: "username"}, user3["key"]) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser6", []interface{}{0}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{Id: "", Name: ""}, *user) -// -// user = &User{} -// err = c.Call(NewRequest("127.0.0.1:20000", url, "GetUser6", []interface{}{1}, nil), NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{Id: "1", Name: ""}, *user) -// -// // destroy -// proto.Destroy() -//} -// -//func TestClient_AsyncCall(t *testing.T) { -// proto, url := InitTest(t) -// -// c := &Client{ -// pendingResponses: new(sync.Map), -// conf: *clientConf, -// opts: Options{ -// ConnectTimeout: 3e9, -// RequestTimeout: 6e9, -// }, -// } -// c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) -// -// user := &User{} -// lock := sync.Mutex{} -// lock.Lock() -// err := c.AsyncCall(NewRequest("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, nil), func(response common.CallbackResponse) { -// r := response.(AsyncCallbackResponse) -// assert.Equal(t, User{Id: "1", Name: "username"}, *r.Reply.(*Response).reply.(*User)) -// lock.Unlock() -// }, NewResponse(user, nil)) -// assert.NoError(t, err) -// assert.Equal(t, User{}, *user) -// -// // destroy -// lock.Lock() -// proto.Destroy() -// lock.Unlock() -//} -// -//func InitTest(t *testing.T) (protocol.Protocol, common.URL) { -// -// hessian.RegisterPOJO(&User{}) -// -// methods, err := common.ServiceMap.Register("dubbo", &UserProvider{}) -// assert.NoError(t, err) -// assert.Equal(t, "GetBigPkg,GetUser,GetUser0,GetUser1,GetUser2,GetUser3,GetUser4,GetUser5,GetUser6", methods) -// -// // config -// SetClientConf(ClientConfig{ -// ConnectionNum: 2, -// HeartbeatPeriod: "5s", -// SessionTimeout: "20s", -// PoolTTL: 600, -// PoolSize: 64, -// GettySessionParam: GettySessionParam{ -// CompressEncoding: false, -// TcpNoDelay: true, -// TcpKeepAlive: true, -// KeepAlivePeriod: "120s", -// TcpRBufSize: 262144, -// TcpWBufSize: 65536, -// PkgWQSize: 512, -// TcpReadTimeout: "4s", -// TcpWriteTimeout: "5s", -// WaitTimeout: "1s", -// MaxMsgLen: 10240000000, -// SessionName: "client", -// }, -// }) -// assert.NoError(t, clientConf.CheckValidity()) -// SetServerConfig(ServerConfig{ -// SessionNumber: 700, -// SessionTimeout: "20s", -// GettySessionParam: GettySessionParam{ -// CompressEncoding: false, -// TcpNoDelay: true, -// TcpKeepAlive: true, -// KeepAlivePeriod: "120s", -// TcpRBufSize: 262144, -// TcpWBufSize: 65536, -// PkgWQSize: 512, -// TcpReadTimeout: "1s", -// TcpWriteTimeout: "5s", -// WaitTimeout: "1s", -// MaxMsgLen: 10240000000, -// SessionName: "server", -// }}) -// assert.NoError(t, srvConf.CheckValidity()) -// -// // Export -// proto := GetProtocol() -// url, err := common.NewURL("dubbo://127.0.0.1:20000/UserProvider?anyhost=true&" + -// "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" + -// "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&" + -// "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" + -// "side=provider&timeout=3000×tamp=1556509797245&bean.name=UserProvider") -// assert.NoError(t, err) -// proto.Export(&proxy_factory.ProxyInvoker{ -// BaseInvoker: *protocol.NewBaseInvoker(url), -// }) -// -// time.Sleep(time.Second * 2) -// -// return proto, url -//} -// -//////////////////////////////////// -//// provider -//////////////////////////////////// -// -//type ( -// User struct { -// Id string `json:"id"` -// Name string `json:"name"` -// } -// -// UserProvider struct { -// user map[string]User -// } -//) -// -//// size:4801228 -//func (u *UserProvider) GetBigPkg(ctx context.Context, req []interface{}, rsp *User) error { -// argBuf := new(bytes.Buffer) -// for i := 0; i < 4000; i++ { -// argBuf.WriteString("击鼓其镗,踊跃用兵。土国城漕,我独南行。从孙子仲,平陈与宋。不我以归,忧心有忡。爰居爰处?爰丧其马?于以求之?于林之下。死生契阔,与子成说。执子之手,与子偕老。于嗟阔兮,不我活兮。于嗟洵兮,不我信兮。") -// argBuf.WriteString("击鼓其镗,踊跃用兵。土国城漕,我独南行。从孙子仲,平陈与宋。不我以归,忧心有忡。爰居爰处?爰丧其马?于以求之?于林之下。死生契阔,与子成说。执子之手,与子偕老。于嗟阔兮,不我活兮。于嗟洵兮,不我信兮。") -// } -// rsp.Id = argBuf.String() -// rsp.Name = argBuf.String() -// return nil -//} -// -//func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error { -// rsp.Id = req[0].(string) -// rsp.Name = req[1].(string) -// return nil -//} -// -//func (u *UserProvider) GetUser0(id string, k *User, name string) (User, error) { -// return User{Id: id, Name: name}, nil -//} -// -//func (u *UserProvider) GetUser1() error { -// return nil -//} -// -//func (u *UserProvider) GetUser2() error { -// return perrors.New("error") -//} -// -//func (u *UserProvider) GetUser3(rsp *[]interface{}) error { -// *rsp = append(*rsp, User{Id: "1", Name: "username"}) -// return nil -//} -// -//func (u *UserProvider) GetUser4(ctx context.Context, req []interface{}) ([]interface{}, error) { -// -// return []interface{}{User{Id: req[0].([]interface{})[0].(string), Name: req[0].([]interface{})[1].(string)}}, nil -//} -// -//func (u *UserProvider) GetUser5(ctx context.Context, req []interface{}) (map[interface{}]interface{}, error) { -// return map[interface{}]interface{}{"key": User{Id: req[0].(map[interface{}]interface{})["id"].(string), Name: req[0].(map[interface{}]interface{})["name"].(string)}}, nil -//} -// -//func (u *UserProvider) GetUser6(id int64) (*User, error) { -// if id == 0 { -// return nil, nil -// } -// return &User{Id: "1"}, nil -//} -// -//func (u *UserProvider) Reference() string { -// return "UserProvider" -//} -// -//func (u User) JavaClassName() string { -// return "com.ikurento.user.User" -//} diff --git a/remoting/getty/dubbo_codec_for_test.go b/remoting/getty/dubbo_codec_for_test.go new file mode 100644 index 0000000000000000000000000000000000000000..46ef7b939e2d2e66ff4bcfecd5c2800520cfa07e --- /dev/null +++ b/remoting/getty/dubbo_codec_for_test.go @@ -0,0 +1,359 @@ +package getty + +import ( + "bufio" + "bytes" + "fmt" + "strconv" + "time" + + hessian "github.com/apache/dubbo-go-hessian2" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/remoting" + perrors "github.com/pkg/errors" +) + +//SerialID serial ID +type SerialID byte + +const ( + // S_Dubbo dubbo serial id + S_Dubbo SerialID = 2 +) + +func init() { + codec := &DubboTestCodec{} + remoting.NewCodec("dubbo", codec) +} + +// DubboPackage ... +type DubboPackage struct { + Header hessian.DubboHeader + Service hessian.Service + Body interface{} + Err error +} + +func (p DubboPackage) String() string { + return fmt.Sprintf("DubboPackage: Header-%v, Path-%v, Body-%v", p.Header, p.Service, p.Body) +} + +// Marshal ... +func (p *DubboPackage) Marshal() (*bytes.Buffer, error) { + codec := hessian.NewHessianCodec(nil) + + pkg, err := codec.Write(p.Service, p.Header, p.Body) + if err != nil { + return nil, perrors.WithStack(err) + } + + return bytes.NewBuffer(pkg), nil +} + +// Unmarshal ... +func (p *DubboPackage) Unmarshal(buf *bytes.Buffer, resp *remoting.Response) error { + // fix issue https://github.com/apache/dubbo-go/issues/380 + bufLen := buf.Len() + if bufLen < hessian.HEADER_LENGTH { + return perrors.WithStack(hessian.ErrHeaderNotEnough) + } + + codec := hessian.NewHessianCodec(bufio.NewReaderSize(buf, bufLen)) + + // read header + err := codec.ReadHeader(&p.Header) + if err != nil { + return perrors.WithStack(err) + } + + if resp != nil { // for client + if p.Header.Type&hessian.PackageRequest != 0x00 { + // size of this array must be '7' + // https://github.com/apache/dubbo-go-hessian2/blob/master/request.go#L272 + p.Body = make([]interface{}, 7) + } else { + pendingRsp := remoting.GetPendingResponse(remoting.SequenceType(p.Header.ID)) + if pendingRsp == nil { + return perrors.Errorf("client.GetPendingResponse(%v) = nil", p.Header.ID) + } + p.Body = &hessian.Response{RspObj: pendingRsp.Reply} + } + } + + // read body + err = codec.ReadBody(p.Body) + return perrors.WithStack(err) +} + +type DubboTestCodec struct { +} + +func (c *DubboTestCodec) EncodeRequest(request *remoting.Request) (*bytes.Buffer, error) { + if request.Event { + return c.encodeHeartbeartReqeust(request) + } + + invoc, ok := request.Data.(*invocation.RPCInvocation) + if !ok { + logger.Errorf("encode request failed for parameter type :%+v", request) + return nil, perrors.Errorf("encode request failed for parameter type :%+v", request) + } + invocation := *invoc + + p := &DubboPackage{} + p.Service.Path = invocation.AttachmentsByKey(constant.PATH_KEY, "") + p.Service.Interface = invocation.AttachmentsByKey(constant.INTERFACE_KEY, "") + p.Service.Version = invocation.AttachmentsByKey(constant.VERSION_KEY, "") + p.Service.Group = invocation.AttachmentsByKey(constant.GROUP_KEY, "") + p.Service.Method = invocation.MethodName() + + timeout, err := strconv.Atoi(invocation.AttachmentsByKey(constant.TIMEOUT_KEY, "3000")) + if err != nil { + panic(err) + } + p.Service.Timeout = time.Duration(timeout) + //var timeout = request.svcUrl.GetParam(strings.Join([]string{constant.METHOD_KEYS, request.method + constant.RETRIES_KEY}, "."), "") + //if len(timeout) != 0 { + // if t, err := time.ParseDuration(timeout); err == nil { + // p.Service.Timeout = t + // } + //} + + p.Header.SerialID = byte(S_Dubbo) + p.Header.ID = request.Id + if request.TwoWay { + p.Header.Type = hessian.PackageRequest_TwoWay + } else { + p.Header.Type = hessian.PackageRequest + } + + p.Body = hessian.NewRequest(invocation.Arguments(), invocation.Attachments()) + + codec := hessian.NewHessianCodec(nil) + + pkg, err := codec.Write(p.Service, p.Header, p.Body) + if err != nil { + return nil, perrors.WithStack(err) + } + + return bytes.NewBuffer(pkg), nil +} +func (c *DubboTestCodec) encodeHeartbeartReqeust(request *remoting.Request) (*bytes.Buffer, error) { + pkg := &DubboPackage{} + pkg.Body = []interface{}{} + pkg.Header.ID = request.Id + pkg.Header.Type = hessian.PackageHeartbeat + pkg.Header.SerialID = byte(S_Dubbo) + + codec := hessian.NewHessianCodec(nil) + + byt, err := codec.Write(pkg.Service, pkg.Header, pkg.Body) + if err != nil { + return nil, perrors.WithStack(err) + } + + return bytes.NewBuffer(byt), nil +} +func (c *DubboTestCodec) EncodeResponse(response *remoting.Response) (*bytes.Buffer, error) { + var ptype = hessian.PackageResponse + if response.IsHeartbeat() { + ptype = hessian.PackageHeartbeat + } + resp := &DubboPackage{ + Header: hessian.DubboHeader{ + SerialID: response.SerialID, + Type: ptype, + ID: response.Id, + ResponseStatus: response.Status, + }, + } + if !response.IsHeartbeat() { + resp.Body = &hessian.Response{ + RspObj: response.Result.(protocol.RPCResult).Rest, + Exception: response.Result.(protocol.RPCResult).Err, + Attachments: response.Result.(protocol.RPCResult).Attrs, + } + } + + //if response.Header.Type&hessian.PackageRequest != 0x00 { + // resp.Body = req.Body + //} else { + // resp.Body = nil + //} + codec := hessian.NewHessianCodec(nil) + + pkg, err := codec.Write(resp.Service, resp.Header, resp.Body) + if err != nil { + return nil, perrors.WithStack(err) + } + + return bytes.NewBuffer(pkg), nil +} +func (c *DubboTestCodec) Decode(data []byte) (remoting.DecodeResult, int, error) { + if c.isRequest(data) { + req, len, err := c.decodeRequest(data) + if err != nil { + return remoting.DecodeResult{}, len, err + } + return remoting.DecodeResult{IsRequest: true, Result: req}, len, err + } else { + resp, len, err := c.decodeResponse(data) + if err != nil { + return remoting.DecodeResult{}, len, err + } + return remoting.DecodeResult{IsRequest: false, Result: resp}, len, err + } +} +func (c *DubboTestCodec) isRequest(data []byte) bool { + if data[2]&byte(0x80) == 0x00 { + return false + } + return true +} + +func (c *DubboTestCodec) decodeRequest(data []byte) (*remoting.Request, int, error) { + pkg := &DubboPackage{ + Body: make([]interface{}, 7), + } + var request *remoting.Request = nil + buf := bytes.NewBuffer(data) + err := pkg.Unmarshal(buf, nil) + if err != nil { + originErr := perrors.Cause(err) + if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { + //FIXME + return nil, 0, originErr + } + logger.Errorf("pkg.Unmarshal(len(@data):%d) = error:%+v", buf.Len(), err) + + return request, 0, perrors.WithStack(err) + } + request = &remoting.Request{ + Id: pkg.Header.ID, + SerialID: pkg.Header.SerialID, + TwoWay: pkg.Header.Type&hessian.PackageRequest_TwoWay != 0x00, + Event: pkg.Header.Type&hessian.PackageHeartbeat != 0x00, + } + if pkg.Header.Type&hessian.PackageHeartbeat == 0x00 { + // convert params of request + req := pkg.Body.([]interface{}) // length of body should be 7 + if len(req) > 0 { + //invocation := request.Data.(*invocation.RPCInvocation) + var methodName string + var args []interface{} + var attachments map[string]string = make(map[string]string) + if req[0] != nil { + //dubbo version + request.Version = req[0].(string) + } + if req[1] != nil { + //path + attachments[constant.PATH_KEY] = req[1].(string) + } + if req[2] != nil { + //version + attachments[constant.VERSION_KEY] = req[2].(string) + } + if req[3] != nil { + //method + methodName = req[3].(string) + } + if req[4] != nil { + //argsType + //invocation.ParameterTypes(constant., req[1].(string)) + //argsTypes = req[4].(string) + } + if req[5] != nil { + args = req[5].([]interface{}) + } + if req[6] != nil { + attachments = req[6].(map[string]string) + } + //if pkg.Service.Path == "" && len(attachments[constant.PATH_KEY]) > 0 { + // pkg.Service.Path = attachments[constant.PATH_KEY] + //} + //if _, ok := attachments[constant.INTERFACE_KEY]; ok { + // pkg.Service.Interface = attachments[constant.INTERFACE_KEY] + //} else { + // pkg.Service.Interface = pkg.Service.Path + //} + //if len(attachments[constant.GROUP_KEY]) > 0 { + // pkg.Service.Group = attachments[constant.GROUP_KEY] + //} + invoc := invocation.NewRPCInvocationWithOptions(invocation.WithAttachments(attachments), + invocation.WithArguments(args), invocation.WithMethodName(methodName)) + request.Data = invoc + //pkg.Body = map[string]interface{}{ + // "dubboVersion": dubboVersion, + // "argsTypes": argsTypes, + // "args": args, + // "service": common.ServiceMap.GetService("dubbo", pkg.Service.Path), // path as a key + // "attachments": attachments, + //} + } + } + return request, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil +} + +func (c *DubboTestCodec) decodeResponse(data []byte) (*remoting.Response, int, error) { + pkg := &DubboPackage{} + buf := bytes.NewBuffer(data) + response := &remoting.Response{} + err := pkg.Unmarshal(buf, response) + if err != nil { + originErr := perrors.Cause(err) + if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { + return nil, 0, originErr + } + logger.Errorf("pkg.Unmarshal(len(@data):%d) = error:%+v", buf.Len(), err) + + return response, 0, perrors.WithStack(err) + } + response = &remoting.Response{ + Id: pkg.Header.ID, + //Version: pkg.Header., + SerialID: pkg.Header.SerialID, + Status: pkg.Header.ResponseStatus, + Event: (pkg.Header.Type & hessian.PackageHeartbeat) != 0, + } + var error error + if pkg.Header.Type&hessian.PackageHeartbeat != 0x00 { + if pkg.Header.Type&hessian.PackageResponse != 0x00 { + logger.Debugf("get rpc heartbeat response{header: %#v, body: %#v}", pkg.Header, pkg.Body) + if pkg.Err != nil { + logger.Errorf("rpc heartbeat response{error: %#v}", pkg.Err) + error = pkg.Err + } + } else { + logger.Debugf("get rpc heartbeat request{header: %#v, service: %#v, body: %#v}", pkg.Header, pkg.Service, pkg.Body) + response.Status = hessian.Response_OK + //reply(session, p, hessian.PackageHeartbeat) + } + return response, hessian.HEADER_LENGTH + pkg.Header.BodyLen, error + } + logger.Debugf("get rpc response{header: %#v, body: %#v}", pkg.Header, pkg.Body) + rpcResult := &protocol.RPCResult{} + response.Result = rpcResult + if pkg.Header.Type&hessian.PackageRequest == 0x00 { + if pkg.Err != nil { + rpcResult.Err = pkg.Err + } else if pkg.Body.(*hessian.Response).Exception != nil { + rpcResult.Err = pkg.Body.(*hessian.Response).Exception + response.Error = rpcResult.Err + } + rpcResult.Attrs = pkg.Body.(*hessian.Response).Attachments + rpcResult.Rest = pkg.Body.(*hessian.Response).RspObj + } + + //h.conn.updateSession(session) + //pendingResponse := h.conn.pool.rpcClient.removePendingResponse(SequenceType(p.Header.ID)) + //if pendingResponse == nil { + // logger.Errorf("failed to get pending response context for response package %s", *p) + // return + //} + + return response, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil +} diff --git a/remoting/getty/getty_client.go b/remoting/getty/getty_client.go index c22f576872387448c187ecaa39d8603865b854ce..8544b8e17f4b93cd3a0bd1d47c5e8b96b7002e2e 100644 --- a/remoting/getty/getty_client.go +++ b/remoting/getty/getty_client.go @@ -18,22 +18,19 @@ package getty import ( - "github.com/apache/dubbo-go/remoting" - "gopkg.in/yaml.v2" "math/rand" "time" -) -import ( + "github.com/apache/dubbo-go/remoting" "github.com/dubbogo/getty" + "gopkg.in/yaml.v2" + gxsync "github.com/dubbogo/gost/sync" - perrors "github.com/pkg/errors" -) -import ( "github.com/apache/dubbo-go/common" "github.com/apache/dubbo-go/common/logger" "github.com/apache/dubbo-go/config" + perrors "github.com/pkg/errors" ) var ( @@ -98,11 +95,6 @@ func SetClientConf(c ClientConfig) { setClientGrpool() } -// GetClientConf ... -func GetClientConf() ClientConfig { - return *clientConf -} - func setClientGrpool() { if clientConf.GrPoolSize > 1 { clientGrpool = gxsync.NewTaskPool(gxsync.WithTaskPoolTaskPoolSize(clientConf.GrPoolSize), gxsync.WithTaskPoolTaskQueueLength(clientConf.QueueLen), @@ -114,19 +106,17 @@ func setClientGrpool() { type Options struct { // connect timeout ConnectTimeout time.Duration - // request timeout - //RequestTimeout time.Duration } -//AsyncCallbackResponse async response for dubbo -type AsyncCallbackResponse struct { - common.CallbackResponse - Opts Options - Cause error - Start time.Time // invoke(call) start time == write start time - ReadStart time.Time // read start time, write duration = ReadStart - Start - Reply interface{} -} +////AsyncCallbackResponse async response for dubbo +//type AsyncCallbackResponse struct { +// common.CallbackResponse +// Opts Options +// Cause error +// Start time.Time // invoke(call) start time == write start time +// ReadStart time.Time // read start time, write duration = ReadStart - Start +// Reply interface{} +//} // Client ... type Client struct { @@ -137,8 +127,6 @@ type Client struct { codec remoting.Codec responseHandler remoting.ResponseHandler ExchangeClient *remoting.ExchangeClient - //sequence atomic.Uint64 - //pendingResponses *sync.Map } // NewClient ... @@ -160,6 +148,7 @@ func (c *Client) SetExchangeClient(client *remoting.ExchangeClient) { func (c *Client) SetResponseHandler(responseHandler remoting.ResponseHandler) { c.responseHandler = responseHandler } + func (c *Client) Connect(url common.URL) { initClient(url.Protocol) c.conf = *clientConf @@ -169,41 +158,15 @@ func (c *Client) Connect(url common.URL) { c.codec = remoting.GetCodec(url.Protocol) c.addr = url.Location } + func (c *Client) Close() { if c.pool != nil { c.pool.close() } c.pool = nil } -func (c *Client) Request(request *remoting.Request, timeout time.Duration, callback common.AsyncCallback, response *remoting.PendingResponse) error { - //p := &DubboPackage{} - //p.Service.Path = strings.TrimPrefix(request.svcUrl.Path, "/") - //p.Service.Interface = request.svcUrl.GetParam(constant.INTERFACE_KEY, "") - //p.Service.Version = request.svcUrl.GetParam(constant.VERSION_KEY, "") - //p.Service.Group = request.svcUrl.GetParam(constant.GROUP_KEY, "") - //p.Service.Method = request.method - // - //p.Service.Timeout = c.opts.RequestTimeout - //var timeout = request.svcUrl.GetParam(strings.Join([]string{constant.METHOD_KEYS, request.method + constant.RETRIES_KEY}, "."), "") - //if len(timeout) != 0 { - // if t, err := time.ParseDuration(timeout); err == nil { - // p.Service.Timeout = t - // } - //} - // - //p.Header.SerialID = byte(S_Dubbo) - //p.Body = hessian.NewRequest(request.args, request.atta) - // - //var rsp *PendingResponse - //if ct != CT_OneWay { - // p.Header.Type = hessian.PackageRequest_TwoWay - // rsp = NewPendingResponse() - // rsp.response = response - // rsp.callback = callback - //} else { - // p.Header.Type = hessian.PackageRequest - //} +func (c *Client) Request(request *remoting.Request, timeout time.Duration, response *remoting.PendingResponse) error { var ( err error @@ -225,11 +188,11 @@ func (c *Client) Request(request *remoting.Request, timeout time.Duration, callb conn.close() }() - if err = c.transfer(session, request, timeout, response); err != nil { + if err = c.transfer(session, request, timeout); err != nil { return perrors.WithStack(err) } - if !request.TwoWay || callback != nil { + if !request.TwoWay || response.Callback != nil { return nil } @@ -243,98 +206,6 @@ func (c *Client) Request(request *remoting.Request, timeout time.Duration, callb return perrors.WithStack(err) } -// CallOneway call one way -//func (c *Client) CallOneway(request *Request) error { -// -// return perrors.WithStack(c.call(CT_OneWay, request, NewResponse(nil, nil), nil)) -//} -// -//// Call if @response is nil, the transport layer will get the response without notify the invoker. -//func (c *Client) Call(request *Request, response *Response) error { -// -// ct := CT_TwoWay -// if response.reply == nil { -// ct = CT_OneWay -// } -// -// return perrors.WithStack(c.call(ct, request, response, nil)) -//} -// -//// AsyncCall ... -//func (c *Client) AsyncCall(request *Request, callback common.AsyncCallback, response *Response) error { -// -// return perrors.WithStack(c.call(CT_TwoWay, request, response, callback)) -//} -// -//func (c *Client) call(ct CallType, request *Request, response *Response, callback common.AsyncCallback) error { -// -// p := &DubboPackage{} -// p.Service.Path = strings.TrimPrefix(request.svcUrl.Path, "/") -// p.Service.Interface = request.svcUrl.GetParam(constant.INTERFACE_KEY, "") -// p.Service.Version = request.svcUrl.GetParam(constant.VERSION_KEY, "") -// p.Service.Group = request.svcUrl.GetParam(constant.GROUP_KEY, "") -// p.Service.Method = request.method -// -// p.Service.Timeout = c.opts.RequestTimeout -// var timeout = request.svcUrl.GetParam(strings.Join([]string{constant.METHOD_KEYS, request.method + constant.RETRIES_KEY}, "."), "") -// if len(timeout) != 0 { -// if t, err := time.ParseDuration(timeout); err == nil { -// p.Service.Timeout = t -// } -// } -// -// p.Header.SerialID = byte(S_Dubbo) -// p.Body = hessian.NewRequest(request.args, request.atta) -// -// var rsp *PendingResponse -// if ct != CT_OneWay { -// p.Header.Type = hessian.PackageRequest_TwoWay -// rsp = NewPendingResponse() -// rsp.response = response -// rsp.callback = callback -// } else { -// p.Header.Type = hessian.PackageRequest -// } -// -// var ( -// err error -// session getty.Session -// conn *gettyRPCClient -// ) -// conn, session, err = c.selectSession(request.addr) -// if err != nil { -// return perrors.WithStack(err) -// } -// if session == nil { -// return errSessionNotExist -// } -// defer func() { -// if err == nil { -// c.pool.put(conn) -// return -// } -// conn.close() -// }() -// -// if err = c.transfer(session, p, rsp); err != nil { -// return perrors.WithStack(err) -// } -// -// if ct == CT_OneWay || callback != nil { -// return nil -// } -// -// select { -// case <-getty.GetTimeWheel().After(c.opts.RequestTimeout): -// c.removePendingResponse(SequenceType(rsp.seq)) -// return perrors.WithStack(errClientReadTimeout) -// case <-rsp.done: -// err = rsp.err -// } -// -// return perrors.WithStack(err) -//} - func (c *Client) selectSession(addr string) (*gettyRPCClient, getty.Session, error) { rpcClient, err := c.pool.getGettyRpcClient(addr) if err != nil { @@ -349,49 +220,15 @@ func (c *Client) heartbeat(session getty.Session) error { req.Event = true resp := remoting.NewPendingResponse(req.Id) remoting.AddPendingResponse(resp) - return c.transfer(session, req, 3*time.Second, resp) + return c.transfer(session, req, 3*time.Second) } -func (c *Client) transfer(session getty.Session, request *remoting.Request, timeout time.Duration, - rsp *remoting.PendingResponse) error { - //sequence = c.sequence.Add(1) - // - //if pkg == nil { - // pkg = &DubboPackage{} - // pkg.Body = hessian.NewRequest([]interface{}{}, nil) - // pkg.Body = []interface{}{} - // pkg.Header.Type = hessian.PackageHeartbeat - // pkg.Header.SerialID = byte(S_Dubbo) - //} - //pkg.Header.ID = int64(sequence) - - // cond1 - //if rsp != nil { - // c.addPendingResponse(rsp) - //} - +func (c *Client) transfer(session getty.Session, request *remoting.Request, timeout time.Duration) error { err := session.WritePkg(request, timeout) - if rsp != nil { // cond2 - // cond2 should not merged with cond1. cause the response package may be returned very - // soon and it will be handled by other goroutine. - rsp.ReadStart = time.Now() - } - + //if rsp != nil { // cond2 + // // cond2 should not merged with cond1. cause the response package may be returned very + // // soon and it will be handled by other goroutine. + // rsp.ReadStart = time.Now() + //} return perrors.WithStack(err) } - -// -//func (c *Client) addPendingResponse(pr *PendingResponse) { -// c.pendingResponses.Store(SequenceType(pr.seq), pr) -//} -// -//func (c *Client) removePendingResponse(seq SequenceType) *PendingResponse { -// if c.pendingResponses == nil { -// return nil -// } -// if presp, ok := c.pendingResponses.Load(seq); ok { -// c.pendingResponses.Delete(seq) -// return presp.(*PendingResponse) -// } -// return nil -//} diff --git a/remoting/getty/getty_client_test.go b/remoting/getty/getty_client_test.go new file mode 100644 index 0000000000000000000000000000000000000000..9fa46daaf3fbeee6b5802e8df5e322f93c0fa9dd --- /dev/null +++ b/remoting/getty/getty_client_test.go @@ -0,0 +1,497 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 getty + +import ( + "bytes" + "context" + "reflect" + "sync" + "testing" + "time" + + "github.com/apache/dubbo-go/common/proxy/proxy_factory" + + "github.com/apache/dubbo-go/config" + + "github.com/apache/dubbo-go/remoting" + + "github.com/apache/dubbo-go/protocol/invocation" + + hessian "github.com/apache/dubbo-go-hessian2" + + "github.com/apache/dubbo-go/common" + . "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/protocol" + perrors "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +func TestRunSuite(t *testing.T) { + svr, url := InitTest(t) + client := getClient(url) + testRequestOneWay(t, svr, url, client) + testClient_Call(t, svr, url, client) + testClient_AsyncCall(t, svr, url, client) + + svr.Stop() +} + +func testRequestOneWay(t *testing.T, svr *Server, url common.URL, client *Client) { + + request := remoting.NewRequest("2.0.2") + up := &UserProvider{} + invocation := createInvocation("GetUser", nil, nil, []interface{}{[]interface{}{"1", "username"}, up}, + []reflect.Value{reflect.ValueOf([]interface{}{"1", "username"}), reflect.ValueOf(up)}) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = false + //user := &User{} + err := client.Request(request, 3*time.Second, nil) + assert.NoError(t, err) +} + +func createInvocation(methodName string, callback interface{}, reply interface{}, arguments []interface{}, + parameterValues []reflect.Value) *invocation.RPCInvocation { + return invocation.NewRPCInvocationWithOptions(invocation.WithMethodName(methodName), + invocation.WithArguments(arguments), invocation.WithReply(reply), + invocation.WithCallBack(callback), invocation.WithParameterValues(parameterValues)) +} + +func setAttachment(invocation *invocation.RPCInvocation, attachments map[string]string) { + for key, value := range attachments { + invocation.SetAttachments(key, value) + } +} + +func getClient(url common.URL) *Client { + client := NewClient(Options{ + ConnectTimeout: config.GetConsumerConfig().ConnectTimeout, + }) + + exchangeClient := remoting.NewExchangeClient(url, client, 5*time.Second) + client.SetExchangeClient(exchangeClient) + client.Connect(url) + client.SetResponseHandler(exchangeClient) + return client +} + +func testClient_Call(t *testing.T, svr *Server, url common.URL, c *Client) { + c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) + + testGetBigPkg(t, c) + testGetUser(t, c) + testGetUser0(t, c) + testGetUser1(t, c) + testGetUser2(t, c) + testGetUser3(t, c) + testGetUser4(t, c) + testGetUser5(t, c) + testGetUser6(t, c) + testGetUser61(t, c) + +} +func testGetBigPkg(t *testing.T, c *Client) { + var ( + user *User + err error + ) + + user = &User{} + request := remoting.NewRequest("2.0.2") + invocation := createInvocation("GetBigPkg", nil, nil, []interface{}{[]interface{}{nil}, user}, + []reflect.Value{reflect.ValueOf([]interface{}{nil}), reflect.ValueOf(user)}) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + pendingResponse.Reply = user + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 8*time.Second, pendingResponse) + assert.NoError(t, err) + assert.NotEqual(t, "", user.Id) + assert.NotEqual(t, "", user.Name) +} +func testGetUser(t *testing.T, c *Client) { + var ( + user *User + err error + ) + user = &User{} + request := remoting.NewRequest("2.0.2") + invocation := createInvocation("GetUser", nil, nil, []interface{}{"1", "username"}, + []reflect.Value{reflect.ValueOf("1"), reflect.ValueOf("username")}) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + pendingResponse.Reply = user + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 3*time.Second, pendingResponse) + assert.NoError(t, err) + assert.Equal(t, User{Id: "1", Name: "username"}, *user) +} + +func testGetUser0(t *testing.T, c *Client) { + var ( + user *User + err error + ) + user = &User{} + request := remoting.NewRequest("2.0.2") + invocation := createInvocation("GetUser0", nil, nil, []interface{}{"1", nil, "username"}, + []reflect.Value{reflect.ValueOf("1"), reflect.ValueOf(nil), reflect.ValueOf("username")}) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + rsp := remoting.NewPendingResponse(request.Id) + rsp.SetResponse(remoting.NewResponse(request.Id, "2.0.2")) + remoting.AddPendingResponse(rsp) + rsp.Reply = user + err = c.Request(request, 3*time.Second, rsp) + assert.NoError(t, err) + assert.Equal(t, User{Id: "1", Name: "username"}, *user) +} +func testGetUser1(t *testing.T, c *Client) { + var ( + err error + ) + request := remoting.NewRequest("2.0.2") + invocation := createInvocation("GetUser1", nil, nil, []interface{}{}, + []reflect.Value{}) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + user := &User{} + pendingResponse.Reply = user + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 3*time.Second, pendingResponse) + assert.NoError(t, err) +} +func testGetUser2(t *testing.T, c *Client) { + var ( + err error + ) + request := remoting.NewRequest("2.0.2") + invocation := createInvocation("GetUser2", nil, nil, []interface{}{}, + []reflect.Value{}) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 3*time.Second, pendingResponse) + assert.EqualError(t, err, "error") +} +func testGetUser3(t *testing.T, c *Client) { + var ( + err error + ) + request := remoting.NewRequest("2.0.2") + invocation := createInvocation("GetUser3", nil, nil, []interface{}{}, + []reflect.Value{}) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + user2 := []interface{}{} + pendingResponse.Reply = &user2 + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 3*time.Second, pendingResponse) + assert.NoError(t, err) + assert.Equal(t, &User{Id: "1", Name: "username"}, user2[0]) +} +func testGetUser4(t *testing.T, c *Client) { + var ( + err error + ) + request := remoting.NewRequest("2.0.2") + invocation := invocation.NewRPCInvocation("GetUser4", []interface{}{[]interface{}{"1", "username"}}, nil) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + user2 := []interface{}{} + pendingResponse.Reply = &user2 + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 3*time.Second, pendingResponse) + assert.NoError(t, err) + assert.Equal(t, &User{Id: "1", Name: "username"}, user2[0]) +} + +func testGetUser5(t *testing.T, c *Client) { + var ( + err error + ) + request := remoting.NewRequest("2.0.2") + invocation := invocation.NewRPCInvocation("GetUser5", []interface{}{map[interface{}]interface{}{"id": "1", "name": "username"}}, nil) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + user3 := map[interface{}]interface{}{} + pendingResponse.Reply = &user3 + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 3*time.Second, pendingResponse) + assert.NoError(t, err) + assert.NotNil(t, user3) + assert.Equal(t, &User{Id: "1", Name: "username"}, user3["key"]) +} + +func testGetUser6(t *testing.T, c *Client) { + var ( + user *User + err error + ) + user = &User{} + request := remoting.NewRequest("2.0.2") + invocation := invocation.NewRPCInvocation("GetUser6", []interface{}{0}, nil) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + pendingResponse.Reply = user + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 3*time.Second, pendingResponse) + assert.NoError(t, err) + assert.Equal(t, User{Id: "", Name: ""}, *user) +} + +func testGetUser61(t *testing.T, c *Client) { + var ( + user *User + err error + ) + user = &User{} + request := remoting.NewRequest("2.0.2") + invocation := invocation.NewRPCInvocation("GetUser6", []interface{}{1}, nil) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + pendingResponse := remoting.NewPendingResponse(request.Id) + pendingResponse.Reply = user + remoting.AddPendingResponse(pendingResponse) + err = c.Request(request, 3*time.Second, pendingResponse) + assert.NoError(t, err) + assert.Equal(t, User{Id: "1", Name: ""}, *user) +} + +func testClient_AsyncCall(t *testing.T, svr *Server, url common.URL, client *Client) { + user := &User{} + lock := sync.Mutex{} + request := remoting.NewRequest("2.0.2") + invocation := createInvocation("GetUser0", nil, nil, []interface{}{"4", nil, "username"}, + []reflect.Value{reflect.ValueOf("4"), reflect.ValueOf(nil), reflect.ValueOf("username")}) + attachment := map[string]string{INTERFACE_KEY: "com.ikurento.user.UserProvider"} + setAttachment(invocation, attachment) + request.Data = invocation + request.Event = false + request.TwoWay = true + rsp := remoting.NewPendingResponse(request.Id) + rsp.SetResponse(remoting.NewResponse(request.Id, "2.0.2")) + remoting.AddPendingResponse(rsp) + rsp.Reply = user + rsp.Callback = func(response common.CallbackResponse) { + r := response.(remoting.AsyncCallbackResponse) + rst := *r.Reply.(*remoting.Response).Result.(*protocol.RPCResult) + assert.Equal(t, User{Id: "4", Name: "username"}, *(rst.Rest.(*User))) + lock.Unlock() + } + lock.Lock() + err := client.Request(request, 3*time.Second, rsp) + assert.NoError(t, err) + assert.Equal(t, User{}, *user) + time.Sleep(1 * time.Second) +} + +func InitTest(t *testing.T) (*Server, common.URL) { + + hessian.RegisterPOJO(&User{}) + remoting.NewCodec("dubbo", &DubboTestCodec{}) + + methods, err := common.ServiceMap.Register("dubbo", &UserProvider{}) + assert.NoError(t, err) + assert.Equal(t, "GetBigPkg,GetUser,GetUser0,GetUser1,GetUser2,GetUser3,GetUser4,GetUser5,GetUser6", methods) + + // config + SetClientConf(ClientConfig{ + ConnectionNum: 2, + HeartbeatPeriod: "5s", + SessionTimeout: "20s", + PoolTTL: 600, + PoolSize: 64, + GettySessionParam: GettySessionParam{ + CompressEncoding: false, + TcpNoDelay: true, + TcpKeepAlive: true, + KeepAlivePeriod: "120s", + TcpRBufSize: 262144, + TcpWBufSize: 65536, + PkgWQSize: 512, + TcpReadTimeout: "4s", + TcpWriteTimeout: "5s", + WaitTimeout: "1s", + MaxMsgLen: 10240000000, + SessionName: "client", + }, + }) + assert.NoError(t, clientConf.CheckValidity()) + SetServerConfig(ServerConfig{ + SessionNumber: 700, + SessionTimeout: "20s", + GettySessionParam: GettySessionParam{ + CompressEncoding: false, + TcpNoDelay: true, + TcpKeepAlive: true, + KeepAlivePeriod: "120s", + TcpRBufSize: 262144, + TcpWBufSize: 65536, + PkgWQSize: 512, + TcpReadTimeout: "1s", + TcpWriteTimeout: "5s", + WaitTimeout: "1s", + MaxMsgLen: 10240000000, + SessionName: "server", + }}) + assert.NoError(t, srvConf.CheckValidity()) + + url, err := common.NewURL("dubbo://127.0.0.1:20060/UserProvider?anyhost=true&" + + "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" + + "environment=dev&interface=com.ikurento.user.UserProvider&ip=127.0.0.1&methods=GetUser%2C&" + + "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" + + "side=provider&timeout=3000×tamp=1556509797245&bean.name=UserProvider") + // init server + userProvider := &UserProvider{} + common.ServiceMap.Register(url.Protocol, userProvider) + invoker := &proxy_factory.ProxyInvoker{ + BaseInvoker: *protocol.NewBaseInvoker(url), + } + handler := func(invocation *invocation.RPCInvocation) protocol.RPCResult { + //result := protocol.RPCResult{} + r := invoker.Invoke(context.Background(), invocation) + result := protocol.RPCResult{ + Err: r.Error(), + Rest: r.Result(), + Attrs: r.Attachments(), + } + return result + } + server := NewServer(url, handler) + server.Start() + + time.Sleep(time.Second * 2) + + return server, url +} + +////////////////////////////////// +// provider +////////////////////////////////// + +type ( + User struct { + Id string `json:"id"` + Name string `json:"name"` + } + + UserProvider struct { + user map[string]User + } +) + +// size:4801228 +func (u *UserProvider) GetBigPkg(ctx context.Context, req []interface{}, rsp *User) error { + argBuf := new(bytes.Buffer) + for i := 0; i < 400; i++ { + argBuf.WriteString("击鼓其镗,踊跃用兵。土国城漕,我独南行。从孙子仲,平陈与宋。不我以归,忧心有忡。爰居爰处?爰丧其马?于以求之?于林之下。死生契阔,与子成说。执子之手,与子偕老。于嗟阔兮,不我活兮。于嗟洵兮,不我信兮。") + argBuf.WriteString("击鼓其镗,踊跃用兵。土国城漕,我独南行。从孙子仲,平陈与宋。不我以归,忧心有忡。爰居爰处?爰丧其马?于以求之?于林之下。死生契阔,与子成说。执子之手,与子偕老。于嗟阔兮,不我活兮。于嗟洵兮,不我信兮。") + } + rsp.Id = argBuf.String() + rsp.Name = argBuf.String() + return nil +} + +func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error { + rsp.Id = req[0].(string) + rsp.Name = req[1].(string) + return nil +} + +func (u *UserProvider) GetUser0(id string, k *User, name string) (User, error) { + return User{Id: id, Name: name}, nil +} + +func (u *UserProvider) GetUser1() error { + return nil +} + +func (u *UserProvider) GetUser2() error { + return perrors.New("error") +} + +func (u *UserProvider) GetUser3(rsp *[]interface{}) error { + *rsp = append(*rsp, User{Id: "1", Name: "username"}) + return nil +} + +func (u *UserProvider) GetUser4(ctx context.Context, req []interface{}) ([]interface{}, error) { + + return []interface{}{User{Id: req[0].([]interface{})[0].(string), Name: req[0].([]interface{})[1].(string)}}, nil +} + +func (u *UserProvider) GetUser5(ctx context.Context, req []interface{}) (map[interface{}]interface{}, error) { + return map[interface{}]interface{}{"key": User{Id: req[0].(map[interface{}]interface{})["id"].(string), Name: req[0].(map[interface{}]interface{})["name"].(string)}}, nil +} + +func (u *UserProvider) GetUser6(id int64) (*User, error) { + if id == 0 { + return nil, nil + } + return &User{Id: "1"}, nil +} + +func (u *UserProvider) Reference() string { + return "UserProvider" +} + +func (u User) JavaClassName() string { + return "com.ikurento.user.User" +} diff --git a/remoting/getty/server.go b/remoting/getty/getty_server.go similarity index 98% rename from remoting/getty/server.go rename to remoting/getty/getty_server.go index 00fba5cae371f846ccd0d19233af6d723ac256e4..874d0401f50e08583a7fec264701ebf684342698 100644 --- a/remoting/getty/server.go +++ b/remoting/getty/getty_server.go @@ -19,22 +19,18 @@ package getty import ( "fmt" + "net" + "github.com/apache/dubbo-go/protocol" "github.com/apache/dubbo-go/protocol/invocation" "github.com/apache/dubbo-go/remoting" - "net" -) - -import ( "github.com/dubbogo/getty" - "github.com/dubbogo/gost/sync" - "gopkg.in/yaml.v2" -) -import ( "github.com/apache/dubbo-go/common" "github.com/apache/dubbo-go/common/logger" "github.com/apache/dubbo-go/config" + gxsync "github.com/dubbogo/gost/sync" + "gopkg.in/yaml.v2" ) var ( diff --git a/remoting/getty/listener.go b/remoting/getty/listener.go index 0dc2792a239bc432b91659f35a59a65f571f2f51..156a4046cb1704c95d87bcd6d8034867b68b1a6e 100644 --- a/remoting/getty/listener.go +++ b/remoting/getty/listener.go @@ -18,25 +18,20 @@ package getty import ( - "context" "fmt" - "github.com/apache/dubbo-go/remoting" "sync" "sync/atomic" "time" -) - -import ( - "github.com/apache/dubbo-go-hessian2" - "github.com/dubbogo/getty" - "github.com/opentracing/opentracing-go" - perrors "github.com/pkg/errors" -) -import ( "github.com/apache/dubbo-go/common/constant" + + "github.com/apache/dubbo-go/remoting" + + hessian "github.com/apache/dubbo-go-hessian2" "github.com/apache/dubbo-go/common/logger" "github.com/apache/dubbo-go/protocol/invocation" + "github.com/dubbogo/getty" + perrors "github.com/pkg/errors" ) // todo: WritePkg_Timeout will entry *.yml @@ -96,37 +91,48 @@ func (h *RpcClientHandler) OnClose(session getty.Session) { // OnMessage ... func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) { - p, ok := pkg.(*remoting.Response) + result, ok := pkg.(remoting.DecodeResult) if !ok { logger.Errorf("illegal package") return } + // get heartbeart request from server + if result.IsRequest { + req := result.Result.(*remoting.Request) + if req.Event { + logger.Debugf("get rpc heartbeat request{%#v}", req) + resp := remoting.NewResponse(req.Id, req.Version) + resp.Status = hessian.Response_OK + resp.Event = req.Event + resp.SerialID = req.SerialID + resp.Version = "2.0.2" + reply(session, resp, hessian.PackageHeartbeat) + return + } + logger.Errorf("illegal request but not heartbeart. {%#v}", req) + return + } + p := result.Result.(*remoting.Response) + // get heartbeart if p.Event { logger.Debugf("get rpc heartbeat response{%#v}", p) if p.Error != nil { logger.Errorf("rpc heartbeat response{error: %#v}", p.Error) } - (h.conn.pool.rpcClient.responseHandler).Handler(p) - //FIXME - //if p.Header.Type&hessian.PackageResponse != 0x00 { - // logger.Debugf("get rpc heartbeat response{header: %#v, body: %#v}", p.Header, p.Body) - // if p.Err != nil { - // logger.Errorf("rpc heartbeat response{error: %#v}", p.Err) - // } - // h.conn.pool.rpcClient.removePendingResponse(SequenceType(p.Header.ID)) - //} else { - // logger.Debugf("get rpc heartbeat request{header: %#v, service: %#v, body: %#v}", p.Header, p.Service, p.Body) - // p.Header.ResponseStatus = hessian.Response_OK - // reply(session, p, hessian.PackageHeartbeat) - //} + h.conn.pool.rpcClient.responseHandler.Handler(p) + return + } + if result.IsRequest { + logger.Errorf("illegal package for it is response type. {%#v}", pkg) return } + logger.Debugf("get rpc response{%#v}", p) h.conn.updateSession(session) - (h.conn.pool.rpcClient.responseHandler).Handler(p) + h.conn.pool.rpcClient.responseHandler.Handler(p) // //pendingResponse := h.conn.pool.rpcClient.removePendingResponse(SequenceType(p.Header.ID)) @@ -232,11 +238,17 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) { } h.rwlock.Unlock() - req, ok := pkg.(*remoting.Request) + decodeResult, ok := pkg.(remoting.DecodeResult) if !ok { logger.Errorf("illegal package{%#v}", pkg) return } + if !decodeResult.IsRequest { + logger.Errorf("illegal package for it is response type. {%#v}", pkg) + return + } + req := decodeResult.Result.(*remoting.Request) + resp := remoting.NewResponse(req.Id, req.Version) resp.Status = hessian.Response_OK resp.Event = req.Event @@ -280,8 +292,13 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) { invoc, ok := req.Data.(*invocation.RPCInvocation) if !ok { - + panic("create invocation occur some exception for the type is not suitable one.") + return } + attachments := invoc.Attachments() + attachments[constant.LOCAL_ADDR] = session.LocalAddr() + attachments[constant.REMOTE_ADDR] = session.RemoteAddr() + result := h.server.requestHandler(invoc) if !req.TwoWay { return @@ -316,21 +333,6 @@ func (h *RpcServerHandler) OnCron(session getty.Session) { } } -// rebuildCtx rebuild the context by attachment. -// Once we decided to transfer more context's key-value, we should change this. -// now we only support rebuild the tracing context -func RebuildCtx(inv *invocation.RPCInvocation) context.Context { - ctx := context.Background() - - // actually, if user do not use any opentracing framework, the err will not be nil. - spanCtx, err := opentracing.GlobalTracer().Extract(opentracing.TextMap, - opentracing.TextMapCarrier(inv.Attachments())) - if err == nil { - ctx = context.WithValue(ctx, constant.TRACING_REMOTE_SPAN_CTX, spanCtx) - } - return ctx -} - func reply(session getty.Session, resp *remoting.Response, tp hessian.PackageType) { //resp := &DubboPackage{ // Header: hessian.DubboHeader{ diff --git a/remoting/getty/listener_test.go b/remoting/getty/listener_test.go index a7feeddce0ee709f99a9cd9fb4616036ddcb3689..49e13d39c9f14ea48551f54f0b1c7f880d1bdd5e 100644 --- a/remoting/getty/listener_test.go +++ b/remoting/getty/listener_test.go @@ -17,42 +17,53 @@ package getty -//import ( -// "testing" -//) -// -//import ( -// "github.com/opentracing/opentracing-go" -// "github.com/opentracing/opentracing-go/mocktracer" -// "github.com/stretchr/testify/assert" -//) -// -//import ( -// "github.com/apache/dubbo-go/common/constant" -// "github.com/apache/dubbo-go/protocol/invocation" -//) -// -//// test rebuild the ctx -//func TestRebuildCtx(t *testing.T) { -// opentracing.SetGlobalTracer(mocktracer.New()) -// attach := make(map[string]string, 10) -// attach[constant.VERSION_KEY] = "1.0" -// attach[constant.GROUP_KEY] = "MyGroup" -// inv := invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach) -// -// // attachment doesn't contains any tracing key-value pair, -// ctx := rebuildCtx(inv) -// assert.NotNil(t, ctx) -// assert.Nil(t, ctx.Value(constant.TRACING_REMOTE_SPAN_CTX)) -// -// span, ctx := opentracing.StartSpanFromContext(ctx, "Test-Client") -// -// opentracing.GlobalTracer().Inject(span.Context(), opentracing.TextMap, -// opentracing.TextMapCarrier(inv.Attachments())) -// // rebuild the context success -// inv = invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach) -// ctx = rebuildCtx(inv) -// span.Finish() -// assert.NotNil(t, ctx) -// assert.NotNil(t, ctx.Value(constant.TRACING_REMOTE_SPAN_CTX)) -//} +import ( + "context" + "testing" + + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/mocktracer" + "github.com/stretchr/testify/assert" +) + +// test rebuild the ctx +func TestRebuildCtx(t *testing.T) { + opentracing.SetGlobalTracer(mocktracer.New()) + attach := make(map[string]string, 10) + attach[constant.VERSION_KEY] = "1.0" + attach[constant.GROUP_KEY] = "MyGroup" + inv := invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach) + + // attachment doesn't contains any tracing key-value pair, + ctx := rebuildCtx(inv) + assert.NotNil(t, ctx) + assert.Nil(t, ctx.Value(constant.TRACING_REMOTE_SPAN_CTX)) + + span, ctx := opentracing.StartSpanFromContext(ctx, "Test-Client") + + opentracing.GlobalTracer().Inject(span.Context(), opentracing.TextMap, + opentracing.TextMapCarrier(inv.Attachments())) + // rebuild the context success + inv = invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach) + ctx = rebuildCtx(inv) + span.Finish() + assert.NotNil(t, ctx) + assert.NotNil(t, ctx.Value(constant.TRACING_REMOTE_SPAN_CTX)) +} + +// rebuildCtx rebuild the context by attachment. +// Once we decided to transfer more context's key-value, we should change this. +// now we only support rebuild the tracing context +func rebuildCtx(inv *invocation.RPCInvocation) context.Context { + ctx := context.WithValue(context.Background(), "attachment", inv.Attachments()) + + // actually, if user do not use any opentracing framework, the err will not be nil. + spanCtx, err := opentracing.GlobalTracer().Extract(opentracing.TextMap, + opentracing.TextMapCarrier(inv.Attachments())) + if err == nil { + ctx = context.WithValue(ctx, constant.TRACING_REMOTE_SPAN_CTX, spanCtx) + } + return ctx +} diff --git a/remoting/getty/readwriter.go b/remoting/getty/readwriter.go index b59d9b82fb9f961da4be435cd717c857e1f79e5e..1aed516a3a9bca3f5f6ab82fe32fa6e981ee1e0b 100644 --- a/remoting/getty/readwriter.go +++ b/remoting/getty/readwriter.go @@ -18,18 +18,15 @@ package getty import ( - "github.com/apache/dubbo-go/remoting" "reflect" -) -import ( - "github.com/apache/dubbo-go-hessian2" + "github.com/apache/dubbo-go/remoting" + + hessian "github.com/apache/dubbo-go-hessian2" "github.com/dubbogo/getty" - perrors "github.com/pkg/errors" -) -import ( "github.com/apache/dubbo-go/common/logger" + perrors "github.com/pkg/errors" ) //////////////////////////////////////////// @@ -49,17 +46,16 @@ func NewRpcClientPackageHandler(client *Client) *RpcClientPackageHandler { func (p *RpcClientPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) { //pkg := &DubboPackage{} //p.client.ExchangeClient.GetPendingResponse(remoting.SequenceType()) - resp, length, err := (p.client.codec).DecodeResponse(data) + resp, length, err := (p.client.codec).Decode(data) //err := pkg.Unmarshal(buf, p.client) if err != nil { - originErr := perrors.Cause(err) - if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { + if err == hessian.ErrHeaderNotEnough || err == hessian.ErrBodyNotEnough { return nil, 0, nil } logger.Errorf("pkg.Unmarshal(ss:%+v, len(@data):%d) = error:%+v", ss, len(data), err) - return nil, length, perrors.WithStack(err) + return nil, length, err } //if pkg.Header.Type&hessian.PackageRequest == 0x00 { // pkg.Err = pkg.Body.(*hessian.Response).Exception @@ -103,18 +99,17 @@ func NewRpcServerPackageHandler(server *Server) *RpcServerPackageHandler { } func (p *RpcServerPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) { - req, length, err := (p.server.codec).DecodeRequest(data) + req, length, err := (p.server.codec).Decode(data) //resp,len, err := (*p.).DecodeResponse(buf) if err != nil { - originErr := perrors.Cause(err) - if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough { + if err == hessian.ErrHeaderNotEnough || err == hessian.ErrBodyNotEnough { return nil, 0, nil } logger.Errorf("pkg.Unmarshal(ss:%+v, len(@data):%d) = error:%+v", ss, len(data), err) - return nil, 0, perrors.WithStack(err) + return nil, 0, err } return req, length, err