apache / dubbo-js

The Typescript implementation of Apache Dubbo. An RPC and microservice framework for Node.js and Web development.
https://dubbo.apache.org/
Apache License 2.0
760 stars 161 forks source link

dubbo3 - stub模块 #302

Open hufeng opened 1 year ago

hufeng commented 1 year ago

目标

TODO

creasy2010 commented 1 year ago

同步下目前进展: 已实现通过引入protoc获取pb文件“ast”( protoc --plugin=./protoc-scene-dubbojs_proto --ts_proto_out=. ./simple.proto);然后单元测试通过ast文件进行处理; 具体任务如下:

接下来需讨论以下示例生成node client代码标准: ··· syntax = "proto3";

option java_multiple_files = true; option java_package = "org.apache.dubbo.demo"; option java_outer_classname = "DemoServiceProto"; option objc_class_prefix = "DEMOSRV";

package demoservice;

// The demo service definition. service DemoService { 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; }

···

zhangjin-007 commented 1 year ago

东哥,你的repo 我直接拉么?

hufeng commented 1 year ago

grpc 生成的client stub service的 代码逻辑:

// The greeting service definition.
var GreeterService = exports.GreeterService = {
  // Sends a greeting
sayHello: {
    path: '/helloworld.Greeter/SayHello',
    requestStream: false,
    responseStream: false,
    requestType: helloworld_pb.HelloRequest,
    responseType: helloworld_pb.HelloReply,
    requestSerialize: serialize_helloworld_HelloRequest,
    requestDeserialize: deserialize_helloworld_HelloRequest,
    responseSerialize: serialize_helloworld_HelloReply,
    responseDeserialize: deserialize_helloworld_HelloReply,
  },
};
exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService);

针对dubbo-js设计: 我建议这块的设计仍然可以参考dubbo-js/dubbo2分支的proxyservice的设计,对于client方invoke调用来说核心的是两点,

还有序列话模块的部分,我们是不是应该设计出一个独立的encode和decode的能力,不跟着具体的生成的rpc的stub代码走

其他同学 补充讨论 ~~~

hufeng commented 1 year ago

针对上面思考,我初步的想法是,

service DemoService {
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;
}

对应的client stub service

// generate request type
export interface HelloRequest {
  name:string
}

// generate response type
export interface HelloReply {
  message: string
}

// generate service interface
export interface IHelloService {
  sayHello(helloRequest: HelloRequest): Promise<HelloReply>
}

// generate dubbo client stub service
export const HelloService = dubbo.newClientStubService<IHelloService>({
    name: 'HelloService',
    methods: {
      sayHello(helloRequest) {
        return  {
            args: [HelloRequest],
           //... maybe other information
         }
      },
  })

dubboClient.addStubServices({helloSerivce: HelloService})

对应的server部分

// generate request type
export interface HelloRequest {
  name:string
}

// generate response type
export interface HelloReply {
  message: string
}

export default abstract class HelloService {
  path: string = 'HelloService'

  // sub class implements this abstract method
  abstract sayHello(req: HelloRequest): Promise<HelloReply>
}

export class HelloService extends AbstractHelloService {
  async sayHello(req: HelloRequest): Promise<HelloReply>: Promise<HelloReply> {
    return {message: `hello from server and receive from ${req.name}}
  }
}

dubboServer.addServices({HelloService})
hsiaosiyuan0 commented 1 year ago

因为 protobuf 比较出名了,所以我在想是不是可以基于现有的开源库来实现,比如 ts-proto

类似 ts-proto(可能需要注意下开源协议)这样我们是否可以直接使用,或者基于它的一些工作,比如直接使用它的前端解析器部分

creasy2010 commented 1 year ago

@hsiaosiyuan0 目前的生成流程也借鉴了ts-proto等库,如:pb文件解析(也是基于官方protoc)及fileDescript类型定义(google提供),其他一些基础方法在coding时可以参考;

两种形态确实要讨论下:

  1. 在ts-proto库写 generate扩展,以生成dubbojs stub;
  2. 单独封装生成命令;
hufeng commented 1 year ago

只要拿到了ast,其实就解决大部分问题了,剩下的只是根据我们的诉求生成dubbo-client/dubbo-server的stub service 方法上可以借鉴,但是我们还是要梳理我们需要什么,如果我们不需要那么重的实现逻辑,也可以自己实现。

现在的重点也要思考生成代码的样子。

杨晓东 在 2022年11月21日 星期一 14:32:50 (+08:00) 写道:

@hsiaosiyuan0 目前的生成流程也借鉴了ts-proto等库,如:pb文件解析(也是基于官方protoc)及fileDescript类型定义(google提供),其他一些基础方法在coding时可以参考;

两种形态确实要讨论下:

在ts-proto库写 generate扩展,以生成dubbojs stub; 单独封装生成命令;

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.

hufeng commented 1 year ago

@creasy2010 我们要把dubbo-client/dubbo-server的stub service 接口设计出来,这样大家就好协同了,模块内部的实现不影响大家的并行协作,我和invoker模块 冯伟同学整体过了下 他这边要做的事情,我们可以根据我们上面的stub service定义 先开展起来,过程中有需要完善的再调整。

creasy2010 commented 1 year ago

@hufeng 目前是按照示例的内容在推进;

hufeng commented 1 year ago

@creasy2010 东哥,这个地方,

// generate request type
export interface HelloRequest {
  name:string
}

// generate response type
export interface HelloReply {
  message: string
}

// generate service interface
export interface IHelloService {
  sayHello(helloRequest: HelloRequest): Promise<HelloReply>
}

// generate dubbo client stub service
export const HelloService = dubbo.newClientStubService<IHelloService>({
    name: 'HelloService',
    methods: {
      sayHello(helloRequest) {
        return  {
            args: [HelloRequest],
           //... maybe other information
         }
      },
  })

dubboClient.addStubServices({helloSerivce: HelloService})

这个地方我的想法 对newClientStubService方法设计,需要考虑点:

这个方法可以约束类型,但不应该覆盖返回类型,返回类型单独export出来

// generate request type
export interface HelloRequest {
  name:string
}

// generate response type
export interface HelloReply {
  message: string
}

// generate service interface
export interface IHelloService {
  sayHello(helloRequest: HelloRequest): Promise<HelloReply>
}

// generate dubbo client stub service
export const HelloService = dubbo.newClientStubService({
    name: 'HelloService',
    methods: {
      sayHello(helloRequest) {
        return  {
            args: [HelloRequest],
           //... maybe other information
         }
      },
  })

dubboClient.addStubServices({helloSerivce: HelloService})