diff --git a/common/constant/key.go b/common/constant/key.go
index 6e73183adbc38f8e6b6482f0b010fb493f5fac8a..06b37cf709bc4940f6763b72e877d3aab44b2109 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -22,27 +22,27 @@ const (
 )
 
 const (
-	GROUP_KEY              = "group"
-	VERSION_KEY            = "version"
-	INTERFACE_KEY          = "interface"
-	PATH_KEY               = "path"
-	SERVICE_KEY            = "service"
-	METHODS_KEY            = "methods"
-	TIMEOUT_KEY            = "timeout"
-	CATEGORY_KEY           = "category"
-	CHECK_KEY              = "check"
-	ENABLED_KEY            = "enabled"
-	SIDE_KEY               = "side"
-	OVERRIDE_PROVIDERS_KEY = "providerAddresses"
-	BEAN_NAME_KEY          = "bean.name"
-	GENERIC_KEY            = "generic"
-	CLASSIFIER_KEY         = "classifier"
-	TOKEN_KEY              = "token"
-	LOCAL_ADDR             = "local-addr"
-	REMOTE_ADDR            = "remote-addr"
-	DUBBO_KEY              = "dubbo"
-	RELEASE_KEY            = "release"
-	ANYHOST_KEY            = "anyhost"
+	GROUP_KEY                = "group"
+	VERSION_KEY              = "version"
+	INTERFACE_KEY            = "interface"
+	PATH_KEY                 = "path"
+	SERVICE_KEY              = "service"
+	METHODS_KEY              = "methods"
+	TIMEOUT_KEY              = "timeout"
+	CATEGORY_KEY             = "category"
+	CHECK_KEY                = "check"
+	ENABLED_KEY              = "enabled"
+	SIDE_KEY                 = "side"
+	OVERRIDE_PROVIDERS_KEY   = "providerAddresses"
+	BEAN_NAME_KEY            = "bean.name"
+	GENERIC_KEY              = "generic"
+	CLASSIFIER_KEY           = "classifier"
+	TOKEN_KEY                = "token"
+	LOCAL_ADDR               = "local-addr"
+	REMOTE_ADDR              = "remote-addr"
+	DEFAULT_REMOTING_TIMEOUT = 3000
+	RELEASE_KEY              = "release"
+	ANYHOST_KEY              = "anyhost"
 )
 
 const (
diff --git a/common/url.go b/common/url.go
index e58f652a865f7a9648c80a73c3c4773258cc246f..5a3e69f266ab509881b6fdafb21926732f68aa94 100644
--- a/common/url.go
+++ b/common/url.go
@@ -18,6 +18,7 @@
 package common
 
 import (
+	"bytes"
 	"encoding/base64"
 	"fmt"
 	"math"
@@ -320,12 +321,15 @@ func (c URL) Key() string {
 
 // ServiceKey gets a unique key of a service.
 func (c URL) ServiceKey() string {
-	intf := c.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/"))
+	return ServiceKey(c.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/")),
+		c.GetParam(constant.GROUP_KEY, ""), c.GetParam(constant.VERSION_KEY, ""))
+}
+
+func ServiceKey(intf string, group string, version string) string {
 	if intf == "" {
 		return ""
 	}
-	var buf strings.Builder
-	group := c.GetParam(constant.GROUP_KEY, "")
+	buf := &bytes.Buffer{}
 	if group != "" {
 		buf.WriteString(group)
 		buf.WriteString("/")
@@ -333,7 +337,6 @@ func (c URL) ServiceKey() string {
 
 	buf.WriteString(intf)
 
-	version := c.GetParam(constant.VERSION_KEY, "")
 	if version != "" && version != "0.0.0" {
 		buf.WriteString(":")
 		buf.WriteString(version)
diff --git a/config/application_config.go b/config/application_config.go
index 16e841792c7bffaa6f847d73c336c6a43431bc49..cc02da3debd77b1693e26ee8b522330f3c2f23c9 100644
--- a/config/application_config.go
+++ b/config/application_config.go
@@ -41,6 +41,16 @@ func (*ApplicationConfig) Prefix() string {
 	return constant.DUBBO + ".application."
 }
 
+// nolint
+func (c *ApplicationConfig) Id() string {
+	return ""
+}
+
+// SetId ...
+func (c *ApplicationConfig) SetId(id string) {
+
+}
+
 // UnmarshalYAML unmarshals the ApplicationConfig by @unmarshal function
 func (c *ApplicationConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	if err := defaults.Set(c); err != nil {
diff --git a/protocol/dubbo/client.go b/protocol/dubbo/client.go
deleted file mode 100644
index 0bd7aac90de4583cff7cc79c01134ff1b299a747..0000000000000000000000000000000000000000
--- a/protocol/dubbo/client.go
+++ /dev/null
@@ -1,70 +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"
-	"time"
-)
-
-import (
-	"gopkg.in/yaml.v2"
-)
-
-import (
-	"github.com/apache/dubbo-go/common/logger"
-	"github.com/apache/dubbo-go/config"
-	"github.com/apache/dubbo-go/protocol/dubbo/impl/remoting"
-)
-
-func init() {
-
-	// load clientconfig from consumer_config
-	// default use dubbo
-	consumerConfig := config.GetConsumerConfig()
-	if consumerConfig.ApplicationConfig == nil {
-		return
-	}
-	protocolConf := config.GetConsumerConfig().ProtocolConf
-	defaultClientConfig := remoting.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
-	}
-	remoting.SetClientConf(*clientConf)
-
-	rand.Seed(time.Now().UnixNano())
-}
diff --git a/protocol/dubbo/client_test.go b/protocol/dubbo/client_test.go
deleted file mode 100644
index 51e532e658da51d625430a04ae66ccf9935b4559..0000000000000000000000000000000000000000
--- a/protocol/dubbo/client_test.go
+++ /dev/null
@@ -1,301 +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"
-	"github.com/apache/dubbo-go/protocol/dubbo/impl/remoting"
-)
-
-func TestClient_CallOneway(t *testing.T) {
-	proto, url := InitTest(t)
-
-	c := &remoting.Client{
-		PendingResponses: new(sync.Map),
-		Conf:             *remoting.GetClientConf(),
-		Opts: remoting.Options{
-			ConnectTimeout: 3e9,
-			RequestTimeout: 6e9,
-		},
-	}
-	c.Pool = remoting.NewGettyRPCClientConnPool(c, remoting.GetClientConf().PoolSize, time.Duration(int(time.Second)*remoting.GetClientConf().PoolTTL))
-
-	//user := &User{}
-	err := c.CallOneway(remoting.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 := &remoting.Client{
-		PendingResponses: new(sync.Map),
-		Conf:             *remoting.GetClientConf(),
-		Opts: remoting.Options{
-			ConnectTimeout: 3e9,
-			RequestTimeout: 10e9,
-		},
-	}
-	c.Pool = remoting.NewGettyRPCClientConnPool(c, remoting.GetClientConf().PoolSize, time.Duration(int(time.Second)*remoting.GetClientConf().PoolTTL))
-
-	var (
-		user *User
-		err  error
-	)
-
-	user = &User{}
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetBigPkg", []interface{}{nil}, nil), remoting.NewResponse(user, nil))
-	assert.NoError(t, err)
-	assert.NotEqual(t, "", user.Id)
-	assert.NotEqual(t, "", user.Name)
-
-	user = &User{}
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, nil), remoting.NewResponse(user, nil))
-	assert.NoError(t, err)
-	assert.Equal(t, User{Id: "1", Name: "username"}, *user)
-
-	user = &User{}
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetUser0", []interface{}{"1", nil, "username"}, nil), remoting.NewResponse(user, nil))
-	assert.NoError(t, err)
-	assert.Equal(t, User{Id: "1", Name: "username"}, *user)
-
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetUser1", []interface{}{}, nil), remoting.NewResponse(user, nil))
-	assert.NoError(t, err)
-
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetUser2", []interface{}{}, nil), remoting.NewResponse(user, nil))
-	assert.EqualError(t, err, "error")
-
-	user2 := []interface{}{}
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetUser3", []interface{}{}, nil), remoting.NewResponse(&user2, nil))
-	assert.NoError(t, err)
-	assert.Equal(t, &User{Id: "1", Name: "username"}, user2[0])
-
-	user2 = []interface{}{}
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetUser4", []interface{}{[]interface{}{"1", "username"}}, nil), remoting.NewResponse(&user2, nil))
-	assert.NoError(t, err)
-	assert.Equal(t, &User{Id: "1", Name: "username"}, user2[0])
-
-	user3 := map[interface{}]interface{}{}
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetUser5", []interface{}{map[interface{}]interface{}{"id": "1", "name": "username"}}, nil), remoting.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(remoting.NewRequest("127.0.0.1:20000", url, "GetUser6", []interface{}{0}, nil), remoting.NewResponse(user, nil))
-	assert.NoError(t, err)
-	assert.Equal(t, User{Id: "", Name: ""}, *user)
-
-	user = &User{}
-	err = c.Call(remoting.NewRequest("127.0.0.1:20000", url, "GetUser6", []interface{}{1}, nil), remoting.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 := &remoting.Client{
-		PendingResponses: new(sync.Map),
-		Conf:             *remoting.GetClientConf(),
-		Opts: remoting.Options{
-			ConnectTimeout: 3e9,
-			RequestTimeout: 6e9,
-		},
-	}
-	c.Pool = remoting.NewGettyRPCClientConnPool(c, remoting.GetClientConf().PoolSize, time.Duration(int(time.Second)*remoting.GetClientConf().PoolTTL))
-
-	user := &User{}
-	lock := sync.Mutex{}
-	lock.Lock()
-	err := c.AsyncCall(remoting.NewRequest("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, nil), func(response common.CallbackResponse) {
-		r := response.(remoting.AsyncCallbackResponse)
-		assert.Equal(t, User{Id: "1", Name: "username"}, *r.Reply.(*remoting.Response).Reply.(*User))
-		lock.Unlock()
-	}, remoting.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("com.ikurento.user.UserProvider", "dubbo", &UserProvider{})
-	assert.NoError(t, err)
-	assert.Equal(t, "GetBigPkg,GetUser,GetUser0,GetUser1,GetUser2,GetUser3,GetUser4,GetUser5,GetUser6", methods)
-
-	// config
-	remoting.SetClientConf(remoting.ClientConfig{
-		ConnectionNum:   2,
-		HeartbeatPeriod: "5s",
-		SessionTimeout:  "20s",
-		PoolTTL:         600,
-		PoolSize:        64,
-		GettySessionParam: remoting.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, remoting.GetClientConf().CheckValidity())
-	remoting.SetServerConfig(remoting.ServerConfig{
-		SessionNumber:  700,
-		SessionTimeout: "20s",
-		GettySessionParam: remoting.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, remoting.GetServerConfig().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&timestamp=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/dubbo_codec.go b/protocol/dubbo/dubbo_codec.go
new file mode 100644
index 0000000000000000000000000000000000000000..e575c797b3ae2096dd015ccd1c7f7dcb9df6d368
--- /dev/null
+++ b/protocol/dubbo/dubbo_codec.go
@@ -0,0 +1,366 @@
+/*
+ * 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"
+	"github.com/apache/dubbo-go/protocol/dubbo/impl"
+	"strconv"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	perrors "github.com/pkg/errors"
+)
+
+import (
+	"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"
+)
+
+//SerialID serial ID
+type SerialID byte
+
+const (
+	// S_Dubbo dubbo serial id
+	S_Dubbo SerialID = 2
+)
+
+func init() {
+	codec := &DubboCodec{}
+	// this is for registry dubboCodec of dubbo protocol
+	remoting.RegistryCodec("dubbo", codec)
+}
+
+// DubboPackage is for hessian encode/decode. If we refactor hessian, it will also be refactored.
+//type DubboPackage struct {
+//	Header  hessian.DubboHeader
+//	Service hessian.Service
+//	Body    interface{}
+//	Err     error
+//}
+
+// String of DubboPackage
+//func (p DubboPackage) String() string {
+//	return fmt.Sprintf("DubboPackage: Header-%v, Path-%v, Body-%v", p.Header, p.Service, p.Body)
+//}
+
+//  nolint
+//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
+//}
+
+// nolint
+//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)
+//}
+
+// DubboCodec. It is implements remoting.Codec
+type DubboCodec struct {
+}
+
+// encode request for transport
+func (c *DubboCodec) EncodeRequest(request *remoting.Request) (*bytes.Buffer, error) {
+	if request.Event {
+		return c.encodeHeartbeartReqeust(request)
+	}
+
+	invoc, ok := request.Data.(*protocol.Invocation)
+	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
+
+	svc := impl.Service{}
+	svc.Path = invocation.AttachmentsByKey(constant.PATH_KEY, "")
+	svc.Interface = invocation.AttachmentsByKey(constant.INTERFACE_KEY, "")
+	svc.Version = invocation.AttachmentsByKey(constant.VERSION_KEY, "")
+	svc.Group = invocation.AttachmentsByKey(constant.GROUP_KEY, "")
+	svc.Method = invocation.MethodName()
+	timeout, err := strconv.Atoi(invocation.AttachmentsByKey(constant.TIMEOUT_KEY, strconv.Itoa(constant.DEFAULT_REMOTING_TIMEOUT)))
+	if err != nil {
+		// it will be wrapped in readwrite.Write .
+		return nil, perrors.WithStack(err)
+	}
+	svc.Timeout = time.Duration(timeout)
+
+	header := impl.DubboHeader{}
+	serialization := invocation.AttachmentsByKey(constant.SERIALIZATION_KEY, constant.HESSIAN2_SERIALIZATION)
+	if serialization == constant.HESSIAN2_SERIALIZATION {
+		header.SerialID = constant.S_Hessian2
+	} else if serialization == constant.PROTOBUF_SERIALIZATION {
+		header.SerialID = constant.S_Proto
+	}
+	header.ID = request.ID
+	if request.TwoWay {
+		header.Type = impl.PackageRequest_TwoWay
+	} else {
+		header.Type = impl.PackageRequest
+	}
+
+	pkg := &impl.DubboPackage{
+		Header:  header,
+		Service: svc,
+		Body:    impl.NewRequestPayload(invocation.Arguments(), invocation.Attachments()),
+		Err:     nil,
+		Codec:   impl.NewDubboCodec(nil),
+	}
+
+	if err := impl.LoadSerializer(pkg); err != nil {
+		return nil, perrors.WithStack(err)
+	}
+
+	return pkg.Marshal()
+}
+
+// encode heartbeart request
+func (c *DubboCodec) encodeHeartbeartReqeust(request *remoting.Request) (*bytes.Buffer, error) {
+	header := impl.DubboHeader{
+		Type:     impl.PackageHeartbeat,
+		SerialID: constant.S_Hessian2,
+		ID:       request.ID,
+	}
+
+	pkg := &impl.DubboPackage{
+		Header:  header,
+		Service: impl.Service{},
+		Body:    impl.NewRequestPayload([]interface{}{}, nil),
+		Err:     nil,
+		Codec:   impl.NewDubboCodec(nil),
+	}
+
+	if err := impl.LoadSerializer(pkg); err != nil {
+		return nil, err
+	}
+	return pkg.Marshal()
+}
+
+// encode response
+func (c *DubboCodec) EncodeResponse(response *remoting.Response) (*bytes.Buffer, error) {
+	var ptype = impl.PackageResponse
+	if response.IsHeartbeat() {
+		ptype = impl.PackageHeartbeat
+	}
+	resp := &impl.DubboPackage{
+		Header: impl.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,
+		}
+	}
+
+	codec := impl.NewDubboCodec(nil)
+
+	pkg, err := codec.Encode(*resp)
+	if err != nil {
+		return nil, perrors.WithStack(err)
+	}
+
+	return bytes.NewBuffer(pkg), nil
+}
+
+// Decode data, including request and response.
+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, perrors.WithStack(err)
+		}
+		return remoting.DecodeResult{IsRequest: true, Result: req}, len, perrors.WithStack(err)
+	} else {
+		resp, len, err := c.decodeResponse(data)
+		if err != nil {
+			return remoting.DecodeResult{}, len, perrors.WithStack(err)
+		}
+		return remoting.DecodeResult{IsRequest: false, Result: resp}, len, perrors.WithStack(err)
+	}
+}
+
+func (c *DubboCodec) isRequest(data []byte) bool {
+	if data[2]&byte(0x80) == 0x00 {
+		return false
+	}
+	return true
+}
+
+// decode request
+func (c *DubboCodec) decodeRequest(data []byte) (*remoting.Request, int, error) {
+	var request *remoting.Request = nil
+	buf := bytes.NewBuffer(data)
+	pkg := impl.NewDubboPackage(buf)
+	pkg.SetBody(make([]interface{}, 7))
+	err := pkg.Unmarshal()
+	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&impl.PackageRequest_TwoWay != 0x00,
+		Event:    pkg.Header.Type&impl.PackageHeartbeat != 0x00,
+	}
+	if (pkg.Header.Type & impl.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 {
+				//ignore argTypes
+			}
+			if req[5] != nil {
+				args = req[5].([]interface{})
+			}
+			if req[6] != nil {
+				attachments = req[6].(map[string]string)
+			}
+			invoc := invocation.NewRPCInvocationWithOptions(invocation.WithAttachments(attachments),
+				invocation.WithArguments(args), invocation.WithMethodName(methodName))
+			request.Data = invoc
+		}
+	}
+	return request, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil
+}
+
+// decode response
+func (c *DubboCodec) decodeResponse(data []byte) (*remoting.Response, int, error) {
+	buf := bytes.NewBuffer(data)
+	pkg := impl.NewDubboPackage(buf)
+	response := &remoting.Response{}
+	err := pkg.Unmarshal()
+	if err != nil {
+		originErr := perrors.Cause(err)
+		// if the data is very big, so the receive need much times.
+		if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough {
+			return nil, 0, originErr
+		}
+		logger.Errorf("pkg.Unmarshal(len(@data):%d) = error:%+v", buf.Len(), err)
+
+		return nil, 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 & impl.PackageHeartbeat) != 0,
+	}
+	var error error
+	if pkg.Header.Type&impl.PackageHeartbeat != 0x00 {
+		if pkg.Header.Type&impl.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&impl.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
+	}
+
+	return response, hessian.HEADER_LENGTH + pkg.Header.BodyLen, nil
+}
diff --git a/protocol/dubbo/dubbo_invoker.go b/protocol/dubbo/dubbo_invoker.go
index 1907c38a3e7bd6be7d5f332372b6efe48cdb672f..e51cc5fccfe43a97de582521f7e7b8116600d39e 100644
--- a/protocol/dubbo/dubbo_invoker.go
+++ b/protocol/dubbo/dubbo_invoker.go
@@ -20,6 +20,7 @@ package dubbo
 import (
 	"context"
 	"strconv"
+	"strings"
 	"sync"
 	"sync/atomic"
 	"time"
@@ -34,9 +35,10 @@ 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"
 	"github.com/apache/dubbo-go/protocol"
-	"github.com/apache/dubbo-go/protocol/dubbo/impl/remoting"
 	invocation_impl "github.com/apache/dubbo-go/protocol/invocation"
+	"github.com/apache/dubbo-go/remoting"
 )
 
 var (
@@ -47,24 +49,35 @@ var (
 )
 
 var (
-	attachmentKey = []string{constant.INTERFACE_KEY, constant.GROUP_KEY, constant.TOKEN_KEY, constant.TIMEOUT_KEY}
+	attachmentKey = []string{constant.INTERFACE_KEY, constant.GROUP_KEY, constant.TOKEN_KEY, constant.TIMEOUT_KEY,
+		constant.VERSION_KEY}
 )
 
-// DubboInvoker is dubbo client invoker.
+// DubboInvoker is implement of protocol.Invoker. A dubboInvoker refer to one service and ip.
 type DubboInvoker struct {
 	protocol.BaseInvoker
-	client   *remoting.Client
+	// the exchange layer, it is focus on network communication.
+	client   *remoting.ExchangeClient
 	quitOnce sync.Once
+	// timeout for service(interface) level.
+	timeout time.Duration
 	// Used to record the number of requests. -1 represent this DubboInvoker is destroyed
 	reqNum int64
 }
 
-// NewDubboInvoker ...
-func NewDubboInvoker(url common.URL, client *remoting.Client) *DubboInvoker {
+// NewDubboInvoker constructor
+func NewDubboInvoker(url common.URL, client *remoting.ExchangeClient) *DubboInvoker {
+	requestTimeout := config.GetConsumerConfig().RequestTimeout
+
+	requestTimeoutStr := url.GetParam(constant.TIMEOUT_KEY, config.GetConsumerConfig().Request_Timeout)
+	if t, err := time.ParseDuration(requestTimeoutStr); err == nil {
+		requestTimeout = t
+	}
 	return &DubboInvoker{
 		BaseInvoker: *protocol.NewBaseInvoker(url),
 		client:      client,
 		reqNum:      0,
+		timeout:     requestTimeout,
 	}
 }
 
@@ -85,6 +98,8 @@ func (di *DubboInvoker) Invoke(ctx context.Context, invocation protocol.Invocati
 	defer atomic.AddInt64(&(di.reqNum), -1)
 
 	inv := invocation.(*invocation_impl.RPCInvocation)
+	// init param
+	inv.SetAttachments(constant.PATH_KEY, di.GetUrl().GetParam(constant.INTERFACE_KEY, ""))
 	for _, k := range attachmentKey {
 		if v := di.GetUrl().GetParam(k, ""); len(v) > 0 {
 			inv.SetAttachments(k, v)
@@ -105,29 +120,47 @@ func (di *DubboInvoker) Invoke(ctx context.Context, invocation protocol.Invocati
 		logger.Errorf("ParseBool - error: %v", err)
 		async = false
 	}
-	response := remoting.NewResponse(inv.Reply(), nil)
+	//response := NewResponse(inv.Reply(), nil)
+	rest := &protocol.RPCResult{}
+	timeout := di.getTimeout(inv)
 	if async {
 		if callBack, ok := inv.CallBack().(func(response common.CallbackResponse)); ok {
-			result.Err = di.client.AsyncCall(remoting.NewRequest(url.Location, url, inv.MethodName(), inv.Arguments(), inv.Attachments()), callBack, response)
+			//result.Err = di.client.AsyncCall(NewRequest(url.Location, url, inv.MethodName(), inv.Arguments(), inv.Attachments()), callBack, response)
+			result.Err = di.client.AsyncRequest(&invocation, url, timeout, callBack, rest)
 		} else {
-			result.Err = di.client.CallOneway(remoting.NewRequest(url.Location, url, inv.MethodName(), inv.Arguments(), inv.Attachments()))
+			result.Err = di.client.Send(&invocation, url, timeout)
 		}
 	} else {
 		if inv.Reply() == nil {
 			result.Err = ErrNoReply
 		} else {
-			result.Err = di.client.Call(remoting.NewRequest(url.Location, url, inv.MethodName(), inv.Arguments(), inv.Attachments()), response)
+			result.Err = di.client.Request(&invocation, url, timeout, rest)
 		}
 	}
 	if result.Err == nil {
 		result.Rest = inv.Reply()
-		result.Attrs = response.Atta
+		result.Attrs = rest.Attrs
 	}
 	logger.Debugf("result.Err: %v, result.Rest: %v", result.Err, result.Rest)
 
 	return &result
 }
 
+// get timeout including methodConfig
+func (di *DubboInvoker) getTimeout(invocation *invocation_impl.RPCInvocation) time.Duration {
+	var timeout = di.GetUrl().GetParam(strings.Join([]string{constant.METHOD_KEYS, invocation.MethodName(), constant.TIMEOUT_KEY}, "."), "")
+	if len(timeout) != 0 {
+		if t, err := time.ParseDuration(timeout); err == nil {
+			// config timeout into attachment
+			invocation.SetAttachments(constant.TIMEOUT_KEY, strconv.Itoa(int(t.Milliseconds())))
+			return t
+		}
+	}
+	// set timeout into invocation at method level
+	invocation.SetAttachments(constant.TIMEOUT_KEY, strconv.Itoa(int(di.timeout.Milliseconds())))
+	return di.timeout
+}
+
 // Destroy destroy dubbo client invoker.
 func (di *DubboInvoker) Destroy() {
 	di.quitOnce.Do(func() {
diff --git a/protocol/dubbo/dubbo_invoker_test.go b/protocol/dubbo/dubbo_invoker_test.go
index e96e8592207a500f876490b5af1fbb2afcc43a37..9585461434a899ee3e4a7ca689a77b3a7d1b2b27 100644
--- a/protocol/dubbo/dubbo_invoker_test.go
+++ b/protocol/dubbo/dubbo_invoker_test.go
@@ -18,6 +18,7 @@
 package dubbo
 
 import (
+	"bytes"
 	"context"
 	"sync"
 	"testing"
@@ -25,29 +26,26 @@ import (
 )
 
 import (
+	hessian "github.com/apache/dubbo-go-hessian2"
 	"github.com/opentracing/opentracing-go"
+	perrors "github.com/pkg/errors"
 	"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/dubbo/impl/remoting"
+	"github.com/apache/dubbo-go/common/proxy/proxy_factory"
+	"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"
 )
 
 func TestDubboInvoker_Invoke(t *testing.T) {
 	proto, url := InitTest(t)
 
-	c := &remoting.Client{
-		PendingResponses: new(sync.Map),
-		Conf:             *remoting.GetClientConf(),
-		Opts: remoting.Options{
-			ConnectTimeout: 3 * time.Second,
-			RequestTimeout: 6 * time.Second,
-		},
-	}
-	c.Pool = remoting.NewGettyRPCClientConnPool(c, remoting.GetClientConf().PoolSize, time.Duration(int(time.Second)*remoting.GetClientConf().PoolTTL))
+	c := getExchangeClient(url)
 
 	invoker := NewDubboInvoker(url, c)
 	user := &User{}
@@ -59,7 +57,6 @@ 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
 
 	// CallOneway
 	inv.SetAttachments(constant.ASYNC_KEY, "true")
@@ -71,7 +68,9 @@ func TestDubboInvoker_Invoke(t *testing.T) {
 	lock.Lock()
 	inv.SetCallBack(func(response common.CallbackResponse) {
 		r := response.(remoting.AsyncCallbackResponse)
-		assert.Equal(t, User{Id: "1", Name: "username"}, *r.Reply.(*remoting.Response).Reply.(*User))
+		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)
@@ -93,3 +92,143 @@ 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&timestamp=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++ {
+		// use chinese for test
+		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 cc67569867241256c4c1bc66126f74ac3f6173ad..915ee74bdea6745fe7c0ac731ef4e1f91b51d076 100644
--- a/protocol/dubbo/dubbo_protocol.go
+++ b/protocol/dubbo/dubbo_protocol.go
@@ -18,10 +18,16 @@
 package dubbo
 
 import (
+	"context"
+	"fmt"
 	"sync"
 	"time"
 )
 
+import (
+	"github.com/opentracing/opentracing-go"
+)
+
 import (
 	"github.com/apache/dubbo-go/common"
 	"github.com/apache/dubbo-go/common/constant"
@@ -29,7 +35,9 @@ import (
 	"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/dubbo/impl/remoting"
+	"github.com/apache/dubbo-go/protocol/invocation"
+	"github.com/apache/dubbo-go/remoting"
+	"github.com/apache/dubbo-go/remoting/getty"
 )
 
 const (
@@ -37,6 +45,13 @@ const (
 	DUBBO = "dubbo"
 )
 
+var (
+	// Make the connection can be shared.
+	// It will create one connection for one address (ip+port)
+	exchangeClientMap *sync.Map = new(sync.Map)
+	exchangeLock      *sync.Map = new(sync.Map)
+)
+
 func init() {
 	extension.SetProtocol(DUBBO, GetProtocol)
 }
@@ -45,22 +60,24 @@ var (
 	dubboProtocol *DubboProtocol
 )
 
-// DubboProtocol is a dubbo protocol implement.
+// It support dubbo protocol. It implements Protocol interface for dubbo protocol.
 type DubboProtocol struct {
 	protocol.BaseProtocol
-	serverMap  map[string]*remoting.Server
+	// It is store relationship about serviceKey(group/interface:version) and ExchangeServer
+	// The ExchangeServer is introduced to replace of Server. Because Server is depend on getty directly.
+	serverMap  map[string]*remoting.ExchangeServer
 	serverLock sync.Mutex
 }
 
-// NewDubboProtocol create a dubbo protocol.
+// nolint
 func NewDubboProtocol() *DubboProtocol {
 	return &DubboProtocol{
 		BaseProtocol: protocol.NewBaseProtocol(),
-		serverMap:    make(map[string]*remoting.Server),
+		serverMap:    make(map[string]*remoting.ExchangeServer),
 	}
 }
 
-// Export export dubbo service.
+// nolint
 func (dp *DubboProtocol) Export(invoker protocol.Invoker) protocol.Exporter {
 	url := invoker.GetUrl()
 	serviceKey := url.ServiceKey()
@@ -74,18 +91,12 @@ func (dp *DubboProtocol) Export(invoker protocol.Invoker) protocol.Exporter {
 
 // Refer create dubbo service reference.
 func (dp *DubboProtocol) Refer(url common.URL) protocol.Invoker {
-	//default requestTimeout
-	var requestTimeout = config.GetConsumerConfig().RequestTimeout
-
-	requestTimeoutStr := url.GetParam(constant.TIMEOUT_KEY, config.GetConsumerConfig().Request_Timeout)
-	if t, err := time.ParseDuration(requestTimeoutStr); err == nil {
-		requestTimeout = t
+	exchangeClient := getExchangeClient(url)
+	if exchangeClient == nil {
+		logger.Warnf("can't dial the server: %+v", url.Location)
+		return nil
 	}
-
-	invoker := NewDubboInvoker(url, remoting.NewClient(remoting.Options{
-		ConnectTimeout: config.GetConsumerConfig().ConnectTimeout,
-		RequestTimeout: requestTimeout,
-	}))
+	invoker := NewDubboInvoker(url, exchangeClient)
 	dp.SetInvokers(invoker)
 	logger.Infof("Refer service: %s", url.String())
 	return invoker
@@ -115,9 +126,12 @@ func (dp *DubboProtocol) openServer(url common.URL) {
 		dp.serverLock.Lock()
 		_, ok = dp.serverMap[url.Location]
 		if !ok {
-			srv := remoting.NewServer(NewStubHandler())
+			handler := func(invocation *invocation.RPCInvocation) protocol.RPCResult {
+				return doHandleRequest(invocation)
+			}
+			srv := remoting.NewExchangeServer(url, getty.NewServer(url, handler))
 			dp.serverMap[url.Location] = srv
-			srv.Start(url)
+			srv.Start()
 		}
 		dp.serverLock.Unlock()
 	}
@@ -130,3 +144,100 @@ func GetProtocol() protocol.Protocol {
 	}
 	return dubboProtocol
 }
+
+func doHandleRequest(rpcInvocation *invocation.RPCInvocation) protocol.RPCResult {
+	exporter, _ := dubboProtocol.ExporterMap().Load(rpcInvocation.ServiceKey())
+	result := protocol.RPCResult{}
+	if exporter == nil {
+		err := fmt.Errorf("don't have this exporter, key: %s", rpcInvocation.ServiceKey())
+		logger.Errorf(err.Error())
+		result.Err = err
+		//reply(session, p, hessian.PackageResponse)
+		return result
+	}
+	invoker := exporter.(protocol.Exporter).GetInvoker()
+	if invoker != nil {
+		// FIXME
+		ctx := rebuildCtx(rpcInvocation)
+
+		invokeResult := invoker.Invoke(ctx, rpcInvocation)
+		if err := invokeResult.Error(); err != nil {
+			result.Err = invokeResult.Error()
+			//p.Header.ResponseStatus = hessian.Response_OK
+			//p.Body = hessian.NewResponse(nil, err, result.Attachments())
+		} else {
+			result.Rest = invokeResult.Result()
+			//p.Header.ResponseStatus = hessian.Response_OK
+			//p.Body = hessian.NewResponse(res, nil, result.Attachments())
+		}
+	} else {
+		result.Err = fmt.Errorf("don't have the invoker, key: %s", rpcInvocation.ServiceKey())
+	}
+	return result
+}
+
+func getExchangeClient(url common.URL) *remoting.ExchangeClient {
+	clientTmp, ok := exchangeClientMap.Load(url.Location)
+	if !ok {
+		var exchangeClientTmp *remoting.ExchangeClient
+		func() {
+			// lock for NewExchangeClient and store into map.
+			_, loaded := exchangeLock.LoadOrStore(url.Location, 0x00)
+			// unlock
+			defer exchangeLock.Delete(url.Location)
+			if loaded {
+				// retry for 5 times.
+				for i := 0; i < 5; i++ {
+					if clientTmp, ok = exchangeClientMap.Load(url.Location); ok {
+						break
+					} else {
+						// if cannot get, sleep a while.
+						time.Sleep(time.Duration(i*100) * time.Millisecond)
+					}
+				}
+				return
+			}
+			// new ExchangeClient
+			exchangeClientTmp = remoting.NewExchangeClient(url, getty.NewClient(getty.Options{
+				ConnectTimeout: config.GetConsumerConfig().ConnectTimeout,
+			}), config.GetConsumerConfig().ConnectTimeout, false)
+			// input store
+			if exchangeClientTmp != nil {
+				exchangeClientMap.Store(url.Location, exchangeClientTmp)
+			}
+		}()
+		if exchangeClientTmp != nil {
+			return exchangeClientTmp
+		}
+	}
+	// cannot dial the server
+	if clientTmp == nil {
+		return nil
+	}
+	exchangeClient, ok := clientTmp.(*remoting.ExchangeClient)
+	if !ok {
+		exchangeClientTmp := remoting.NewExchangeClient(url, getty.NewClient(getty.Options{
+			ConnectTimeout: config.GetConsumerConfig().ConnectTimeout,
+		}), config.GetConsumerConfig().ConnectTimeout, false)
+		if exchangeClientTmp != nil {
+			exchangeClientMap.Store(url.Location, exchangeClientTmp)
+		}
+		return exchangeClientTmp
+	}
+	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 1915a072f0e4ccb874e2a366dba72d70da2f7a7c..07b890f1345eaf994b6d7ba90642a116526355c4 100644
--- a/protocol/dubbo/dubbo_protocol_test.go
+++ b/protocol/dubbo/dubbo_protocol_test.go
@@ -22,22 +22,62 @@ import (
 )
 
 import (
-	"github.com/apache/dubbo-go/common"
-	"github.com/apache/dubbo-go/common/constant"
-	"github.com/apache/dubbo-go/protocol"
-	"github.com/apache/dubbo-go/protocol/dubbo/impl/remoting"
+	"github.com/stretchr/testify/assert"
 )
 
 import (
-	"github.com/stretchr/testify/assert"
+	"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"
 )
 
+func init() {
+	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",
+		}})
+	getty.SetClientConf(getty.ClientConfig{
+		ConnectionNum:   1,
+		HeartbeatPeriod: "3s",
+		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",
+		},
+	})
+}
 func TestDubboProtocol_Export(t *testing.T) {
-	srvCfg := remoting.GetDefaultServerConfig()
-	remoting.SetServerConfig(srvCfg)
+	srvCfg := getty.GetDefaultServerConfig()
+	getty.SetServerConfig(srvCfg)
 	// Export
 	proto := GetProtocol()
-	url, err := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
+	url, err := common.NewURL("dubbo://127.0.0.1:20094/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&" +
@@ -50,7 +90,7 @@ func TestDubboProtocol_Export(t *testing.T) {
 	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&"+
+	url2, err := common.NewURL("dubbo://127.0.0.1:20095/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&"+
@@ -76,12 +116,26 @@ func TestDubboProtocol_Export(t *testing.T) {
 	assert.False(t, ok)
 }
 
+func TestDubboProtocol_Refer_No_connect(t *testing.T) {
+	// Refer
+	proto := GetProtocol()
+	url, err := common.NewURL("dubbo://127.0.0.1:20096/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&timestamp=1556509797245")
+	assert.NoError(t, err)
+	invoker := proto.Refer(url)
+	assert.Nil(t, invoker)
+}
+
 func TestDubboProtocol_Refer(t *testing.T) {
-	cliCfg := remoting.GetDefaultClientConfig()
-	remoting.SetClientConf(cliCfg)
+	cliCfg := getty.GetDefaultClientConfig()
+	getty.SetClientConf(cliCfg)
 	// Refer
 	proto := GetProtocol()
-	url, err := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
+
+	url, err := common.NewURL("dubbo://127.0.0.1:20091/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&" +
diff --git a/protocol/dubbo/impl/codec_test.go b/protocol/dubbo/impl/codec_test.go
index c93f307aa34bf159f42b33f872b3daa5dcacc5db..92f2f2e9c08324b91e220cd4b7621fd2c23a98e2 100644
--- a/protocol/dubbo/impl/codec_test.go
+++ b/protocol/dubbo/impl/codec_test.go
@@ -128,7 +128,7 @@ func TestDubboPackage_Protobuf_Serialization_Request(t *testing.T) {
 	// protobuf rpc just has exact one parameter
 	assert.Equal(t, len(req), 1)
 	argsBytes, ok := req[0].([]byte)
-	assert.Equal(t, ok, true)
+	assert.Equal(t, true, ok)
 	sv := pb.StringValue{}
 	buf := proto.NewBuffer(argsBytes)
 	err = buf.Unmarshal(&sv)
diff --git a/protocol/dubbo/impl/const.go b/protocol/dubbo/impl/const.go
index 06e73fab1d64354a450946542c32f7d6d4b150d7..c2f4006174a5690512a9329eaa8f541b2014197c 100644
--- a/protocol/dubbo/impl/const.go
+++ b/protocol/dubbo/impl/const.go
@@ -1,12 +1,3 @@
-package impl
-
-import (
-	"reflect"
-	"regexp"
-
-	"github.com/pkg/errors"
-)
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -24,6 +15,15 @@ import (
  * limitations under the License.
  */
 
+package impl
+
+import (
+	"reflect"
+	"regexp"
+
+	"github.com/pkg/errors"
+)
+
 const (
 	DUBBO = "dubbo"
 )
diff --git a/protocol/dubbo/impl/proto.go b/protocol/dubbo/impl/proto.go
index ea1c55da96fb71fb6c69f801ba86806187b14f8f..2622620b397b6328a540391134631cc607dd945b 100644
--- a/protocol/dubbo/impl/proto.go
+++ b/protocol/dubbo/impl/proto.go
@@ -21,6 +21,7 @@ import (
 	"bytes"
 	"encoding/binary"
 	"fmt"
+	"github.com/apache/dubbo-go/common/logger"
 	"io"
 	"reflect"
 	"strconv"
@@ -157,9 +158,11 @@ func unmarshalRequestProto(data []byte, pkg *DubboPackage) error {
 		return err
 	}
 	arg := getRegisterMessage(argsType)
-	err := proto.Unmarshal(argBytes, arg.Interface().(JavaProto))
-	if err != nil {
-		panic(err)
+	if !arg.IsZero() {
+		err := proto.Unmarshal(argBytes, arg.Interface().(JavaProto))
+		if err != nil {
+			panic(err)
+		}
 	}
 
 	m := &pb.Map{}
@@ -432,7 +435,8 @@ func getRegisterMessage(sig string) reflect.Value {
 
 	t, ok := register.registry[sig]
 	if !ok {
-		panic(fmt.Sprintf("registry dose not have for svc: %v", sig))
+		logger.Error(fmt.Sprintf("registry dose not have for svc: %v", sig))
+		return NilValue
 	}
 	return reflect.New(t)
 }
diff --git a/protocol/dubbo/impl/remoting/client_impl.go b/protocol/dubbo/impl/remoting/client_impl.go
deleted file mode 100644
index e5f7c7138b94737f9266c64082b8300f3cfdfdeb..0000000000000000000000000000000000000000
--- a/protocol/dubbo/impl/remoting/client_impl.go
+++ /dev/null
@@ -1,391 +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 remoting
-
-import (
-	"math/rand"
-	"strings"
-	"sync"
-	"time"
-)
-
-import (
-	"github.com/dubbogo/getty"
-	gxsync "github.com/dubbogo/gost/sync"
-	perrors "github.com/pkg/errors"
-	"go.uber.org/atomic"
-)
-
-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/dubbo/impl"
-)
-
-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")
-)
-
-var (
-	clientConf   *ClientConfig
-	clientGrpool *gxsync.TaskPool
-)
-
-// SetClientConf set dubbo client config.
-func SetClientConf(c ClientConfig) {
-	clientConf = &c
-	err := clientConf.CheckValidity()
-	if err != nil {
-		logger.Warnf("[ClientConfig CheckValidity] error: %v", err)
-		return
-	}
-	setClientGrpool()
-}
-
-// GetClientConf get dubbo client config.
-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 is option for create dubbo client
-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 is dubbo protocol client.
-type Client struct {
-	Opts     Options
-	Conf     ClientConfig
-	Pool     *gettyRPCClientPool
-	Sequence atomic.Uint64
-
-	PendingResponses *sync.Map
-	codec            impl.DubboCodec
-}
-
-// NewClient create a new Client.
-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,
-		codec:            impl.DubboCodec{},
-	}
-	c.Sequence.Store(initSequence)
-	c.Pool = NewGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL))
-
-	return c
-}
-
-// Request is dubbo protocol request.
-type Request struct {
-	addr   string
-	svcUrl common.URL
-	method string
-	args   interface{}
-	atta   map[string]string
-}
-
-// NewRequest create a new Request.
-func NewRequest(addr string, svcUrl common.URL, method string, args interface{}, atta map[string]string) *Request {
-	// NOTE: compatible with old versions
-	if svcUrl.GetParam(constant.SERIALIZATION_KEY, "") == "" {
-		svcUrl.SetParam(constant.SERIALIZATION_KEY, constant.DEFAULT_SERIALIZATION)
-	}
-	return &Request{
-		addr:   addr,
-		svcUrl: svcUrl,
-		method: method,
-		args:   args,
-		atta:   atta,
-	}
-}
-
-// Response is dubbo protocol response.
-type Response struct {
-	Reply interface{}
-	Atta  map[string]string
-}
-
-// NewResponse  create a new Response.
-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(impl.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 := impl.CT_TwoWay
-	if response.Reply == nil {
-		ct = impl.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(impl.CT_TwoWay, request, response, callback))
-}
-
-func (c *Client) call(ct impl.CallType, request *Request, response *Response, callback common.AsyncCallback) error {
-	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()
-	}()
-
-	var rsp *PendingResponse
-	svc := impl.Service{}
-	header := impl.DubboHeader{}
-	svc.Path = strings.TrimPrefix(request.svcUrl.Path, "/")
-	svc.Interface = request.svcUrl.GetParam(constant.INTERFACE_KEY, "")
-	svc.Version = request.svcUrl.GetParam(constant.VERSION_KEY, "")
-	svc.Group = request.svcUrl.GetParam(constant.GROUP_KEY, "")
-	svc.Method = request.method
-	svc.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 {
-			svc.Timeout = t
-		}
-	}
-	p := NewClientRequestPackage(header, svc)
-
-	serialization := request.svcUrl.GetParam(constant.SERIALIZATION_KEY, c.Conf.Serialization)
-	if serialization == constant.HESSIAN2_SERIALIZATION {
-		p.Header.SerialID = constant.S_Hessian2
-	} else if serialization == constant.PROTOBUF_SERIALIZATION {
-		p.Header.SerialID = constant.S_Proto
-	}
-	p.SetBody(impl.NewRequestPayload(request.args, request.atta))
-
-	if err := impl.LoadSerializer(p); err != nil {
-		return err
-	}
-
-	if ct != impl.CT_OneWay {
-		p.Header.Type = impl.PackageRequest_TwoWay
-		rsp = NewPendingResponse()
-		rsp.response = response
-		rsp.callback = callback
-	} else {
-		p.Header.Type = impl.PackageRequest
-	}
-	if err = c.transfer(session, p, rsp); err != nil {
-		return perrors.WithStack(err)
-	}
-
-	if ct == impl.CT_OneWay || callback != nil {
-		return nil
-	}
-
-	select {
-	case <-getty.GetTimeWheel().After(c.Opts.RequestTimeout):
-		c.removePendingResponse(impl.SequenceType(rsp.seq))
-		return perrors.WithStack(errClientReadTimeout)
-	case <-rsp.done:
-		err = rsp.err
-	}
-
-	return perrors.WithStack(err)
-}
-
-// Close close the client pool.
-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(impl.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 *impl.DubboPackage,
-	rsp *PendingResponse) error {
-
-	var (
-		sequence uint64
-		err      error
-	)
-
-	sequence = c.Sequence.Add(1)
-
-	if pkg == nil {
-		// make heartbeat package
-		header := impl.DubboHeader{
-			Type:     impl.PackageHeartbeat,
-			SerialID: constant.S_Hessian2,
-		}
-		pkg = NewClientRequestPackage(header, impl.Service{})
-		// SetBody
-		reqPayload := impl.NewRequestPayload([]interface{}{}, nil)
-		pkg.SetBody(reqPayload)
-		// set serializer
-		if err := impl.LoadSerializer(pkg); err != nil {
-			return err
-		}
-	}
-	pkg.SetID(int64(sequence))
-
-	// cond1
-	if rsp != nil {
-		rsp.seq = sequence
-		c.addPendingResponse(rsp)
-	}
-
-	err = session.WritePkg(pkg, c.Opts.RequestTimeout)
-	if err != nil {
-		c.removePendingResponse(impl.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(impl.SequenceType(pr.seq), pr)
-}
-
-func (c *Client) removePendingResponse(seq impl.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
-}
-
-// PendingResponse ...
-type PendingResponse struct {
-	seq       uint64
-	err       error
-	start     time.Time
-	readStart time.Time
-	callback  common.AsyncCallback
-	response  *Response
-	done      chan struct{}
-}
-
-// NewPendingResponse create a PendingResponses.
-func NewPendingResponse() *PendingResponse {
-	return &PendingResponse{
-		start:    time.Now(),
-		response: &Response{},
-		done:     make(chan struct{}),
-	}
-}
-
-// GetCallResponse get AsyncCallbackResponse.
-func (r PendingResponse) GetCallResponse() common.CallbackResponse {
-	return AsyncCallbackResponse{
-		Cause:     r.err,
-		Start:     r.start,
-		ReadStart: r.readStart,
-		Reply:     r.response,
-	}
-}
-
-// client side request package, just for serialization
-func NewClientRequestPackage(header impl.DubboHeader, svc impl.Service) *impl.DubboPackage {
-	return &impl.DubboPackage{
-		Header:  header,
-		Service: svc,
-		Body:    nil,
-		Err:     nil,
-		Codec:   impl.NewDubboCodec(nil),
-	}
-}
diff --git a/protocol/dubbo/server.go b/protocol/dubbo/server.go
deleted file mode 100644
index 134a58c68697ea86f6803adfb63e593f909c6717..0000000000000000000000000000000000000000
--- a/protocol/dubbo/server.go
+++ /dev/null
@@ -1,125 +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"
-)
-import (
-	"github.com/opentracing/opentracing-go"
-	"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"
-	"github.com/apache/dubbo-go/protocol"
-	"github.com/apache/dubbo-go/protocol/dubbo/impl"
-	"github.com/apache/dubbo-go/protocol/dubbo/impl/remoting"
-	"github.com/apache/dubbo-go/protocol/invocation"
-	"github.com/dubbogo/getty"
-)
-
-func init() {
-
-	// load clientconfig from provider_config
-	// default use dubbo
-	providerConfig := config.GetProviderConfig()
-	if providerConfig.ApplicationConfig == nil {
-		return
-	}
-	protocolConf := providerConfig.ProtocolConf
-	defaultServerConfig := remoting.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)
-		}
-	}
-	remoting.SetServerConfig(defaultServerConfig)
-}
-
-// 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 NewStubHandler() remoting.StubHandler {
-	return remoting.StubFunc(func(session getty.Session, p *impl.DubboPackage) {
-		u := common.NewURLWithOptions(common.WithPath(p.GetService().Path), common.WithParams(url.Values{}),
-			common.WithParamsValue(constant.GROUP_KEY, p.GetService().Group),
-			common.WithParamsValue(constant.INTERFACE_KEY, p.GetService().Interface),
-			common.WithParamsValue(constant.VERSION_KEY, p.GetService().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.SetResponseStatus(impl.Response_OK)
-			p.SetBody(err)
-			return
-		}
-		invoker := exporter.(protocol.Exporter).GetInvoker()
-		if invoker != nil {
-			attachments := p.GetBody().(map[string]interface{})["attachments"].(map[string]string)
-			attachments[constant.LOCAL_ADDR] = session.LocalAddr()
-			attachments[constant.REMOTE_ADDR] = session.RemoteAddr()
-
-			args := p.GetBody().(map[string]interface{})["args"].([]interface{})
-			inv := invocation.NewRPCInvocation(p.GetService().Method, args, attachments)
-
-			ctx := rebuildCtx(inv)
-			result := invoker.Invoke(ctx, inv)
-			logger.Debugf("invoker result: %+v", result)
-			if err := result.Error(); err != nil {
-				p.SetResponseStatus(impl.Response_OK)
-				p.SetBody(&impl.ResponsePayload{nil, err, result.Attachments()})
-			} else {
-				res := result.Result()
-				p.SetResponseStatus(impl.Response_OK)
-				p.SetBody(&impl.ResponsePayload{res, nil, result.Attachments()})
-			}
-		}
-	})
-}
diff --git a/protocol/invocation/rpcinvocation.go b/protocol/invocation/rpcinvocation.go
index b8b5b509702ea5ee62df83eb55bf7f1c86625b26..a84b4a7975a57065f565885b33b5e7660981dfb4 100644
--- a/protocol/invocation/rpcinvocation.go
+++ b/protocol/invocation/rpcinvocation.go
@@ -18,11 +18,13 @@
 package invocation
 
 import (
+	"github.com/apache/dubbo-go/common"
 	"reflect"
 	"sync"
 )
 
 import (
+	"github.com/apache/dubbo-go/common/constant"
 	"github.com/apache/dubbo-go/protocol"
 )
 
@@ -170,6 +172,11 @@ func (r *RPCInvocation) SetCallBack(c interface{}) {
 	r.callBack = c
 }
 
+func (r *RPCInvocation) ServiceKey() string {
+	return common.ServiceKey(r.AttachmentsByKey(constant.INTERFACE_KEY, ""),
+		r.AttachmentsByKey(constant.GROUP_KEY, ""), r.AttachmentsByKey(constant.VERSION_KEY, ""))
+}
+
 // /////////////////////////
 // option
 // /////////////////////////
diff --git a/protocol/jsonrpc/http_test.go b/protocol/jsonrpc/http_test.go
index f8480bf32e15ad428209eedb72757a299455eb20..188b036dfca5087f4729afbc64017d27b9aee902 100644
--- a/protocol/jsonrpc/http_test.go
+++ b/protocol/jsonrpc/http_test.go
@@ -22,19 +22,15 @@ import (
 	"strings"
 	"testing"
 	"time"
-)
 
-import (
 	"github.com/opentracing/opentracing-go"
-	perrors "github.com/pkg/errors"
-	"github.com/stretchr/testify/assert"
-)
 
-import (
 	"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"
+	perrors "github.com/pkg/errors"
+	"github.com/stretchr/testify/assert"
 )
 
 type (
@@ -71,7 +67,7 @@ func TestHTTPClient_Call(t *testing.T) {
 
 	// call GetUser
 	ctx := context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
-		"X-Proxy-Id": "dubbogo",
+		"X-Proxy-ID": "dubbogo",
 		"X-Services": url.Path,
 		"X-Method":   "GetUser",
 	})
@@ -85,7 +81,7 @@ func TestHTTPClient_Call(t *testing.T) {
 
 	// call GetUser0
 	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
-		"X-Proxy-Id": "dubbogo",
+		"X-Proxy-ID": "dubbogo",
 		"X-Services": url.Path,
 		"X-Method":   "GetUser0",
 	})
@@ -98,7 +94,7 @@ func TestHTTPClient_Call(t *testing.T) {
 
 	// call GetUser1
 	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
-		"X-Proxy-Id": "dubbogo",
+		"X-Proxy-ID": "dubbogo",
 		"X-Services": url.Path,
 		"X-Method":   "GetUser1",
 	})
@@ -110,7 +106,7 @@ func TestHTTPClient_Call(t *testing.T) {
 
 	// call GetUser2
 	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
-		"X-Proxy-Id": "dubbogo",
+		"X-Proxy-ID": "dubbogo",
 		"X-Services": url.Path,
 		"X-Method":   "GetUser2",
 	})
@@ -122,7 +118,7 @@ func TestHTTPClient_Call(t *testing.T) {
 
 	// call GetUser3
 	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
-		"X-Proxy-Id": "dubbogo",
+		"X-Proxy-ID": "dubbogo",
 		"X-Services": url.Path,
 		"X-Method":   "GetUser3",
 	})
@@ -134,7 +130,7 @@ func TestHTTPClient_Call(t *testing.T) {
 
 	// call GetUser4
 	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
-		"X-Proxy-Id": "dubbogo",
+		"X-Proxy-ID": "dubbogo",
 		"X-Services": url.Path,
 		"X-Method":   "GetUser4",
 	})
@@ -145,7 +141,7 @@ func TestHTTPClient_Call(t *testing.T) {
 	assert.Equal(t, &User{Id: "", Name: ""}, reply)
 
 	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
-		"X-Proxy-Id": "dubbogo",
+		"X-Proxy-ID": "dubbogo",
 		"X-Services": url.Path,
 		"X-Method":   "GetUser4",
 	})
diff --git a/protocol/jsonrpc/jsonrpc_invoker.go b/protocol/jsonrpc/jsonrpc_invoker.go
index d84b980216ade6e569e68af31fc90e1ea16b3056..6b3df4a52728060f79ecf25de7e0f81ed5c55854 100644
--- a/protocol/jsonrpc/jsonrpc_invoker.go
+++ b/protocol/jsonrpc/jsonrpc_invoker.go
@@ -19,13 +19,12 @@ package jsonrpc
 
 import (
 	"context"
-)
 
-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"
+
 	invocation_impl "github.com/apache/dubbo-go/protocol/invocation"
 )
 
diff --git a/protocol/protocolwrapper/protocol_filter_wrapper.go b/protocol/protocolwrapper/protocol_filter_wrapper.go
index cba1d5d5bce8c3de387381d17cc3f7965bf3adac..6cb343c160323805836aa00a78def97bf5878b54 100644
--- a/protocol/protocolwrapper/protocol_filter_wrapper.go
+++ b/protocol/protocolwrapper/protocol_filter_wrapper.go
@@ -68,6 +68,9 @@ func (pfw *ProtocolFilterWrapper) Destroy() {
 }
 
 func buildInvokerChain(invoker protocol.Invoker, key string) protocol.Invoker {
+	if invoker == nil {
+		return nil
+	}
 	filtName := invoker.GetUrl().GetParam(key, "")
 	if filtName == "" {
 		return invoker
diff --git a/protocol/dubbo/impl/remoting/errors.go b/remoting/codec.go
similarity index 61%
rename from protocol/dubbo/impl/remoting/errors.go
rename to remoting/codec.go
index 8fda9b31ff07c050b0658c2105b0c6d002a88b5c..607d1643cc1967e93bf5288d8d4c0788c73a735e 100644
--- a/protocol/dubbo/impl/remoting/errors.go
+++ b/remoting/codec.go
@@ -15,3 +15,31 @@
  * limitations under the License.
  */
 package remoting
+
+import (
+	"bytes"
+)
+
+// codec for exchangeClient
+type Codec interface {
+	EncodeRequest(request *Request) (*bytes.Buffer, error)
+	EncodeResponse(response *Response) (*bytes.Buffer, error)
+	Decode(data []byte) (DecodeResult, int, error)
+}
+
+type DecodeResult struct {
+	IsRequest bool
+	Result    interface{}
+}
+
+var (
+	codec = make(map[string]Codec, 2)
+)
+
+func RegistryCodec(protocol string, codecTmp Codec) {
+	codec[protocol] = codecTmp
+}
+
+func GetCodec(protocol string) Codec {
+	return codec[protocol]
+}
diff --git a/remoting/exchange.go b/remoting/exchange.go
new file mode 100644
index 0000000000000000000000000000000000000000..b97d6073c1f734d91c094372cf7de0919d088d99
--- /dev/null
+++ b/remoting/exchange.go
@@ -0,0 +1,144 @@
+/*
+ * 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 remoting
+
+import (
+	"time"
+)
+
+import (
+	"go.uber.org/atomic"
+)
+
+import (
+	"github.com/apache/dubbo-go/common"
+)
+
+var (
+	// generate request ID for global use
+	sequence atomic.Int64
+)
+
+func init() {
+	// init request ID
+	sequence.Store(0)
+}
+
+func SequenceId() int64 {
+	// increse 2 for every request as the same before.
+	// We expect that the request from client to server, the requestId is even; but from server to client, the requestId is odd.
+	return sequence.Add(2)
+}
+
+// this is request for transport layer
+type Request struct {
+	ID int64
+	// protocol version
+	Version string
+	// serial ID (ignore)
+	SerialID byte
+	// Data
+	Data   interface{}
+	TwoWay bool
+	Event  bool
+}
+
+// NewRequest aims to create Request.
+// The ID is auto increase.
+func NewRequest(version string) *Request {
+	return &Request{
+		ID:      SequenceId(),
+		Version: version,
+	}
+}
+
+// this is response for transport layer
+type Response struct {
+	ID       int64
+	Version  string
+	SerialID byte
+	Status   uint8
+	Event    bool
+	Error    error
+	Result   interface{}
+}
+
+// NewResponse aims to create Response
+func NewResponse(id int64, version string) *Response {
+	return &Response{
+		ID:      id,
+		Version: version,
+	}
+}
+
+// the response is heartbeat
+func (response *Response) IsHeartbeat() bool {
+	return response.Event && response.Result == nil
+}
+
+type Options struct {
+	// connect timeout
+	ConnectTimeout 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{}
+}
+
+// the client sends requst to server, there is one pendingResponse at client side to wait the response from server
+type PendingResponse struct {
+	seq       int64
+	Err       error
+	start     time.Time
+	ReadStart time.Time
+	Callback  common.AsyncCallback
+	response  *Response
+	Reply     interface{}
+	Done      chan struct{}
+}
+
+// NewPendingResponse aims to create PendingResponse.
+// Id is always from ID of Request
+func NewPendingResponse(id int64) *PendingResponse {
+	return &PendingResponse{
+		seq:      id,
+		start:    time.Now(),
+		response: &Response{},
+		Done:     make(chan struct{}),
+	}
+}
+
+func (r *PendingResponse) SetResponse(response *Response) {
+	r.response = response
+}
+
+// GetCallResponse is used for callback of async.
+// It is will return AsyncCallbackResponse.
+func (r PendingResponse) GetCallResponse() common.CallbackResponse {
+	return AsyncCallbackResponse{
+		Cause:     r.Err,
+		Start:     r.start,
+		ReadStart: r.ReadStart,
+		Reply:     r.response,
+	}
+}
diff --git a/remoting/exchange_client.go b/remoting/exchange_client.go
new file mode 100644
index 0000000000000000000000000000000000000000..7c0520ab9cb599ae1a4d09c575c9f4389aa007eb
--- /dev/null
+++ b/remoting/exchange_client.go
@@ -0,0 +1,227 @@
+/*
+ * 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 remoting
+
+import (
+	"errors"
+	"sync"
+	"time"
+)
+
+import (
+	"github.com/apache/dubbo-go/common"
+	"github.com/apache/dubbo-go/common/logger"
+	"github.com/apache/dubbo-go/protocol"
+)
+
+var (
+	// store requestID and response
+	pendingResponses *sync.Map = new(sync.Map)
+)
+
+type SequenceType int64
+
+// It is interface of client for network communication.
+// If you use getty as network communication, you should define GettyClient that implements this interface.
+type Client interface {
+	SetExchangeClient(client *ExchangeClient)
+	// responseHandler is used to deal with msg
+	SetResponseHandler(responseHandler ResponseHandler)
+	// connect url
+	Connect(url common.URL) error
+	// close
+	Close()
+	// send request to server.
+	Request(request *Request, timeout time.Duration, response *PendingResponse) error
+}
+
+// This is abstraction level. it is like facade.
+type ExchangeClient struct {
+	// connect server timeout
+	ConnectTimeout time.Duration
+	// to dial server address. The format: ip:port
+	address string
+	// the client that will deal with the transport. It is interface, and it will use gettyClient by default.
+	client Client
+	// the tag for init.
+	init bool
+}
+
+// handle the message from server
+type ResponseHandler interface {
+	Handler(response *Response)
+}
+
+// create ExchangeClient
+func NewExchangeClient(url common.URL, client Client, connectTimeout time.Duration, lazyInit bool) *ExchangeClient {
+	exchangeClient := &ExchangeClient{
+		ConnectTimeout: connectTimeout,
+		address:        url.Location,
+		client:         client,
+	}
+	client.SetExchangeClient(exchangeClient)
+	if !lazyInit {
+		if err := exchangeClient.doInit(url); err != nil {
+			return nil
+		}
+	}
+
+	client.SetResponseHandler(exchangeClient)
+	return exchangeClient
+}
+
+func (cl *ExchangeClient) doInit(url common.URL) error {
+	if cl.init {
+		return nil
+	}
+	if cl.client.Connect(url) != nil {
+		//retry for a while
+		time.Sleep(100 * time.Millisecond)
+		if cl.client.Connect(url) != nil {
+			logger.Errorf("Failed to connect server %+v " + url.Location)
+			return errors.New("Failed to connect server " + url.Location)
+		}
+	}
+	//FIXME atomic operation
+	cl.init = true
+	return nil
+}
+
+// two way request
+func (client *ExchangeClient) Request(invocation *protocol.Invocation, url common.URL, timeout time.Duration,
+	result *protocol.RPCResult) error {
+	if er := client.doInit(url); er != nil {
+		return er
+	}
+	request := NewRequest("2.0.2")
+	request.Data = invocation
+	request.Event = false
+	request.TwoWay = true
+
+	rsp := NewPendingResponse(request.ID)
+	rsp.response = NewResponse(request.ID, "2.0.2")
+	rsp.Reply = (*invocation).Reply()
+	AddPendingResponse(rsp)
+
+	err := client.client.Request(request, timeout, rsp)
+	// request error
+	if err != nil {
+		result.Err = err
+		return err
+	}
+	if resultTmp, ok := rsp.response.Result.(*protocol.RPCResult); ok {
+		result.Rest = resultTmp.Rest
+		result.Attrs = resultTmp.Attrs
+		result.Err = resultTmp.Err
+	}
+	return nil
+}
+
+// async two way request
+func (client *ExchangeClient) AsyncRequest(invocation *protocol.Invocation, url common.URL, timeout time.Duration,
+	callback common.AsyncCallback, result *protocol.RPCResult) error {
+	if er := client.doInit(url); er != nil {
+		return er
+	}
+	request := NewRequest("2.0.2")
+	request.Data = invocation
+	request.Event = false
+	request.TwoWay = true
+
+	rsp := NewPendingResponse(request.ID)
+	rsp.response = NewResponse(request.ID, "2.0.2")
+	rsp.Callback = callback
+	rsp.Reply = (*invocation).Reply()
+	AddPendingResponse(rsp)
+
+	err := client.client.Request(request, timeout, rsp)
+	if err != nil {
+		result.Err = err
+		return err
+	}
+	result.Rest = rsp.response
+	return nil
+}
+
+// oneway request
+func (client *ExchangeClient) Send(invocation *protocol.Invocation, url common.URL, timeout time.Duration) error {
+	if er := client.doInit(url); er != nil {
+		return er
+	}
+	request := NewRequest("2.0.2")
+	request.Data = invocation
+	request.Event = false
+	request.TwoWay = false
+
+	rsp := NewPendingResponse(request.ID)
+	rsp.response = NewResponse(request.ID, "2.0.2")
+
+	err := client.client.Request(request, timeout, rsp)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// close client
+func (client *ExchangeClient) Close() {
+	client.client.Close()
+}
+
+// handle the response from server
+func (client *ExchangeClient) Handler(response *Response) {
+
+	pendingResponse := removePendingResponse(SequenceType(response.ID))
+	if pendingResponse == nil {
+		logger.Errorf("failed to get pending response context for response package %s", *response)
+		return
+	}
+
+	pendingResponse.response = response
+
+	if pendingResponse.Callback == nil {
+		pendingResponse.Err = pendingResponse.response.Error
+		pendingResponse.Done <- struct{}{}
+	} else {
+		pendingResponse.Callback(pendingResponse.GetCallResponse())
+	}
+}
+
+// store response into map
+func AddPendingResponse(pr *PendingResponse) {
+	pendingResponses.Store(SequenceType(pr.seq), pr)
+}
+
+// get and remove response
+func removePendingResponse(seq SequenceType) *PendingResponse {
+	if pendingResponses == nil {
+		return nil
+	}
+	if presp, ok := pendingResponses.Load(seq); ok {
+		pendingResponses.Delete(seq)
+		return presp.(*PendingResponse)
+	}
+	return nil
+}
+
+// get response
+func GetPendingResponse(seq SequenceType) *PendingResponse {
+	if presp, ok := pendingResponses.Load(seq); ok {
+		return presp.(*PendingResponse)
+	}
+	return nil
+}
diff --git a/remoting/exchange_server.go b/remoting/exchange_server.go
new file mode 100644
index 0000000000000000000000000000000000000000..c4538075b53b9451bcf7ccc8cb981926b6adeb43
--- /dev/null
+++ b/remoting/exchange_server.go
@@ -0,0 +1,53 @@
+/*
+ * 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 remoting
+
+import (
+	"github.com/apache/dubbo-go/common"
+)
+
+// It is interface of server for network communication.
+// If you use getty as network communication, you should define GettyServer that implements this interface.
+type Server interface {
+	//invoke once for connection
+	Start()
+	//it is for destroy
+	Stop()
+}
+
+// This is abstraction level. it is like facade.
+type ExchangeServer struct {
+	Server Server
+}
+
+// Create ExchangeServer
+func NewExchangeServer(url common.URL, server Server) *ExchangeServer {
+	exchangServer := &ExchangeServer{
+		Server: server,
+	}
+	return exchangServer
+}
+
+// start server
+func (server *ExchangeServer) Start() {
+	server.Server.Start()
+}
+
+// stop server
+func (server *ExchangeServer) Stop() {
+	server.Server.Stop()
+}
diff --git a/protocol/dubbo/impl/remoting/config.go b/remoting/getty/config.go
similarity index 75%
rename from protocol/dubbo/impl/remoting/config.go
rename to remoting/getty/config.go
index 1f26422f79055ab126a8ef89446c84ed05cbdbab..d63a45a2e4d4d2e2b53c13b2de50a76fc3230b65 100644
--- a/protocol/dubbo/impl/remoting/config.go
+++ b/remoting/getty/config.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package remoting
+package getty
 
 import (
 	"time"
@@ -27,32 +27,33 @@ import (
 )
 
 type (
-	// GettySessionParam is session configuration for getty.
+	// 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"`
-		KeepAlivePeriodD time.Duration
+		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"`
-		TcpReadTimeoutD  time.Duration
+		tcpReadTimeout   time.Duration
 		TcpWriteTimeout  string `default:"5s" yaml:"tcp_write_timeout" json:"tcp_write_timeout,omitempty"`
-		TcpWriteTimeoutD time.Duration
+		tcpWriteTimeout  time.Duration
 		WaitTimeout      string `default:"7s" yaml:"wait_timeout" json:"wait_timeout,omitempty"`
-		WaitTimeoutD     time.Duration
+		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 holds supported types by the multiconfig package
+	// ServerConfig
+	//Config holds supported types by the multiconfig package
 	ServerConfig struct {
 		// session
-		SessionTimeout  string `default:"60s" yaml:"session_timeout" json:"session_timeout,omitempty"`
-		SessionTimeoutD time.Duration
-		SessionNumber   int `default:"1000" yaml:"session_number" json:"session_number,omitempty"`
+		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"`
@@ -63,20 +64,21 @@ type (
 		GettySessionParam GettySessionParam `required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"`
 	}
 
-	// ClientConfig holds supported types by the multiconfig package
+	// ClientConfig
+	//Config holds supported types by the multiconfig package
 	ClientConfig struct {
 		ReconnectInterval int `default:"0" yaml:"reconnect_interval" json:"reconnect_interval,omitempty"`
 
-		// session Pool
+		// 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"`
-		HeartbeatPeriodD time.Duration
+		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"`
-		SessionTimeoutD time.Duration
+		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"`
@@ -89,13 +91,10 @@ type (
 
 		// session tcp parameters
 		GettySessionParam GettySessionParam `required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"`
-
-		// serialization
-		Serialization string `default:"hessian2" yaml:"serialization" json:"serialization"`
 	}
 )
 
-// GetDefaultClientConfig gets client default configuration.
+// GetDefaultClientConfig ...
 func GetDefaultClientConfig() ClientConfig {
 	return ClientConfig{
 		ReconnectInterval: 0,
@@ -107,7 +106,6 @@ func GetDefaultClientConfig() ClientConfig {
 		GrPoolSize:        200,
 		QueueLen:          64,
 		QueueNumber:       10,
-		Serialization:     "hessian2",
 		GettySessionParam: GettySessionParam{
 			CompressEncoding: false,
 			TcpNoDelay:       true,
@@ -124,7 +122,7 @@ func GetDefaultClientConfig() ClientConfig {
 		}}
 }
 
-// GetDefaultServerConfig gets server default configuration.
+// GetDefaultServerConfig ...
 func GetDefaultServerConfig() ServerConfig {
 	return ServerConfig{
 		SessionTimeout: "180s",
@@ -149,60 +147,60 @@ func GetDefaultServerConfig() ServerConfig {
 	}
 }
 
-// CheckValidity confirm getty sessian params.
+// CheckValidity ...
 func (c *GettySessionParam) CheckValidity() error {
 	var err error
 
-	if c.KeepAlivePeriodD, err = time.ParseDuration(c.KeepAlivePeriod); err != nil {
+	if c.keepAlivePeriod, err = time.ParseDuration(c.KeepAlivePeriod); err != nil {
 		return perrors.WithMessagef(err, "time.ParseDuration(KeepAlivePeriod{%#v})", c.KeepAlivePeriod)
 	}
 
-	if c.TcpReadTimeoutD, err = time.ParseDuration(c.TcpReadTimeout); err != nil {
+	if c.tcpReadTimeout, err = time.ParseDuration(c.TcpReadTimeout); err != nil {
 		return perrors.WithMessagef(err, "time.ParseDuration(TcpReadTimeout{%#v})", c.TcpReadTimeout)
 	}
 
-	if c.TcpWriteTimeoutD, err = time.ParseDuration(c.TcpWriteTimeout); err != nil {
+	if c.tcpWriteTimeout, err = time.ParseDuration(c.TcpWriteTimeout); err != nil {
 		return perrors.WithMessagef(err, "time.ParseDuration(TcpWriteTimeout{%#v})", c.TcpWriteTimeout)
 	}
 
-	if c.WaitTimeoutD, err = time.ParseDuration(c.WaitTimeout); err != nil {
+	if c.waitTimeout, err = time.ParseDuration(c.WaitTimeout); err != nil {
 		return perrors.WithMessagef(err, "time.ParseDuration(WaitTimeout{%#v})", c.WaitTimeout)
 	}
 
 	return nil
 }
 
-// CheckValidity confirm client params.
+// CheckValidity ...
 func (c *ClientConfig) CheckValidity() error {
 	var err error
 
 	c.ReconnectInterval = c.ReconnectInterval * 1e6
 
-	if c.HeartbeatPeriodD, err = time.ParseDuration(c.HeartbeatPeriod); err != nil {
+	if c.heartbeatPeriod, err = time.ParseDuration(c.HeartbeatPeriod); err != nil {
 		return perrors.WithMessagef(err, "time.ParseDuration(HeartbeatPeroid{%#v})", c.HeartbeatPeriod)
 	}
 
-	if c.HeartbeatPeriodD >= time.Duration(getty.MaxWheelTimeSpan) {
+	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.SessionTimeoutD, err = time.ParseDuration(c.SessionTimeout); err != nil {
+	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 confirm server params.
+// CheckValidity ...
 func (c *ServerConfig) CheckValidity() error {
 	var err error
 
-	if c.SessionTimeoutD, err = time.ParseDuration(c.SessionTimeout); err != nil {
+	if c.sessionTimeout, err = time.ParseDuration(c.SessionTimeout); err != nil {
 		return perrors.WithMessagef(err, "time.ParseDuration(SessionTimeout{%#v})", c.SessionTimeout)
 	}
 
-	if c.SessionTimeoutD >= time.Duration(getty.MaxWheelTimeSpan) {
+	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))
 	}
diff --git a/remoting/getty/dubbo_codec_for_test.go b/remoting/getty/dubbo_codec_for_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..f6460cde9ddb420eb57758bd32150bb84fea9dd0
--- /dev/null
+++ b/remoting/getty/dubbo_codec_for_test.go
@@ -0,0 +1,382 @@
+/*
+ * 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
+
+// copy from dubbo/dubbo_codec.go .
+// it is used to unit test.
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"strconv"
+	"time"
+)
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	perrors "github.com/pkg/errors"
+)
+
+import (
+	"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"
+)
+
+//SerialID serial ID
+type SerialID byte
+
+const (
+	// S_Dubbo dubbo serial id
+	S_Dubbo SerialID = 2
+)
+
+func init() {
+	codec := &DubboTestCodec{}
+	remoting.RegistryCodec("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 {
+		// it will be wrapped in readwrite.Write .
+		return nil, 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
new file mode 100644
index 0000000000000000000000000000000000000000..7055b985056a5c2d7d7aeb325ac3f367953347ea
--- /dev/null
+++ b/remoting/getty/getty_client.go
@@ -0,0 +1,219 @@
+/*
+ * 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 (
+	"math/rand"
+	"time"
+)
+
+import (
+	"github.com/dubbogo/getty"
+	gxsync "github.com/dubbogo/gost/sync"
+	perrors "github.com/pkg/errors"
+	"gopkg.in/yaml.v2"
+)
+
+import (
+	"github.com/apache/dubbo-go/common"
+	"github.com/apache/dubbo-go/common/logger"
+	"github.com/apache/dubbo-go/config"
+	"github.com/apache/dubbo-go/remoting"
+)
+
+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
+)
+
+// it is init client for single protocol.
+func initClient(protocol string) {
+	if protocol == "" {
+		return
+	}
+
+	// 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{})[protocol]
+		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())
+}
+
+// Config ClientConf
+func SetClientConf(c ClientConfig) {
+	clientConf = &c
+	err := clientConf.CheckValidity()
+	if err != nil {
+		logger.Warnf("[ClientConfig CheckValidity] error: %v", err)
+		return
+	}
+	setClientGrpool()
+}
+
+func setClientGrpool() {
+	if clientConf.GrPoolSize > 1 {
+		clientGrpool = gxsync.NewTaskPool(gxsync.WithTaskPoolTaskPoolSize(clientConf.GrPoolSize), gxsync.WithTaskPoolTaskQueueLength(clientConf.QueueLen),
+			gxsync.WithTaskPoolTaskQueueNumber(clientConf.QueueNumber))
+	}
+}
+
+// Options : param config
+type Options struct {
+	// connect timeout
+	// remove request timeout, it will be calulate for every request
+	ConnectTimeout time.Duration
+}
+
+// Client : some configuration for network communication.
+type Client struct {
+	addr            string
+	opts            Options
+	conf            ClientConfig
+	pool            *gettyRPCClientPool
+	codec           remoting.Codec
+	responseHandler remoting.ResponseHandler
+	ExchangeClient  *remoting.ExchangeClient
+}
+
+// create client
+func NewClient(opt Options) *Client {
+	switch {
+	case opt.ConnectTimeout == 0:
+		opt.ConnectTimeout = 3 * time.Second
+	}
+
+	c := &Client{
+		opts: opt,
+	}
+	return c
+}
+
+func (c *Client) SetExchangeClient(client *remoting.ExchangeClient) {
+	c.ExchangeClient = client
+}
+func (c *Client) SetResponseHandler(responseHandler remoting.ResponseHandler) {
+	c.responseHandler = responseHandler
+}
+
+// init client and try to connection.
+func (c *Client) Connect(url common.URL) error {
+	initClient(url.Protocol)
+	c.conf = *clientConf
+	// new client
+	c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL))
+	// codec
+	c.codec = remoting.GetCodec(url.Protocol)
+	c.addr = url.Location
+	_, _, err := c.selectSession(c.addr)
+	if err != nil {
+		logger.Errorf("try to connect server %v failed for : %v", url.Location, err)
+	}
+	return err
+}
+
+// close network connection
+func (c *Client) Close() {
+	if c.pool != nil {
+		c.pool.close()
+	}
+	c.pool = nil
+}
+
+// send request
+func (c *Client) Request(request *remoting.Request, timeout time.Duration, response *remoting.PendingResponse) error {
+	_, session, err := c.selectSession(c.addr)
+	if err != nil {
+		return perrors.WithStack(err)
+	}
+	if session == nil {
+		return errSessionNotExist
+	}
+
+	if err = c.transfer(session, request, timeout); err != nil {
+		return perrors.WithStack(err)
+	}
+
+	if !request.TwoWay || response.Callback != nil {
+		return nil
+	}
+
+	select {
+	case <-getty.GetTimeWheel().After(timeout):
+		return perrors.WithStack(errClientReadTimeout)
+	case <-response.Done:
+		err = response.Err
+	}
+
+	return perrors.WithStack(err)
+}
+
+func (c *Client) selectSession(addr string) (*gettyRPCClient, getty.Session, error) {
+	rpcClient, err := c.pool.getGettyRpcClient(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(req.ID)
+	remoting.AddPendingResponse(resp)
+	return c.transfer(session, req, 3*time.Second)
+}
+
+func (c *Client) transfer(session getty.Session, request *remoting.Request, timeout time.Duration) error {
+	err := session.WritePkg(request, timeout)
+	return perrors.WithStack(err)
+}
diff --git a/remoting/getty/getty_client_test.go b/remoting/getty/getty_client_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..12726547d69e75912d1074af6f96b4427ed20ac8
--- /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"
+)
+
+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/constant"
+	"github.com/apache/dubbo-go/common/proxy/proxy_factory"
+	"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"
+)
+
+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, false)
+	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.RegistryCodec("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&timestamp=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/protocol/dubbo/impl/remoting/server_impl.go b/remoting/getty/getty_server.go
similarity index 56%
rename from protocol/dubbo/impl/remoting/server_impl.go
rename to remoting/getty/getty_server.go
index 6419ff685cda3390554f63477baed47c730a1b4e..6dc15d251f3b357f271ac420b6adc9ea194b957f 100644
--- a/protocol/dubbo/impl/remoting/server_impl.go
+++ b/remoting/getty/getty_server.go
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package remoting
+
+package getty
 
 import (
 	"fmt"
@@ -22,35 +23,74 @@ import (
 )
 
 import (
-	"github.com/apache/dubbo-go/common"
-	"github.com/apache/dubbo-go/common/logger"
+	"github.com/dubbogo/getty"
+	gxsync "github.com/dubbogo/gost/sync"
+	"gopkg.in/yaml.v2"
 )
 
 import (
-	"github.com/dubbogo/getty"
-	gxsync "github.com/dubbogo/gost/sync"
+	"github.com/apache/dubbo-go/common"
+	"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"
 )
 
-// TODO: 闇€瑕佺Щ鍔ㄥ埌 涓氬姟鐨勫疄鐜�
 var (
 	srvConf   *ServerConfig
 	srvGrpool *gxsync.TaskPool
 )
 
+func initServer(protocol string) {
+
+	// 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{})[protocol]
+		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 {
-		panic(err)
+		logger.Warnf("[ServerConfig CheckValidity] error: %v", err)
 		return
 	}
 	SetServerGrpool()
 }
 
 // GetServerConfig ...
-func GetServerConfig() *ServerConfig {
-	return srvConf
+func GetServerConfig() ServerConfig {
+	return *srvConf
 }
 
 // SetServerGrpool ...
@@ -63,19 +103,27 @@ func SetServerGrpool() {
 
 // Server ...
 type Server struct {
-	conf       ServerConfig
-	tcpServer  getty.Server
-	rpcHandler *RpcServerHandler
+	conf           ServerConfig
+	addr           string
+	codec          remoting.Codec
+	tcpServer      getty.Server
+	rpcHandler     *RpcServerHandler
+	requestHandler func(*invocation.RPCInvocation) protocol.RPCResult
 }
 
 // NewServer ...
-func NewServer(handler StubHandler) *Server {
+func NewServer(url common.URL, handlers func(*invocation.RPCInvocation) protocol.RPCResult) *Server {
+	//init
+	initServer(url.Protocol)
 
 	s := &Server{
-		conf: *srvConf,
+		conf:           *srvConf,
+		addr:           url.Location,
+		codec:          remoting.GetCodec(url.Protocol),
+		requestHandler: handlers,
 	}
 
-	s.rpcHandler = NewRpcServerHandler(handler, s.conf.SessionNumber, s.conf.SessionTimeoutD)
+	s.rpcHandler = NewRpcServerHandler(s.conf.SessionNumber, s.conf.sessionTimeout, s)
 
 	return s
 }
@@ -98,20 +146,20 @@ func (s *Server) newSession(session getty.Session) error {
 	tcpConn.SetNoDelay(conf.GettySessionParam.TcpNoDelay)
 	tcpConn.SetKeepAlive(conf.GettySessionParam.TcpKeepAlive)
 	if conf.GettySessionParam.TcpKeepAlive {
-		tcpConn.SetKeepAlivePeriod(conf.GettySessionParam.KeepAlivePeriodD)
+		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.SetPkgHandler(NewRpcServerPackageHandler(s))
 	session.SetEventListener(s.rpcHandler)
 	session.SetWQLen(conf.GettySessionParam.PkgWQSize)
-	session.SetReadTimeout(conf.GettySessionParam.TcpReadTimeoutD)
-	session.SetWriteTimeout(conf.GettySessionParam.TcpWriteTimeoutD)
-	session.SetCronPeriod((int)(conf.SessionTimeoutD.Nanoseconds() / 1e6))
-	session.SetWaitTime(conf.GettySessionParam.WaitTimeoutD)
+	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)
@@ -120,18 +168,16 @@ func (s *Server) newSession(session getty.Session) error {
 }
 
 // Start ...
-func (s *Server) Start(url common.URL) {
+func (s *Server) Start() {
 	var (
-		addr      string
 		tcpServer getty.Server
 	)
 
-	addr = url.Location
 	tcpServer = getty.NewTCPServer(
-		getty.WithLocalAddress(addr),
+		getty.WithLocalAddress(s.addr),
 	)
 	tcpServer.RunEventLoop(s.newSession)
-	logger.Debugf("s bind addr{%s} ok!", addr)
+	logger.Debugf("s bind addr{%s} ok!", s.addr)
 	s.tcpServer = tcpServer
 
 }
diff --git a/protocol/dubbo/impl/remoting/server_listener.go b/remoting/getty/listener.go
similarity index 54%
rename from protocol/dubbo/impl/remoting/server_listener.go
rename to remoting/getty/listener.go
index f59e88e3f31a1067a27c133e8f7c8bdca8a76137..777e14c2ecb344d3fa2aa2084b79c7805f542e28 100644
--- a/protocol/dubbo/impl/remoting/server_listener.go
+++ b/remoting/getty/listener.go
@@ -15,9 +15,10 @@
  * limitations under the License.
  */
 
-package remoting
+package getty
 
 import (
+	"fmt"
 	"sync"
 	"sync/atomic"
 	"time"
@@ -30,13 +31,16 @@ import (
 )
 
 import (
+	"github.com/apache/dubbo-go/common/constant"
 	"github.com/apache/dubbo-go/common/logger"
-	"github.com/apache/dubbo-go/protocol/dubbo/impl"
+	"github.com/apache/dubbo-go/protocol/invocation"
+	"github.com/apache/dubbo-go/remoting"
 )
 
-// todo: writePkg_Timeout will entry *.yml
+// todo: WritePkg_Timeout will entry *.yml
 const (
-	writePkg_Timeout = 5 * time.Second
+	// WritePkg_Timeout ...
+	WritePkg_Timeout = 5 * time.Second
 )
 
 var (
@@ -48,12 +52,10 @@ type rpcSession struct {
 	reqNum  int32
 }
 
-// AddReqNum adds total request number safely
 func (s *rpcSession) AddReqNum(num int32) {
 	atomic.AddInt32(&s.reqNum, num)
 }
 
-// GetReqNum gets total request number safely
 func (s *rpcSession) GetReqNum() int32 {
 	return atomic.LoadInt32(&s.reqNum)
 }
@@ -62,74 +64,81 @@ func (s *rpcSession) GetReqNum() int32 {
 // RpcClientHandler
 // //////////////////////////////////////////
 
-// RpcClientHandler is handler of RPC Client
+// RpcClientHandler ...
 type RpcClientHandler struct {
 	conn *gettyRPCClient
 }
 
-// NewRpcClientHandler creates RpcClientHandler with @gettyRPCClient
+// NewRpcClientHandler ...
 func NewRpcClientHandler(client *gettyRPCClient) *RpcClientHandler {
 	return &RpcClientHandler{conn: client}
 }
 
-// OnOpen notified when RPC client session opened
+// OnOpen ...
 func (h *RpcClientHandler) OnOpen(session getty.Session) error {
 	h.conn.addSession(session)
 	return nil
 }
 
-// OnError notified when RPC client session got any error
+// OnError ...
 func (h *RpcClientHandler) OnError(session getty.Session, err error) {
-	logger.Warnf("session{%s} got error{%v}, will be closed.", session.Stat(), err)
+	logger.Infof("session{%s} got error{%v}, will be closed.", session.Stat(), err)
 	h.conn.removeSession(session)
 }
 
-// OnOpen notified when RPC client session closed
+// OnClose ...
 func (h *RpcClientHandler) OnClose(session getty.Session) {
 	logger.Infof("session{%s} is closing......", session.Stat())
 	h.conn.removeSession(session)
 }
 
-// OnMessage notified when RPC client session got any message in connection
+// OnMessage ...
 func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) {
-	p, ok := pkg.(*impl.DubboPackage)
+	result, ok := pkg.(remoting.DecodeResult)
 	if !ok {
 		logger.Errorf("illegal package")
 		return
 	}
-
-	if p.Header.Type&impl.PackageHeartbeat != 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)
+	// 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
 	}
-	logger.Debugf("get rpc response{header: %#v, body: %#v}", p.Header, p.Body)
-
-	h.conn.updateSession(session)
 
-	pendingResponse := h.conn.pool.rpcClient.removePendingResponse(impl.SequenceType(p.Header.ID))
-	if pendingResponse == nil {
-		logger.Errorf("failed to get pending response context for response package %s", *p)
+	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)
 		return
 	}
-
-	if p.Err != nil {
-		pendingResponse.err = p.Err
+	if result.IsRequest {
+		logger.Errorf("illegal package for it is response type. {%#v}", pkg)
+		return
 	}
 
-	pendingResponse.response.Atta = p.Body.(*Response).Atta
+	logger.Debugf("get rpc response{%#v}", p)
 
-	if pendingResponse.callback == nil {
-		pendingResponse.done <- struct{}{}
-	} else {
-		logger.Info("proxy service callback")
-		pendingResponse.callback(pendingResponse.GetCallResponse())
-	}
+	h.conn.updateSession(session)
+
+	h.conn.pool.rpcClient.responseHandler.Handler(p)
 }
 
-// OnCron notified when RPC client session got any message in cron job
+// OnCron ...
 func (h *RpcClientHandler) OnCron(session getty.Session) {
 	rpcSession, err := h.conn.getClientRpcSession(session)
 	if err != nil {
@@ -137,10 +146,10 @@ func (h *RpcClientHandler) OnCron(session getty.Session) {
 			session.Stat(), perrors.WithStack(err))
 		return
 	}
-	if h.conn.pool.rpcClient.Conf.SessionTimeoutD.Nanoseconds() < time.Since(session.GetActive()).Nanoseconds() {
+	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)
+		h.conn.removeSession(session) // -> h.conn.close() -> h.conn.pool.remove(h.conn)
 		return
 	}
 
@@ -151,35 +160,26 @@ func (h *RpcClientHandler) OnCron(session getty.Session) {
 // RpcServerHandler
 // //////////////////////////////////////////
 
-type StubHandler interface {
-	OnPackage(session getty.Session, pkg *impl.DubboPackage)
-}
-
-type StubFunc func(session getty.Session, pkg *impl.DubboPackage)
-
-func (f StubFunc) OnPackage(session getty.Session, pkg *impl.DubboPackage) {
-	f(session, pkg)
-}
-
+// RpcServerHandler ...
 type RpcServerHandler struct {
 	maxSessionNum  int
 	sessionTimeout time.Duration
 	sessionMap     map[getty.Session]*rpcSession
 	rwlock         sync.RWMutex
-	stub           StubHandler
+	server         *Server
 }
 
-// NewRpcServerHandler creates RpcServerHandler with @maxSessionNum and @sessionTimeout
-func NewRpcServerHandler(stubHandler StubHandler, maxSessionNum int, sessionTimeout time.Duration) *RpcServerHandler {
+// NewRpcServerHandler ...
+func NewRpcServerHandler(maxSessionNum int, sessionTimeout time.Duration, serverP *Server) *RpcServerHandler {
 	return &RpcServerHandler{
 		maxSessionNum:  maxSessionNum,
 		sessionTimeout: sessionTimeout,
 		sessionMap:     make(map[getty.Session]*rpcSession),
-		stub:           stubHandler,
+		server:         serverP,
 	}
 }
 
-// OnOpen notified when RPC server session opened
+// OnOpen ...
 func (h *RpcServerHandler) OnOpen(session getty.Session) error {
 	var err error
 	h.rwlock.RLock()
@@ -198,15 +198,15 @@ func (h *RpcServerHandler) OnOpen(session getty.Session) error {
 	return nil
 }
 
-// OnError notified when RPC server session got any error
+// OnError ...
 func (h *RpcServerHandler) OnError(session getty.Session, err error) {
-	logger.Warnf("session{%s} got error{%v}, will be closed.", session.Stat(), err)
+	logger.Infof("session{%s} got error{%v}, will be closed.", session.Stat(), err)
 	h.rwlock.Lock()
 	delete(h.sessionMap, session)
 	h.rwlock.Unlock()
 }
 
-// OnOpen notified when RPC server session closed
+// OnClose ...
 func (h *RpcServerHandler) OnClose(session getty.Session) {
 	logger.Infof("session{%s} is closing......", session.Stat())
 	h.rwlock.Lock()
@@ -214,7 +214,7 @@ func (h *RpcServerHandler) OnClose(session getty.Session) {
 	h.rwlock.Unlock()
 }
 
-// OnMessage notified when RPC server session got any message in connection
+// OnMessage ...
 func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) {
 	h.rwlock.Lock()
 	if _, ok := h.sessionMap[session]; ok {
@@ -222,54 +222,70 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) {
 	}
 	h.rwlock.Unlock()
 
-	p, ok := pkg.(*impl.DubboPackage)
+	decodeResult, ok := pkg.(remoting.DecodeResult)
 	if !ok {
 		logger.Errorf("illegal package{%#v}", pkg)
 		return
 	}
-	p.SetResponseStatus(hessian.Response_OK)
-	//p.Header.ResponseStatus = hessian.Response_OK
-
-	// heartbeat
-	if p.GetHeader().Type&impl.PackageHeartbeat != 0x00 {
-		logger.Debugf("get rpc heartbeat request{header: %#v, service: %#v, body: %#v}", p.GetHeader(), p.GetService(), p.GetBody())
-		h.reply(session, p, impl.PackageHeartbeat)
+	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
+	resp.SerialID = req.SerialID
+	resp.Version = "2.0.2"
 
-	twoway := true
-	// not twoway
-	if p.GetHeader().Type&impl.PackageRequest_TwoWay == 0x00 {
-		twoway = false
+	// heartbeat
+	if req.Event {
+		logger.Debugf("get rpc heartbeat request{%#v}", resp)
+		reply(session, resp, hessian.PackageHeartbeat)
+		return
 	}
 
 	defer func() {
 		if e := recover(); e != nil {
-			p.SetResponseStatus(hessian.Response_SERVER_ERROR)
+			resp.Status = hessian.Response_SERVER_ERROR
 			if err, ok := e.(error); ok {
 				logger.Errorf("OnMessage panic: %+v", perrors.WithStack(err))
-				p.SetBody(perrors.WithStack(err))
+				resp.Error = perrors.WithStack(err)
 			} else if err, ok := e.(string); ok {
 				logger.Errorf("OnMessage panic: %+v", perrors.New(err))
-				p.SetBody(perrors.New(err))
+				resp.Error = perrors.New(err)
 			} else {
 				logger.Errorf("OnMessage panic: %+v, this is impossible.", e)
-				p.SetBody(e)
+				resp.Error = fmt.Errorf("OnMessage panic unknow exception. %+v", e)
 			}
 
-			if !twoway {
+			if !req.TwoWay {
 				return
 			}
-			h.reply(session, p, impl.PackageResponse)
+			reply(session, resp, hessian.PackageResponse)
 		}
 
 	}()
 
-	h.stub.OnPackage(session, p)
-	h.reply(session, p, impl.PackageResponse)
+	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
+	}
+	resp.Result = result
+	reply(session, resp, hessian.PackageResponse)
 }
 
-// OnCron notified when RPC server session got any message in cron job
+// OnCron ...
 func (h *RpcServerHandler) OnCron(session getty.Session) {
 	var (
 		flag   bool
@@ -295,35 +311,9 @@ func (h *RpcServerHandler) OnCron(session getty.Session) {
 	}
 }
 
-func (h *RpcServerHandler) reply(session getty.Session, req *impl.DubboPackage, tp impl.PackageType) {
-	header := impl.DubboHeader{
-		SerialID:       req.GetHeader().SerialID,
-		Type:           tp,
-		ID:             req.GetHeader().ID,
-		BodyLen:        0,
-		ResponseStatus: req.GetHeader().ResponseStatus,
-	}
-	resp := NewServerResponsePackage(header)
-	if err := impl.LoadSerializer(resp); err != nil {
-		logger.Errorf("Reply error %v", err)
-		return
-	}
-
-	if req.GetHeader().Type&impl.PackageRequest != 0x00 {
-		resp.SetBody(req.GetBody())
-	}
-
-	if err := session.WritePkg(resp, writePkg_Timeout); err != nil {
-		logger.Errorf("WritePkg error: %#v, %#v", perrors.WithStack(err), req.GetHeader())
-	}
-}
+func reply(session getty.Session, resp *remoting.Response, tp hessian.PackageType) {
 
-// server side response package, just for serialization
-func NewServerResponsePackage(header impl.DubboHeader) *impl.DubboPackage {
-	return &impl.DubboPackage{
-		Header: header,
-		Body:   nil,
-		Err:    nil,
-		Codec:  impl.NewDubboCodec(nil),
+	if err := session.WritePkg(resp, WritePkg_Timeout); err != nil {
+		logger.Errorf("WritePkg error: %#v, %#v", perrors.WithStack(err), resp)
 	}
 }
diff --git a/protocol/dubbo/server_test.go b/remoting/getty/listener_test.go
similarity index 74%
rename from protocol/dubbo/server_test.go
rename to remoting/getty/listener_test.go
index aa7d75056f8bae405c22a1caa5f7224c17360015..da460aec1430f8ecb2c2cb84fc6978b92ba9be58 100644
--- a/protocol/dubbo/server_test.go
+++ b/remoting/getty/listener_test.go
@@ -15,9 +15,10 @@
  * limitations under the License.
  */
 
-package dubbo
+package getty
 
 import (
+	"context"
 	"testing"
 )
 
@@ -56,3 +57,18 @@ func TestRebuildCtx(t *testing.T) {
 	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/protocol/dubbo/impl/remoting/pool.go b/remoting/getty/pool.go
similarity index 81%
rename from protocol/dubbo/impl/remoting/pool.go
rename to remoting/getty/pool.go
index dc8b1238cc1b8f6ae8aee2e4b42186ae7d6e24bc..fdefa238202f0b650c9b7cf3389b81cca2f1c80d 100644
--- a/protocol/dubbo/impl/remoting/pool.go
+++ b/remoting/getty/pool.go
@@ -15,11 +15,10 @@
  * limitations under the License.
  */
 
-package remoting
+package getty
 
 import (
 	"fmt"
-
 	"math/rand"
 	"net"
 	"sync"
@@ -37,10 +36,10 @@ import (
 )
 
 type gettyRPCClient struct {
-	once     sync.Once
-	protocol string
-	addr     string
-	active   int64 // zero, not create or be destroyed
+	once sync.Once
+	//protocol string
+	addr   string
+	active int64 // zero, not create or be destroyed
 
 	pool *gettyRPCClientPool
 
@@ -50,23 +49,23 @@ type gettyRPCClient struct {
 }
 
 var (
-	errClientPoolClosed = perrors.New("client Pool closed")
+	errClientPoolClosed = perrors.New("client pool closed")
 )
 
-func newGettyRPCClientConn(pool *gettyRPCClientPool, protocol, addr string) (*gettyRPCClient, error) {
+func newGettyRPCClientConn(pool *gettyRPCClientPool, addr string) (*gettyRPCClient, error) {
 	c := &gettyRPCClient{
-		protocol: protocol,
-		addr:     addr,
-		pool:     pool,
+		//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),
+			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)
+	times := int(pool.rpcClient.opts.ConnectTimeout / 1e6)
 	for {
 		idx++
 		if c.isAvailable() {
@@ -99,8 +98,7 @@ func (c *gettyRPCClient) newSession(session getty.Session) error {
 		tcpConn *net.TCPConn
 		conf    ClientConfig
 	)
-
-	conf = c.pool.rpcClient.Conf
+	conf = c.pool.rpcClient.conf
 	if conf.GettySessionParam.CompressEncoding {
 		session.SetCompressType(getty.CompressZip)
 	}
@@ -112,7 +110,7 @@ func (c *gettyRPCClient) newSession(session getty.Session) error {
 	tcpConn.SetNoDelay(conf.GettySessionParam.TcpNoDelay)
 	tcpConn.SetKeepAlive(conf.GettySessionParam.TcpKeepAlive)
 	if conf.GettySessionParam.TcpKeepAlive {
-		tcpConn.SetKeepAlivePeriod(conf.GettySessionParam.KeepAlivePeriodD)
+		tcpConn.SetKeepAlivePeriod(conf.GettySessionParam.keepAlivePeriod)
 	}
 	tcpConn.SetReadBuffer(conf.GettySessionParam.TcpRBufSize)
 	tcpConn.SetWriteBuffer(conf.GettySessionParam.TcpWBufSize)
@@ -122,10 +120,10 @@ func (c *gettyRPCClient) newSession(session getty.Session) error {
 	session.SetPkgHandler(NewRpcClientPackageHandler(c.pool.rpcClient))
 	session.SetEventListener(NewRpcClientHandler(c))
 	session.SetWQLen(conf.GettySessionParam.PkgWQSize)
-	session.SetReadTimeout(conf.GettySessionParam.TcpReadTimeoutD)
-	session.SetWriteTimeout(conf.GettySessionParam.TcpWriteTimeoutD)
-	session.SetCronPeriod((int)(conf.HeartbeatPeriodD.Nanoseconds() / 1e6))
-	session.SetWaitTime(conf.GettySessionParam.WaitTimeoutD)
+	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)
@@ -220,25 +218,25 @@ func (c *gettyRPCClient) updateSession(session getty.Session) {
 
 func (c *gettyRPCClient) getClientRpcSession(session getty.Session) (rpcSession, error) {
 	var (
-		err              error
-		rpcClientSession rpcSession
+		err        error
+		rpcSession rpcSession
 	)
 	c.lock.RLock()
 	defer c.lock.RUnlock()
 	if c.sessions == nil {
-		return rpcClientSession, errClientClosed
+		return rpcSession, errClientClosed
 	}
 
 	err = errSessionNotExist
 	for _, s := range c.sessions {
 		if s.session == session {
-			rpcClientSession = *s
+			rpcSession = *s
 			err = nil
 			break
 		}
 	}
 
-	return rpcClientSession, perrors.WithStack(err)
+	return rpcSession, perrors.WithStack(err)
 }
 
 func (c *gettyRPCClient) isAvailable() bool {
@@ -297,12 +295,13 @@ type gettyRPCClientPool struct {
 	conns []*gettyRPCClient
 }
 
-func NewGettyRPCClientConnPool(rpcClient *Client, size int, ttl time.Duration) *gettyRPCClientPool {
+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),
+		// init capacity : 2
+		conns: make([]*gettyRPCClient, 0, 2),
 	}
 }
 
@@ -316,11 +315,15 @@ func (p *gettyRPCClientPool) close() {
 	}
 }
 
-func (p *gettyRPCClientPool) getGettyRpcClient(protocol, addr string) (*gettyRPCClient, error) {
+func (p *gettyRPCClientPool) getGettyRpcClient(addr string) (*gettyRPCClient, error) {
 	conn, err := p.get()
 	if err == nil && conn == nil {
 		// create new conn
-		conn, err = newGettyRPCClientConn(p, protocol, addr)
+		rpcClientConn, err := newGettyRPCClientConn(p, addr)
+		if err == nil {
+			p.put(rpcClientConn)
+		}
+		return rpcClientConn, perrors.WithStack(err)
 	}
 	return conn, perrors.WithStack(err)
 }
@@ -333,10 +336,15 @@ func (p *gettyRPCClientPool) get() (*gettyRPCClient, error) {
 	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]
+	for num := len(p.conns); num > 0; {
+		var conn *gettyRPCClient
+		if num != 1 {
+			conn = p.conns[rand.Int31n(int32(num))]
+		} else {
+			conn = p.conns[0]
+		}
+		// This will recreate gettyRpcClient for remove last position
+		//p.conns = p.conns[:len(p.conns)-1]
 
 		if d := now - conn.getActive(); d > p.ttl {
 			p.remove(conn)
@@ -353,23 +361,19 @@ 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
+		// delete @conn from client pool
 		// p.remove(conn)
 		conn.close()
 		return
diff --git a/protocol/dubbo/impl/remoting/readwriter.go b/remoting/getty/readwriter.go
similarity index 50%
rename from protocol/dubbo/impl/remoting/readwriter.go
rename to remoting/getty/readwriter.go
index 6d211f5ea5e6e9365d396370a9f0c102f7fa6183..c8105fad0f47bab9c216c06500dac86946ad2017 100644
--- a/protocol/dubbo/impl/remoting/readwriter.go
+++ b/remoting/getty/readwriter.go
@@ -15,12 +15,9 @@
  * limitations under the License.
  */
 
-// TODO: zero.xu readwrite 涓皢client/server handler 鍒嗗紑
-package remoting
+package getty
 
 import (
-	"bufio"
-	"bytes"
 	"reflect"
 )
 
@@ -32,7 +29,7 @@ import (
 
 import (
 	"github.com/apache/dubbo-go/common/logger"
-	"github.com/apache/dubbo-go/protocol/dubbo/impl"
+	"github.com/apache/dubbo-go/remoting"
 )
 
 ////////////////////////////////////////////
@@ -50,130 +47,89 @@ func NewRpcClientPackageHandler(client *Client) *RpcClientPackageHandler {
 }
 
 func (p *RpcClientPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
-	pkg := NewClientResponsePackage(data)
-	if err := pkg.ReadHeader(); err != nil {
-		originErr := perrors.Cause(err)
-		if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough {
+	//pkg := &DubboPackage{}
+	//p.client.ExchangeClient.GetPendingResponse(remoting.SequenceType())
+	resp, length, err := (p.client.codec).Decode(data)
+	//err := pkg.Unmarshal(buf, p.client)
+	if err != nil {
+		if err == hessian.ErrHeaderNotEnough || err == hessian.ErrBodyNotEnough {
 			return nil, 0, nil
 		}
-		logger.Errorf("[RpcClientPackageHandler.Read] ss:%+v, len(@data):%d) = error:%+v ", ss, len(data), err)
-		return nil, 0, perrors.WithStack(err)
-	}
-	if pkg.IsHeartBeat() {
-		// heartbeat package doesn't need deserialize
-		return pkg, pkg.GetLen(), nil
-	}
 
-	if err := impl.LoadSerializer(pkg); err != nil {
-		return nil, 0, err
-	}
+		logger.Errorf("pkg.Unmarshal(ss:%+v, len(@data):%d) = error:%+v", ss, len(data), err)
 
-	// load response
-	pendingRsp, ok := p.client.PendingResponses.Load(impl.SequenceType(pkg.GetHeader().ID))
-	if !ok {
-		return nil, 0, perrors.Errorf("client.GetPendingResopnse(%v) = nil", pkg.GetHeader().ID)
-	}
-	// set package body
-	body := impl.NewResponsePayload(pendingRsp.(*PendingResponse).response.Reply, nil, nil)
-	pkg.SetBody(body)
-	err := pkg.Unmarshal()
-	if err != nil {
-		return nil, 0, perrors.WithStack(err)
+		return nil, length, err
 	}
-	resp := pkg.Body.(*impl.ResponsePayload)
-	pkg.Err = resp.Exception
-	pkg.Body = NewResponse(resp.RspObj, resp.Attachments)
-	return pkg, pkg.GetLen(), nil
+	//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 resp, length, nil
 }
 
 func (p *RpcClientPackageHandler) Write(ss getty.Session, pkg interface{}) ([]byte, error) {
-	req, ok := pkg.(*impl.DubboPackage)
+	req, ok := pkg.(*remoting.Request)
 	if !ok {
+		logger.Errorf("illegal pkg:%+v\n", pkg)
 		return nil, perrors.New("invalid rpc request")
 	}
-	buf, err := req.Marshal()
+
+	buf, err := (p.client.codec).EncodeRequest(req)
 	if err != nil {
 		logger.Warnf("binary.Write(req{%#v}) = err{%#v}", req, perrors.WithStack(err))
 		return nil, perrors.WithStack(err)
 	}
-	return buf.Bytes(), nil
-}
 
-func NewClientResponsePackage(data []byte) *impl.DubboPackage {
-	return &impl.DubboPackage{
-		Header:  impl.DubboHeader{},
-		Service: impl.Service{},
-		Body:    &impl.ResponsePayload{},
-		Err:     nil,
-		Codec:   impl.NewDubboCodec(bufio.NewReaderSize(bytes.NewBuffer(data), len(data))),
-	}
+	return buf.Bytes(), nil
 }
 
 ////////////////////////////////////////////
 // RpcServerPackageHandler
 ////////////////////////////////////////////
 
-var (
-	rpcServerPkgHandler = &RpcServerPackageHandler{}
-)
+//var (
+//	rpcServerPkgHandler = &RpcServerPackageHandler{}
+//)
 
 // RpcServerPackageHandler ...
 type RpcServerPackageHandler struct {
+	server *Server
 }
 
-func (p *RpcServerPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
-	pkg := NewServerRequestPackage(data)
-	if err := pkg.ReadHeader(); err != nil {
-		originErr := perrors.Cause(err)
-		if originErr == hessian.ErrHeaderNotEnough || originErr == hessian.ErrBodyNotEnough {
-			return nil, 0, nil
-		}
-		return nil, 0, perrors.WithStack(err)
-	}
-
-	if pkg.IsHeartBeat() {
-		return pkg, pkg.GetLen(), nil
-	}
+func NewRpcServerPackageHandler(server *Server) *RpcServerPackageHandler {
+	return &RpcServerPackageHandler{server: server}
+}
 
-	if err := impl.LoadSerializer(pkg); err != nil {
-		return nil, 0, err
-	}
+func (p *RpcServerPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
+	req, length, err := (p.server.codec).Decode(data)
+	//resp,len, err := (*p.).DecodeResponse(buf)
 
-	err := pkg.Unmarshal()
 	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 pkg, pkg.GetLen(), nil
+
+	return req, length, err
 }
 
 func (p *RpcServerPackageHandler) Write(ss getty.Session, pkg interface{}) ([]byte, error) {
-	res, ok := pkg.(*impl.DubboPackage)
+	res, ok := pkg.(*remoting.Response)
 	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()
+
+	buf, err := (p.server.codec).EncodeResponse(res)
 	if err != nil {
 		logger.Warnf("binary.Write(res{%#v}) = err{%#v}", res, perrors.WithStack(err))
 		return nil, perrors.WithStack(err)
 	}
-	return buf.Bytes(), nil
-}
-
-// server side receive request package, just for deserialization
-func NewServerRequestPackage(data []byte) *impl.DubboPackage {
-	return &impl.DubboPackage{
-		Header:  impl.DubboHeader{},
-		Service: impl.Service{},
-		Body:    make([]interface{}, 7),
-		Err:     nil,
-		Codec:   impl.NewDubboCodec(bufio.NewReaderSize(bytes.NewBuffer(data), len(data))),
-	}
 
+	return buf.Bytes(), nil
 }