RPC在点我达网关的实践一

栏目: 服务器 · 发布时间: 5年前

内容简介:关于 RPC 细节点,可以阅读在项目刚启动阶段,网关项目会通过 zk(路由管理系统) 进行路由寻址(寻找相应后端组的服务),后续网关项目就能和相应的后端组的服务直接通讯了。在初始化阶段,网关项目会将项目信息、注册区域(异地多活)、所需服务等传递给

RPC 是什么

  • RPC(Remote Procedure Call) 译为远端过程调用。即在一台机子上能调用到另外一台机子上的服务;
  • RPC 可以基于 HTTP 调用也可以基于 TCP 调用。基于 TCP 调用性能更佳,但是实现也更为复杂;
  • RPC 通常要实现两部分协议,一个是应用层协议(如 JSON),一个是用来传输数据的通讯层协议(如 Dubbo);

RPC 调用过程

  1. 调用方通过本地网关调用相应服务;
  2. 网关将服务名和参数封装为 RPC 对象传给客户端 RPC 框架(@dwd/noob-client);
  3. 客户端 RPC 框架(@dwd/noob-client)将数据转化成二进制形式,然后以 TCP 的形式传递给服务端 RPC 框架;
  4. 服务端 RPC 框架将二进制数据反序列化为 RPC 对象,并交由服务方处理,服务端处理后返回结果;
  5. 执行上述阶段的逆序操作;

关于 RPC 细节点,可以阅读 聊聊 Node.js RPC(一)— 协议

结合代码分析 Java 包的调用过程

初始化阶段 —— RPC 调用之前

在项目刚启动阶段,网关项目会通过 zk(路由管理系统) 进行路由寻址(寻找相应后端组的服务),后续网关项目就能和相应的后端组的服务直接通讯了。

在初始化阶段,网关项目会将项目信息、注册区域(异地多活)、所需服务等传递给 @dwd/noob-client ,相关代码如下:

import { Client } from '@dwd/noob-client'

const client = new Client({  
  application: {                // 项目信息
    name: config.name,
  },
  registry: config.registry,    // 注册区域
  reference: config.references, // 所需服务
  routerServer: { address: routerAddress },
})

return client.init().then(() => {  
  for (const r of config.references) {
    loadService(r.id)
  }
})

根据 xml 文件生成相关的包文件

在项目伊始时,会通过后端给出的 xml 文件,根据脚本生成相应包的 ts 文件。比如以下代码为骑手服务组的一个包的 ts 文件。

import { Reference } from '@dwd/noob'  
import { provideService, javaType} from '../../util/dubbo'

@provideService('com.dianwoba.rider.elastic.provider.RiderElasticProvider')
export default class RiderElasticProvider implements com.dianwoba.rider.elastic.provider.RiderElasticProvider {

  constructor(private _ref: Reference<com.dianwoba.rider.elastic.provider.RiderElasticProvider> ) {}

  async pageSearch(@javaType({"name":"com.dianwoba.rider.elastic.domain.dto.param.RiderEsParamDTO","isPrimitive":false,"isArray":false,"isGeneric":false}) paramDTO: com.dianwoba.rider.elastic.domain.dto.param.RiderEsParamDTO) : Promise<com.dianwoba.dubbo.base.result.Pagination<com.dianwoba.rider.elastic.domain.dto.result.RiderEsDTO>> {
    return this._ref.invoke('pageSearch', Array.from(arguments))
  }

  ...
}

RiderElasticProvider 的实例化

网关的核心架构使用了 IoC 框架 inverify 。在 IoC 架构下,实例化的过程在容器内进行。

在上述代码点开 provideService 方法,可以看到实例化的过程 new ServiceClass(reference) ,代码如下:

// dubbo.ts
import { Client } from '@dwd/noob-client'

export const provideService = <T>(interfaceName: string) => (ServiceClass: interfaces.Newable<T>) => {  
  const reference = Client.reference.get(interfaceName)                    // 获取远程引用资源
  const service = proxyService(new ServiceClass(reference), interfaceName) // 代理实例对象,下文解析
  moduleBind<T>(interfaceName).toConstantValue(service)                    // 依赖注入
}

reference 对象的 __proto__ 属性上有 invoke 方法(继承自 @dwd/noob)

proxyService 代理

proxyService 方法的作用给包类的每个方法做了一层代理,代理的具体作用是将传入参数和包名包装为 RPC 对象。

// dubbo.ts
function proxyService<T>(service:T, identifier: string) {  
  let handler = {
    apply: function(target: Function, thisArgument: any, argumentsList: any[]) {
      let funcName = target.name
      // 获取前面代码 @javaType({}) 中声明的对象
      let paramTypes: JavaType[] = Reflect.getMetadata(JAVATYPE_SYMBOL, service, funcName)
      // 工厂模式创建转化为 RPC 对象的方法
      let transform = converter.methodParameterTransformerFactory(...paramTypes)
      // 将传入参数和包名转化为 RPC 对象
      let args = transform(argumentsList)
      return target.apply(thisArgument, args)
    }
  }
  Object.getOwnPropertyNames(Object.getPrototypeOf(service)).filter(name => name !== 'constructor' && !name.startsWith('_')).forEach(methodName => {
    service[methodName] = new Proxy(service[methodName], handler) // 将原型链上 service[methodName] 赋值到 service[methodName] 上,并用 handler 进行代理
  })
  return service
}

番外笔记

ts 的语法

class Test {  
  constructor(private _ref) {}
}

ts 转换为 js 的形式如下

function Test(_ref) {  
  this._ref = _ref
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

网络英雄传

网络英雄传

郭羽、刘波 / 江苏凤凰文艺出版社 / 2018-6 / 59.80元

“商战鬼才郭羽、营销奇才刘波强强联手,凝集十年实战经验,倾力打造商战巨作。” 这是一个商业竞争和资本激战交织的惊心动魄的创业交锋故事。 由郭天宇、刘帅共同创立的在线旅游公司万全天盛凭借其出色的商业模式异军突起,与老牌巨头“51旅游网”两强相争,但国际巨头通远来势汹汹,国内在线旅游市场进入战火纷飞的“三国杀”时代,分踞杭、沪、京三地互相“搏杀”。中国新兴的互联网公司面对国际巨头的入侵,毫不退缩......一起来看看 《网络英雄传》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具