1 - 服务调用API的Proto定义

Dapr服务调用API的Proto定义

InvokeService的定义

Service Invoken API 定义在 proto文件 dapr/proto/runtime/v1/dapr.proto 中:

service Dapr {
  // Invokes a method on a remote Dapr app.
  rpc InvokeService(InvokeServiceRequest) returns (common.v1.InvokeResponse) {}
  ...
}

InvokeServiceRequest 包含一个被调用服务的ID,和通用的 InvokeRequest:

// InvokeServiceRequest represents the request message for Service invocation.
message InvokeServiceRequest {
  // Required. Callee's app id.
  string id = 1;

  // Required. message which will be delivered to callee.
  common.v1.InvokeRequest message = 3;
}

AppCallback的定义

AppCallback API 定义在 proto文件 dapr/proto/runtime/v1/appcallback.proto 中:

service AppCallback {
  // Invokes service method with InvokeRequest.
  rpc OnInvoke (common.v1.InvokeRequest) returns (common.v1.InvokeResponse) {}
  ...
}

Invoke的通用定义

Invoke的通用定义在 proto文件 dapr/proto/common/v1/common.proto 中。

InvokeRequest是用来携带数据调用方法的消息,这个消息在Dapr gRPC服务的InvokeService和AppCallback gRPC服务的OnInvoke中使用:

// InvokeRequest is the message to invoke a method with the data.
// This message is used in InvokeService of Dapr gRPC Service and OnInvoke
// of AppCallback gRPC service.
message InvokeRequest {
  // Required. method is a method name which will be invoked by caller.
  string method = 1;

  // Required. Bytes value or Protobuf message which caller sent.
  // Dapr treats Any.value as bytes type if Any.type_url is unset.
  google.protobuf.Any data = 2;

  // The type of data content.
  //
  // This field is required if data delivers http request body
  // Otherwise, this is optional.
  string content_type = 3;

  // HTTP specific fields if request conveys http-compatible request.
  //
  // This field is required for http-compatible request. Otherwise,
  // this field is optional.
  HTTPExtension http_extension = 4;
}

InvokeResponse是包括应用程序回调的数据和内容类型的响应消息,该消息在Dapr gRPC服务的InvokeService方法和AppCallback gRPC服务的OnInvoke方法中使用:

// InvokeResponse is the response message inclduing data and its content type
// from app callback.
// This message is used in InvokeService of Dapr gRPC Service and OnInvoke
// of AppCallback gRPC service.
message InvokeResponse {
  // Required. The content body of InvokeService response.
  google.protobuf.Any data = 1;

  // Required. The type of data content.
  string content_type = 2;
}

相关的消息定义

HTTPExtension 消息的定义:

// 当Dapr运行时传递HTTP内容时,HTTPExtension包括HTTP verb和querystring。
// 
// For example, when callers calls http invoke api
// POST http://localhost:3500/v1.0/invoke/<app_id>/method/<method>?query1=value1&query2=value2
// 
// Dapr runtime will parse POST as a verb and extract querystring to quersytring map.
message HTTPExtension {
  // Type of HTTP 1.1 Methods
  // RFC 7231: https://tools.ietf.org/html/rfc7231#page-24
  enum Verb {
    NONE = 0;
    GET = 1;
    HEAD = 2;
    POST = 3;
    PUT = 4;
    DELETE = 5;
    CONNECT = 6;
    OPTIONS = 7;
    TRACE = 8;
  }

  // Required. HTTP verb.
  Verb verb = 1;

  // querystring includes HTTP querystring.
  map<string, string> querystring = 2;
}

Any消息的定义:

message Any {
  string type_url = 1;

  // Must be a valid serialized protocol buffer of the above specified type.
  bytes value = 2;
}

2 - 服务调用API的golang生成代码

服务调用API的golang生成代码

从proto api定义文件生成的golang代码,被存放在dapr项目的 pkg/proto/ 目录下。

grpc服务定义

DaprServer 是 dapr 服务的服务器端API定义,包含 InvokeService方法:

// DaprServer is the server API for Dapr service.
type DaprServer interface {
	// Invokes a method on a remote Dapr app.
	InvokeService(context.Context, *InvokeServiceRequest) (*v1.InvokeResponse, error)
   ......
}

AppCallbackServer 是 AppCallback 服务的服务器端API定义,包含 OnInvoke 方法:

// AppCallbackServer is the server API for AppCallback service.
type AppCallbackServer interface {
	// Invokes service method with InvokeRequest.
	OnInvoke(context.Context, *v1.InvokeRequest) (*v1.InvokeResponse, error)
	......
}

InvokeServiceRequest的定义

https://github.com/dapr/dapr/blob/11741c6cd697e08b2e776943e61bb2e3388c85a8/pkg/proto/runtime/v1/dapr.pb.go

type InvokeServiceRequest struct {
	// Required. Callee's app id.
	Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
	// Required. message which will be delivered to callee.
	Message              *v1.InvokeRequest `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
	XXX_unrecognized     []byte            `json:"-"`
	XXX_sizecache        int32             `json:"-"`
}

InvokeRequest的定义

https://github.com/dapr/dapr/blob/de49fe260c8f7c53e146e27150faad8c0880fe90/pkg/proto/common/v1/common.pb.go

type InvokeRequest struct {
	// Required. method is a method name which will be invoked by caller.
	Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
	// Required. Bytes value or Protobuf message which caller sent.
	// Dapr treats Any.value as bytes type if Any.type_url is unset.
	Data *any.Any `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
	// The type of data content.
	//
	// This field is required if data delivers http request body
	// Otherwise, this is optional.
	ContentType string `protobuf:"bytes,3,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
	// HTTP specific fields if request conveys http-compatible request.
	//
	// This field is required for http-compatible request. Otherwise,
	// this field is optional.
	HttpExtension        *HTTPExtension `protobuf:"bytes,4,opt,name=http_extension,json=httpExtension,proto3" json:"http_extension,omitempty"`
	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
	XXX_unrecognized     []byte         `json:"-"`
	XXX_sizecache        int32          `json:"-"`
}

InvokeResponse的定义

type InvokeResponse struct {
	// Required. The content body of InvokeService response.
	Data *any.Any `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
	// Required. The type of data content.
	ContentType          string   `protobuf:"bytes,2,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

备注:只是在proto定义的字段上增加了一些 XXX_ 字段。

3 - 服务调用的go client定义

Dapr服务调用的go client定义

DaprClient

https://github.com/dapr/dapr/blob/11741c6cd697e08b2e776943e61bb2e3388c85a8/pkg/proto/runtime/v1/dapr.pb.go

// DaprClient is the client API for Dapr service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type DaprClient interface {
	// Invokes a method on a remote Dapr app.
	InvokeService(ctx context.Context, in *InvokeServiceRequest, opts ...grpc.CallOption) (*v1.InvokeResponse, error)
	......s
}

DaprClient 的实现:

type daprClient struct {
	cc *grpc.ClientConn
}

func NewDaprClient(cc *grpc.ClientConn) DaprClient {
	return &daprClient{cc}
}

func (c *daprClient) InvokeService(ctx context.Context, in *InvokeServiceRequest, opts ...grpc.CallOption) (*v1.InvokeResponse, error) {
	out := new(v1.InvokeResponse)
	err := c.cc.Invoke(ctx, "/dapr.proto.runtime.v1.Dapr/InvokeService", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

AppCallbackClient

https://github.com/dapr/dapr/blob/11741c6cd697e08b2e776943e61bb2e3388c85a8/pkg/proto/runtime/v1/appcallback.pb.go

// AppCallbackClient is the client API for AppCallback service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type AppCallbackClient interface {
	// Invokes service method with InvokeRequest.
	OnInvoke(ctx context.Context, in *v1.InvokeRequest, opts ...grpc.CallOption) (*v1.InvokeResponse, error)
	......
}

AppCallbackClient 的实现:

type appCallbackClient struct {
	cc *grpc.ClientConn
}

func NewAppCallbackClient(cc *grpc.ClientConn) AppCallbackClient {
	return &appCallbackClient{cc}
}

func (c *appCallbackClient) OnInvoke(ctx context.Context, in *v1.InvokeRequest, opts ...grpc.CallOption) (*v1.InvokeResponse, error) {
	out := new(v1.InvokeResponse)
	err := c.cc.Invoke(ctx, "/dapr.proto.runtime.v1.AppCallback/OnInvoke", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

4 - Dapr服务调用的go sdk定义

Dapr服务调用的go sdk定义

go sdk使用案例

https://github.com/dapr/go-sdk

要在另一个使用Dapr sidecar运行的服务上调用特定的方法,Dapr客户端提供了两个选项。

调用一个没有任何数据的服务:

resp, err = client.InvokeService(ctx, "service-name", "method-name") 

还有带数据调用服务:

content := &DataContent{
    ContentType: "application/json",
    Data:        []byte(`{ "id": "a123", "value": "demo", "valid": true }`)
}

resp, err := client.InvokeServiceWithContent(ctx, "service-name", "method-name", content)

go sdk提供的API

https://github.com/dapr/go-sdk/blob/d6de57c71a1d3c7ce3a3b81385609dfba18a1a18/client/invoke.go

go sdk在 client 上封装了两个方法用于服务调用,InvokeService方法用来发送不带数据的请求:

// InvokeService invokes service without raw data ([]byte).
func (c *GRPCClient) InvokeService(ctx context.Context, serviceID, method string) (out []byte, err error) {
...
}

InvokeServiceWithContent方法用来发现带数据的请求:

// InvokeServiceWithContent invokes service without content (data + content type).
func (c *GRPCClient) InvokeServiceWithContent(ctx context.Context, serviceID, method string, content *DataContent) (out []byte, err error) {
......
}

DataContent 的定义:

// DataContent the service invocation content
type DataContent struct {
	// Data is the input data
	Data []byte
	// ContentType is the type of the data content
	ContentType string
}