Skip to content
Snippets Groups Projects
Commit 6a75b696 authored by LaurenceLiZhixin's avatar LaurenceLiZhixin
Browse files

ftr: add triple support

parent f457be69
No related branches found
No related tags found
No related merge requests found
......@@ -14,6 +14,7 @@ require (
github.com/creasty/defaults v1.5.1
github.com/dubbogo/go-zookeeper v1.0.2
github.com/dubbogo/gost v1.11.0
github.com/dubbogo/triple v0.0.0-20210301083516-185f5a3b1234 // indirect
github.com/elazarl/go-bindata-assetfs v1.0.0 // indirect
github.com/emicklei/go-restful/v3 v3.4.0
github.com/frankban/quicktest v1.4.1 // indirect
......@@ -44,7 +45,7 @@ require (
go.uber.org/atomic v1.7.0
go.uber.org/zap v1.16.0
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 // indirect
google.golang.org/grpc v1.26.0
google.golang.org/grpc v1.31.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.16.9
k8s.io/apimachinery v0.16.9
......
This diff is collapsed.
/*
* 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 dubbo3
import (
"sync"
)
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"
)
// DubboExporter is dubbo3 service exporter.
type Dubbo3Exporter struct {
protocol.BaseExporter
}
// NewDubbo3Exporter get a Dubbo3Exporter.
func NewDubbo3Exporter(key string, invoker protocol.Invoker, exporterMap *sync.Map) *Dubbo3Exporter {
return &Dubbo3Exporter{
BaseExporter: *protocol.NewBaseExporter(key, invoker, exporterMap),
}
}
// Unexport unexport dubbo3 service exporter.
func (de *Dubbo3Exporter) Unexport() {
url := de.GetInvoker().GetUrl()
serviceId := url.GetParam(constant.BEAN_NAME_KEY, "")
interfaceName := url.GetParam(constant.INTERFACE_KEY, "")
de.BaseExporter.Unexport()
err := common.ServiceMap.UnRegister(interfaceName, DUBBO3, serviceId)
if err != nil {
logger.Errorf("[DubboExporter.Unexport] error: %v", err)
}
}
/*
* 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 dubbo3
import (
"context"
"reflect"
"strconv"
"strings"
"sync"
"time"
)
import (
hessian2 "github.com/apache/dubbo-go-hessian2"
)
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"
invocation_impl "github.com/apache/dubbo-go/protocol/invocation"
dubbo3 "github.com/dubbogo/triple/pkg/triple"
)
// Dubbo3Invoker is implement of protocol.Invoker. A dubboInvoker refer to one service and ip.
type Dubbo3Invoker struct {
protocol.BaseInvoker
// the net layer client, it is focus on network communication.
client *dubbo3.TripleClient
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
}
// NewDubbo3Invoker constructor
func NewDubbo3Invoker(url *common.URL) (*Dubbo3Invoker, error) {
requestTimeout := config.GetConsumerConfig().RequestTimeout
requestTimeoutStr := url.GetParam(constant.TIMEOUT_KEY, config.GetConsumerConfig().Request_Timeout)
if t, err := time.ParseDuration(requestTimeoutStr); err == nil {
requestTimeout = t
}
key := url.GetParam(constant.BEAN_NAME_KEY, "")
consumerService := config.GetConsumerService(key)
client, err := dubbo3.NewTripleClient(url, consumerService)
if err != nil {
return nil, err
}
return &Dubbo3Invoker{
BaseInvoker: *protocol.NewBaseInvoker(url),
client: client,
reqNum: 0,
timeout: requestTimeout,
}, nil
}
// Invoke call remoting.
func (di *Dubbo3Invoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result {
var (
result protocol.RPCResult
)
in := make([]reflect.Value, 0, 16)
in = append(in, reflect.ValueOf(ctx))
if len(invocation.ParameterValues()) > 0 {
in = append(in, invocation.ParameterValues()...)
}
methodName := invocation.MethodName()
method := di.client.Invoker.MethodByName(methodName)
res := method.Call(in)
result.Rest = res[0]
// check err
if !res[1].IsNil() {
result.Err = res[1].Interface().(error)
} else {
_ = hessian2.ReflectResponse(res[0], invocation.Reply())
}
return &result
}
// get timeout including methodConfig
func (di *Dubbo3Invoker) getTimeout(invocation *invocation_impl.RPCInvocation) time.Duration {
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
}
// IsAvailable check if invoker is available, now it is useless
func (di *Dubbo3Invoker) IsAvailable() bool {
return di.client.IsAvailable()
}
// Destroy destroy dubbo3 client invoker.
func (di *Dubbo3Invoker) Destroy() {
di.quitOnce.Do(func() {
for {
if di.reqNum == 0 {
di.reqNum = -1
logger.Infof("dubboInvoker is destroyed,url:{%s}", di.GetUrl().Key())
di.BaseInvoker.Destroy()
if di.client != nil {
di.client.Close()
di.client = nil
}
break
}
logger.Warnf("DubboInvoker is to be destroyed, wait {%v} req end,url:{%s}", di.reqNum, di.GetUrl().Key())
time.Sleep(1 * time.Second)
}
})
}
/*
* 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 dubbo3
import (
"fmt"
"reflect"
"sync"
)
import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/constant"
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/common/logger"
"github.com/apache/dubbo-go/config"
"github.com/apache/dubbo-go/protocol"
dubbo3 "github.com/dubbogo/triple/pkg/triple"
"google.golang.org/grpc"
)
const (
// DUBBO3 is dubbo3 protocol name
DUBBO3 = "dubbo3"
)
func init() {
extension.SetProtocol(DUBBO3, GetProtocol)
}
var (
dubbo3Protocol *Dubbo3Protocol
)
// It support dubbo protocol. It implements Protocol interface for dubbo protocol.
type Dubbo3Protocol struct {
protocol.BaseProtocol
serverLock sync.Mutex
serverMap map[string]*dubbo3.TripleServer // It is store relationship about serviceKey(group/interface:version) and ExchangeServer
}
// NewDubbo3Protocol create a dubbo protocol.
func NewDubbo3Protocol() *Dubbo3Protocol {
return &Dubbo3Protocol{
BaseProtocol: protocol.NewBaseProtocol(),
serverMap: make(map[string]*dubbo3.TripleServer),
}
}
// Export export dubbo3 service.
func (dp *Dubbo3Protocol) Export(invoker protocol.Invoker) protocol.Exporter {
url := invoker.GetUrl()
serviceKey := url.ServiceKey()
exporter := NewDubbo3Exporter(serviceKey, invoker, dp.ExporterMap())
dp.SetExporterMap(serviceKey, exporter)
logger.Infof("Export service: %s", url.String())
// start server
dp.openServer(url)
return exporter
}
// Refer create dubbo3 service reference.
func (dp *Dubbo3Protocol) Refer(url *common.URL) protocol.Invoker {
invoker, err := NewDubbo3Invoker(url)
if err != nil {
logger.Errorf("Refer url = %+v, with error = %s", *url, err.Error())
return nil
}
dp.SetInvokers(invoker)
logger.Infof("Refer service: %s", url.String())
return invoker
}
// Destroy destroy dubbo3 service.
func (dp *Dubbo3Protocol) Destroy() {
dp.BaseProtocol.Destroy()
// stop server
for key, server := range dp.serverMap {
delete(dp.serverMap, key)
server.Stop()
}
}
// Dubbo3GrpcService is gRPC service
type Dubbo3GrpcService interface {
// SetProxyImpl sets proxy.
SetProxyImpl(impl protocol.Invoker)
// GetProxyImpl gets proxy.
GetProxyImpl() protocol.Invoker
// ServiceDesc gets an RPC service's specification.
ServiceDesc() *grpc.ServiceDesc
}
// openServer open a dubbo3 server
func (dp *Dubbo3Protocol) openServer(url *common.URL) {
_, ok := dp.serverMap[url.Location]
if ok {
return
}
_, ok = dp.ExporterMap().Load(url.ServiceKey())
if !ok {
panic("[DubboProtocol]" + url.Key() + "is not existing")
}
dp.serverLock.Lock()
defer dp.serverLock.Unlock()
_, ok = dp.serverMap[url.Location]
if ok {
return
}
key := url.GetParam(constant.BEAN_NAME_KEY, "")
service := config.GetProviderService(key)
m, ok := reflect.TypeOf(service).MethodByName("SetProxyImpl")
if !ok {
panic("method SetProxyImpl is necessary for grpc service")
}
exporter, _ := dubbo3Protocol.ExporterMap().Load(url.ServiceKey())
if exporter == nil {
panic(fmt.Sprintf("no exporter found for servicekey: %v", url.ServiceKey()))
}
invoker := exporter.(protocol.Exporter).GetInvoker()
if invoker == nil {
panic(fmt.Sprintf("no invoker found for servicekey: %v", url.ServiceKey()))
}
in := []reflect.Value{reflect.ValueOf(service)}
in = append(in, reflect.ValueOf(invoker))
m.Func.Call(in)
srv := dubbo3.NewTripleServer(url, service.(dubbo3.Dubbo3GrpcService))
dp.serverMap[url.Location] = srv
srv.Start()
}
// GetProtocol get a single dubbo3 protocol.
func GetProtocol() protocol.Protocol {
logger.Warn("GetProtocol")
if dubbo3Protocol == nil {
dubbo3Protocol = NewDubbo3Protocol()
}
return dubbo3Protocol
}
# 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.
grpc-gen:
protoc -I ./ helloworld.proto --go_out=plugins=grpc:.
dubbo3-gen:
protoc -I ./ helloworld.proto --dubbo3_out=plugins=grpc+dubbo:.
/*
* 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.
*/
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: helloworld.proto
package main
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
import (
"github.com/apache/dubbo-go/protocol"
dgrpc "github.com/apache/dubbo-go/protocol/grpc"
"github.com/apache/dubbo-go/protocol/invocation"
dubbo3 "github.com/dubbogo/triple/pkg/triple"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// The request message containing the user's name.
type HelloRequest struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *HelloRequest) Reset() { *m = HelloRequest{} }
func (m *HelloRequest) String() string { return proto.CompactTextString(m) }
func (*HelloRequest) ProtoMessage() {}
func (*HelloRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_17b8c58d586b62f2, []int{0}
}
func (m *HelloRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_HelloRequest.Unmarshal(m, b)
}
func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic)
}
func (m *HelloRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_HelloRequest.Merge(m, src)
}
func (m *HelloRequest) XXX_Size() int {
return xxx_messageInfo_HelloRequest.Size(m)
}
func (m *HelloRequest) XXX_DiscardUnknown() {
xxx_messageInfo_HelloRequest.DiscardUnknown(m)
}
var xxx_messageInfo_HelloRequest proto.InternalMessageInfo
func (m *HelloRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
// The response message containing the greetings
type HelloReply struct {
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *HelloReply) Reset() { *m = HelloReply{} }
func (m *HelloReply) String() string { return proto.CompactTextString(m) }
func (*HelloReply) ProtoMessage() {}
func (*HelloReply) Descriptor() ([]byte, []int) {
return fileDescriptor_17b8c58d586b62f2, []int{1}
}
func (m *HelloReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_HelloReply.Unmarshal(m, b)
}
func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic)
}
func (m *HelloReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_HelloReply.Merge(m, src)
}
func (m *HelloReply) XXX_Size() int {
return xxx_messageInfo_HelloReply.Size(m)
}
func (m *HelloReply) XXX_DiscardUnknown() {
xxx_messageInfo_HelloReply.DiscardUnknown(m)
}
var xxx_messageInfo_HelloReply proto.InternalMessageInfo
func (m *HelloReply) GetMessage() string {
if m != nil {
return m.Message
}
return ""
}
func init() {
proto.RegisterType((*HelloRequest)(nil), "main.HelloRequest")
proto.RegisterType((*HelloReply)(nil), "main.HelloReply")
}
func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) }
var fileDescriptor_17b8c58d586b62f2 = []byte{
// 185 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9,
0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xc9, 0x4d,
0xcc, 0xcc, 0x53, 0x52, 0xe2, 0xe2, 0xf1, 0x00, 0xc9, 0x04, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97,
0x08, 0x09, 0x71, 0xb1, 0xe4, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x81,
0xd9, 0x4a, 0x6a, 0x5c, 0x5c, 0x50, 0x35, 0x05, 0x39, 0x95, 0x42, 0x12, 0x5c, 0xec, 0xb9, 0xa9,
0xc5, 0xc5, 0x89, 0xe9, 0x30, 0x45, 0x30, 0xae, 0x91, 0x2d, 0x17, 0xbb, 0x7b, 0x51, 0x6a, 0x6a,
0x49, 0x6a, 0x91, 0x90, 0x11, 0x17, 0x47, 0x70, 0x62, 0x25, 0x58, 0x97, 0x90, 0x90, 0x1e, 0xc8,
0x26, 0x3d, 0x64, 0x6b, 0xa4, 0x04, 0x50, 0xc4, 0x0a, 0x72, 0x2a, 0x95, 0x18, 0x9c, 0xcc, 0xb8,
0xa4, 0x33, 0xf3, 0xf5, 0xd2, 0x8b, 0x0a, 0x92, 0xf5, 0x52, 0x2b, 0x12, 0x73, 0x0b, 0x72, 0x52,
0x8b, 0xf5, 0x10, 0xae, 0x76, 0xe2, 0x07, 0x2b, 0x0e, 0x07, 0xb1, 0x03, 0x40, 0x1e, 0x08, 0x60,
0x5c, 0xc4, 0xc4, 0xec, 0xe1, 0x13, 0x9e, 0xc4, 0x06, 0xf6, 0x8f, 0x31, 0x20, 0x00, 0x00, 0xff,
0xff, 0xd2, 0x16, 0x5f, 0x34, 0xe3, 0x00, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// GreeterClient is the client API for Greeter service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type GreeterClient interface {
// Sends a greeting
SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
}
type greeterClient struct {
cc grpc.ClientConnInterface
}
func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient {
return &greeterClient{cc}
}
func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
out := new(HelloReply)
err := c.cc.Invoke(ctx, "/main.Greeter/SayHello", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// GreeterServer is the server API for Greeter service.
type GreeterServer interface {
// Sends a greeting
SayHello(context.Context, *HelloRequest) (*HelloReply, error)
}
// UnimplementedGreeterServer can be embedded to have forward compatible implementations.
type UnimplementedGreeterServer struct {
}
func (*UnimplementedGreeterServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
}
func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
s.RegisterService(&_Greeter_serviceDesc, srv)
}
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(HelloRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GreeterServer).SayHello(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/main.Greeter/SayHello",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Greeter_serviceDesc = grpc.ServiceDesc{
ServiceName: "main.Greeter",
HandlerType: (*GreeterServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SayHello",
Handler: _Greeter_SayHello_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "helloworld.proto",
}
type greeterDubbo3Client struct {
cc *dubbo3.TripleConn
}
func NewGreeterDubbo3Client(cc *dubbo3.TripleConn) GreeterClient {
return &greeterDubbo3Client{cc}
}
func (c *greeterDubbo3Client) SayHello(ctx context.Context, in *HelloRequest, opt ...grpc.CallOption) (*HelloReply, error) {
out := new(HelloReply)
err := c.cc.Invoke(ctx, "/protobuf.Greeter/SayHello", in, out)
if err != nil {
return nil, err
}
return out, nil
}
// GreeterClientImpl is the client API for Greeter service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type GreeterClientImpl struct {
// Sends a greeting
SayHello func(ctx context.Context, in *HelloRequest, out *HelloReply) error
}
func (c *GreeterClientImpl) Reference() string {
return "greeterImpl"
}
func (c *GreeterClientImpl) GetDubboStub(cc *dubbo3.TripleConn) GreeterClient {
return NewGreeterDubbo3Client(cc)
}
type GreeterProviderBase struct {
proxyImpl protocol.Invoker
}
func (s *GreeterProviderBase) SetProxyImpl(impl protocol.Invoker) {
s.proxyImpl = impl
}
func (s *GreeterProviderBase) GetProxyImpl() protocol.Invoker {
return s.proxyImpl
}
func _DUBBO_Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(HelloRequest)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dgrpc.DubboGrpcService)
args := []interface{}{}
args = append(args, in)
invo := invocation.NewRPCInvocation("SayHello", args, nil)
if interceptor == nil {
result := base.GetProxyImpl().Invoke(ctx, invo)
return result.Result(), result.Error()
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/main.Greeter/SayHello",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.GetProxyImpl().Invoke(context.Background(), invo)
return result.Result(), result.Error()
}
return interceptor(ctx, in, info, handler)
}
func (s *GreeterProviderBase) ServiceDesc() *grpc.ServiceDesc {
return &grpc.ServiceDesc{
ServiceName: "main.Greeter",
HandlerType: (*GreeterServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SayHello",
Handler: _DUBBO_Greeter_SayHello_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "helloworld.proto",
}
}
/*
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.
*/
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package main;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
/*
* 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 main
import (
"io/ioutil"
"os"
)
import (
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/protoc-gen-go/generator"
_ "github.com/golang/protobuf/protoc-gen-go/grpc"
)
import (
_ "github.com/apache/dubbo-go/protocol/dubbo3/protoc-gen-dubbo3/plugin/dubbo3"
)
func main() {
// Begin by allocating a generate. The request and response structures are stored there
// so we can do error handling easily - the response structure contains the field to
// report failure.
g := generator.New()
data, err := ioutil.ReadAll(os.Stdin)
if err != nil {
g.Error(err, "reading input")
}
if err := proto.Unmarshal(data, g.Request); err != nil {
g.Error(err, "parsing input proto")
}
if len(g.Request.FileToGenerate) == 0 {
g.Fail("no files to generate")
}
g.CommandLineParameters(g.Request.GetParameter())
// Create a wrapped version of the Descriptors and EnumDescriptors that
// point to the file that defines them.
g.WrapTypes()
g.SetPackageNames()
g.BuildTypeNameMap()
g.GenerateAllFiles()
// Send back the results.
data, err = proto.Marshal(g.Response)
if err != nil {
g.Error(err, "failed to marshal output proto")
}
_, err = os.Stdout.Write(data)
if err != nil {
g.Error(err, "failed to write output proto")
}
}
/*
* 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 plugin for protobuf.
package dubbo
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dubbo
import (
"fmt"
"strconv"
"strings"
)
import (
pb "github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/golang/protobuf/protoc-gen-go/generator"
)
// generatedCodeVersion indicates a version of the generated codes.
// It is incremented whenever an incompatibility between the generated codes and
// the grpc package is introduced; the generated codes references
// a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion).
const generatedCodeVersion = 4
// Paths for packages used by codes generated in this file,
// relative to the import_prefix of the generator.Generator.
const (
contextPkgPath = "context"
grpcPkgPath = "google.golang.org/grpc"
codePkgPath = "google.golang.org/grpc/codes"
statusPkgPath = "google.golang.org/grpc/status"
)
func init() {
generator.RegisterPlugin(new(dubboGrpc))
}
// grpc is an implementation of the Go protocol buffer compiler's
// plugin architecture. It generates bindings for gRPC-dubbo support.
type dubboGrpc struct {
gen *generator.Generator
}
// Name returns the name of this plugin, "grpc".
func (g *dubboGrpc) Name() string {
return "dubbo"
}
// The names for packages imported in the generated codes.
// They may vary from the final path component of the import path
// if the name is used by other packages.
var (
contextPkg string
grpcPkg string
)
// Init initializes the plugin.
func (g *dubboGrpc) Init(gen *generator.Generator) {
g.gen = gen
}
// Given a type name defined in a .proto, return its object.
// Also record that we're using it, to guarantee the associated import.
func (g *dubboGrpc) objectNamed(name string) generator.Object {
g.gen.RecordTypeUse(name)
return g.gen.ObjectNamed(name)
}
// Given a type name defined in a .proto, return its name as we will print it.
func (g *dubboGrpc) typeName(str string) string {
return g.gen.TypeName(g.objectNamed(str))
}
// P forwards to g.gen.P.
func (g *dubboGrpc) P(args ...interface{}) { g.gen.P(args...) }
// Generate generates codes for the services in the given file.
// be consistent with grpc plugin
func (g *dubboGrpc) Generate(file *generator.FileDescriptor) {
if len(file.FileDescriptorProto.Service) == 0 {
return
}
contextPkg = string(g.gen.AddImport(contextPkgPath))
grpcPkg = string(g.gen.AddImport(grpcPkgPath))
for i, service := range file.FileDescriptorProto.Service {
g.generateService(file, service, i)
}
}
// GenerateImports generates the import declaration for this file.
func (g *dubboGrpc) GenerateImports(file *generator.FileDescriptor) {
g.P("import (")
g.P(`dgrpc "github.com/apache/dubbo-go/protocol/grpc"`)
g.P(`"github.com/apache/dubbo-go/protocol/invocation"`)
g.P(`"github.com/apache/dubbo-go/protocol"`)
g.P(`dubbo3 "github.com/dubbogo/triple/pkg/triple"`)
g.P(` ) `)
}
func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }
// deprecationComment is the standard comment added to deprecated
// messages, fields, enums, and enum values.
var deprecationComment = "// Deprecated: Do not use."
// generateService generates all the codes for the named service.
func (g *dubboGrpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) {
path := fmt.Sprintf("6,%d", index) // 6 means service.
origServName := service.GetName()
fullServName := origServName
if pkg := file.GetPackage(); pkg != "" {
fullServName = pkg + "." + fullServName
}
servName := generator.CamelCase(origServName)
lowerServName := strings.ToLower(servName)
lowerFrontServeName := strings.ToLower(servName[:1]) + servName[1:]
g.P(fmt.Sprintf("type %sDubbo3Client struct {", lowerServName))
g.P(fmt.Sprintf("cc *dubbo3.TripleConn"))
g.P("}")
g.P(fmt.Sprintf("func New%sDubbo3Client (cc *dubbo3.TripleConn) %sClient {", servName, servName))
g.P(fmt.Sprintf("return &%sDubbo3Client{cc}", lowerServName))
g.P(fmt.Sprintf("}"))
for _, method := range service.Method {
inputTypeNames := strings.Split(method.GetInputType(), ".")
inputTypeName := inputTypeNames[len(inputTypeNames)-1]
outputTypeNames := strings.Split(method.GetOutputType(), ".")
outputTypeName := outputTypeNames[len(outputTypeNames)-1]
if method.GetServerStreaming() || method.GetClientStreaming() {
//now we only support two way streaming
g.P(fmt.Sprintf("func (c *%sDubbo3Client) %s(ctx %s.Context,opt ...grpc.CallOption) (%s, error) {",
lowerServName, method.GetName(), contextPkg, servName+"_"+method.GetName()+"Client"))
g.P(fmt.Sprintf("stream, err := c.cc.NewStream(ctx, \"/%s/%s\", opt...)", fullServName, method.GetName()))
g.P("if err != nil {")
g.P("return nil, err")
g.P("}")
g.P(fmt.Sprintf("x := &%s%sClient{stream}", lowerFrontServeName, method.GetName()))
g.P("return x, nil")
g.P("}")
continue
}
// unary rpc method client
g.P(fmt.Sprintf("func (c *%sDubbo3Client) %s(ctx %s.Context, in *%s, opt ...grpc.CallOption) (*%s, error) {",
lowerServName, method.GetName(), contextPkg, inputTypeName, outputTypeName))
g.P(fmt.Sprintf("out := new(%s)", outputTypeName))
g.P(fmt.Sprintf("err := c.cc.Invoke(ctx, \"/%s/%s\", in, out)", fullServName, method.GetName()))
g.P("if err != nil {")
g.P("return nil, err")
g.P("}")
g.P("return out, nil")
g.P("}")
}
deprecated := service.GetOptions().GetDeprecated()
g.P()
g.P(fmt.Sprintf(`// %sClientImpl is the client API for %s service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.`, servName, servName))
// Client interface.
if deprecated {
g.P("//")
g.P(deprecationComment)
}
dubboSrvName := servName + "ClientImpl"
g.P("type ", dubboSrvName, " struct {")
for i, method := range service.Method {
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
if method.GetOptions().GetDeprecated() {
g.P("//")
g.P(deprecationComment)
}
g.P(g.generateClientSignature(servName, method))
}
g.P("}")
g.P()
// NewClient factory.
if deprecated {
g.P(deprecationComment)
}
// add Reference method
//func (u *GrpcGreeterImpl) Reference() string {
// return "GrpcGreeterImpl"
//}
g.P("func (c *", dubboSrvName, ") ", " Reference() string ", "{")
g.P(`return "`, unexport(servName), `Impl"`)
g.P("}")
g.P()
// add GetDubboStub method
// func (u *GrpcGreeterImpl) GetDubboStub(cc *dubbo3.TripleConn) GreeterClient {
// return NewGreeterClient(cc)
//}
g.P("func (c *", dubboSrvName, ") ", " GetDubboStub(cc *dubbo3.TripleConn) ", servName, "Client {")
g.P(`return New`, servName, `Dubbo3Client(cc)`)
g.P("}")
g.P()
// Server interface.
serverType := servName + "ProviderBase"
g.P("type ", serverType, " struct {")
g.P("proxyImpl protocol.Invoker")
g.P("}")
g.P()
// add set method
//func (g *GreeterProviderBase) SetProxyImpl(impl protocol.Invoker) {
// g.proxyImpl = impl
//}
g.P("func (s *", serverType, ") SetProxyImpl(impl protocol.Invoker) {")
g.P(`s.proxyImpl = impl`)
g.P("}")
g.P()
// return get method
g.P("func (s *", serverType, ") GetProxyImpl() protocol.Invoker {")
g.P(`return s.proxyImpl`)
g.P("}")
g.P()
// add handler
var handlerNames []string
for _, method := range service.Method {
hname := g.generateServerMethod(servName, fullServName, method)
handlerNames = append(handlerNames, hname)
}
grpcserverType := servName + "Server"
// return service desc
g.P("func (s *", serverType, ") ServiceDesc() *grpc.ServiceDesc {")
g.P(`return &grpc.ServiceDesc{`)
g.P("ServiceName: ", strconv.Quote(fullServName), ",")
g.P("HandlerType: (*", grpcserverType, ")(nil),")
g.P("Methods: []", grpcPkg, ".MethodDesc{")
for i, method := range service.Method {
if method.GetServerStreaming() || method.GetClientStreaming() {
continue
}
g.P("{")
g.P("MethodName: ", strconv.Quote(method.GetName()), ",")
g.P("Handler: ", handlerNames[i], ",")
g.P("},")
}
g.P("},")
g.P("Streams: []", grpcPkg, ".StreamDesc{")
for i, method := range service.Method {
if !method.GetClientStreaming() && !method.GetServerStreaming() {
continue
}
g.P("{")
g.P("StreamName: ", strconv.Quote(method.GetName()), ",")
g.P("Handler: ", handlerNames[i], ",")
if method.GetServerStreaming() {
g.P("ServerStreams: true,")
}
if method.GetClientStreaming() {
g.P("ClientStreams: true,")
}
g.P("},")
}
g.P("},")
g.P("Metadata: \"", file.GetName(), "\",")
g.P("}")
g.P("}")
g.P()
}
// generateClientSignature returns the client-side signature for a method.
func (g *dubboGrpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
methName := generator.CamelCase(origMethName)
//if reservedClientName[methName] {
// methName += "_"
//}
reqArg := ", in *" + g.typeName(method.GetInputType())
if method.GetClientStreaming() {
reqArg = ""
}
respName := "out *" + g.typeName(method.GetOutputType())
if method.GetServerStreaming() || method.GetClientStreaming() {
respName = servName + "_" + generator.CamelCase(origMethName) + "Client"
return fmt.Sprintf("%s func(ctx %s.Context%s) (%s, error)", methName, contextPkg, reqArg, respName)
}
return fmt.Sprintf("%s func(ctx %s.Context%s, %s) error", methName, contextPkg, reqArg, respName)
}
func (g *dubboGrpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) {
}
func (g *dubboGrpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string {
methName := generator.CamelCase(method.GetName())
hname := fmt.Sprintf("_DUBBO_%s_%s_Handler", servName, methName)
inType := g.typeName(method.GetInputType())
if !method.GetServerStreaming() && !method.GetClientStreaming() {
g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {")
g.P("in := new(", inType, ")")
g.P("if err := dec(in); err != nil { return nil, err }")
g.P("base := srv.(dgrpc.DubboGrpcService)")
g.P("args := []interface{}{}")
g.P("args = append(args, in)")
g.P(`invo := invocation.NewRPCInvocation("`, methName, `", args, nil)`)
g.P("if interceptor == nil {")
g.P("result := base.GetProxyImpl().Invoke(ctx, invo)")
g.P("return result.Result(), result.Error()")
g.P("}")
g.P("info := &", grpcPkg, ".UnaryServerInfo{")
g.P("Server: srv,")
g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",")
g.P("}")
g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {")
g.P("result := base.GetProxyImpl().Invoke(context.Background(), invo)")
g.P("return result.Result(), result.Error()")
g.P("}")
g.P("return interceptor(ctx, in, info, handler)")
g.P("}")
g.P()
return hname
}
// streaming rpc
streamType := unexport(servName) + methName + "Server"
g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {")
g.P("_, ok := srv.(dgrpc.DubboGrpcService)")
g.P(`invo := invocation.NewRPCInvocation("`, methName, `", nil, nil)`)
g.P("if !ok {")
g.P("fmt.Println(invo)")
g.P("}")
if !method.GetClientStreaming() {
g.P("m := new(", inType, ")")
g.P("if err := stream.RecvMsg(m); err != nil { return err }")
g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})")
} else {
g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})")
}
g.P("}")
g.P()
return hname
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment