Skip to content

Commit

Permalink
feat(prob): support protocol probing
Browse files Browse the repository at this point in the history
  • Loading branch information
whalecold committed May 15, 2024
1 parent e45a62c commit eec94d0
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 0 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,39 @@ service EchoService {
}
```

### 协议嗅探

一个端口支持同时接受 dubbo 和 kitex 原生协议的请求,只需要在初始化 server 的时候加上组件即可,示例如下:
```
import (
"github.com/cloudwego/kitex/server"
dubbo "github.com/kitex-contrib/codec-dubbo/pkg"
hello "demo-server/kitex_gen/hello/greetservice"
"log"
"net"
)
func main() {
// 指定服务端将要监听的地址
addr, _ := net.ResolveTCPAddr("tcp", ":21000")
svr := hello.NewServer(new(GreetServiceImpl),
server.WithServiceAddr(addr),
// 配置 DubboCodec
server.WithTransHandlerFactory(dubbo.NewSvrTransHandlerFactory(
// 配置 Kitex 服务所对应的 Java Interface. 其他 dubbo 客户端和 kitex 客户端可以通过这个名字进行调用。
dubbo.WithJavaClassName("org.cloudwego.kitex.samples.api.GreetProvider"),
)),
)
err := svr.Run()
if err != nil {
log.Println(err.Error())
}
}
```

### 异常处理

**codec-dubbo** 将异常定义为实现了以下接口的错误,你可以像处理错误一样处理 java 中的异常:
Expand Down
31 changes: 31 additions & 0 deletions README_ENG.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,37 @@ service EchoService {
}
```
### Protocol Probing
Simultaneous support Dubbo and Thrift protocols, example:
```
import (
"github.com/cloudwego/kitex/server"
dubbo "github.com/kitex-contrib/codec-dubbo/pkg"
hello "demo-server/kitex_gen/hello/greetservice"
"log"
"net"
)
func main() {
addr, _ := net.ResolveTCPAddr("tcp", ":21000")
svr := hello.NewServer(new(GreetServiceImpl),
server.WithServiceAddr(addr),
// 配置 DubboCodec
server.WithTransHandlerFactory(dubbo.NewSvrTransHandlerFactory(
dubbo.WithJavaClassName("org.cloudwego.kitex.samples.api.GreetProvider"),
)),
)
err := svr.Run()
if err != nil {
log.Println(err.Error())
}
}
```
### Exception Handling
**codec-dubbo** defines exceptions as **error** that implement the following interface. You can handle exceptions in Java as you could handle **error** in Go:
Expand Down
82 changes: 82 additions & 0 deletions pkg/server_trans_handler_factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package dubbo

import (
"context"
"errors"
"net"

"github.com/cloudwego/kitex/pkg/endpoint"
"github.com/cloudwego/kitex/pkg/remote"
"github.com/cloudwego/kitex/pkg/remote/trans/detection"
"github.com/cloudwego/kitex/pkg/remote/trans/netpoll"
"github.com/cloudwego/kitex/pkg/remote/trans/nphttp2"
cnetpoll "github.com/cloudwego/netpoll"

"github.com/kitex-contrib/codec-dubbo/pkg/dubbo_spec"
)

// NewSvrTransHandlerFactory the factory expand the implementation of DetectableServerTransHandler for
// hessian protocol to support the dubbo protocol probing.
func NewSvrTransHandlerFactory(opts ...Option) remote.ServerTransHandlerFactory {
return detection.NewSvrTransHandlerFactory(netpoll.NewSvrTransHandlerFactory(),
nphttp2.NewSvrTransHandlerFactory(),
&svrTransHandlerFactory{
codec: NewDubboCodec(opts...),
ServerTransHandlerFactory: netpoll.NewSvrTransHandlerFactory(),
})
}

type svrTransHandlerFactory struct {
remote.ServerTransHandlerFactory
// the codec should be set with dubbo codec to keep consistent
// with the function ProtocolMatch.
codec remote.Codec
}

func (f *svrTransHandlerFactory) NewTransHandler(opt *remote.ServerOption) (remote.ServerTransHandler, error) {
sourceCodec := opt.Codec
opt.Codec = f.codec
defer func() {
// just set the handler with dubbo codec and restore the source codec
opt.Codec = sourceCodec
}()

handler, err := f.ServerTransHandlerFactory.NewTransHandler(opt)
if err != nil {
return nil, err
}
return &svrTransHandler{
ServerTransHandler: handler,
}, nil
}

type svrTransHandler struct {
remote.ServerTransHandler
}

func (svr *svrTransHandler) ProtocolMatch(ctx context.Context, conn net.Conn) (err error) {
// Check the validity of client preface.
npReader := conn.(interface{ Reader() cnetpoll.Reader }).Reader()
// read at most avoid block
header, err := npReader.Peek(dubbo_spec.HEADER_SIZE)
if err != nil {
return err
}
if header[0] == dubbo_spec.MAGIC_HIGH && header[1] == dubbo_spec.MAGIC_LOW {
return nil
}
return errors.New("error protocol not match hessian")
}

func (svr *svrTransHandler) GracefulShutdown(ctx context.Context) error {
if g, ok := svr.ServerTransHandler.(remote.GracefulShutdown); ok {
g.GracefulShutdown(ctx)
}
return nil
}
func (svr *svrTransHandler) SetInvokeHandleFunc(inkHdlFunc endpoint.Endpoint) {
if s, ok := svr.ServerTransHandler.(remote.InvokeHandleFuncSetter); ok {
s.SetInvokeHandleFunc(inkHdlFunc)
}
return
}

0 comments on commit eec94d0

Please sign in to comment.