{"id":13527454,"url":"https://github.com/sofastack/sofa-rpc-node","last_synced_at":"2025-05-16T04:04:47.478Z","repository":{"id":32471998,"uuid":"134402137","full_name":"sofastack/sofa-rpc-node","owner":"sofastack","description":"SOFARPC Node is a high-performance, high-extensibility, production-level Nodejs RPC framework.","archived":false,"fork":false,"pushed_at":"2023-12-01T14:54:35.000Z","size":17446,"stargazers_count":614,"open_issues_count":13,"forks_count":66,"subscribers_count":34,"default_branch":"master","last_synced_at":"2025-04-08T14:12:36.678Z","etag":null,"topics":["nodejs","rpc","rpc-framework","sofa","sofa-rpc","sofastack"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sofastack.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-22T10:57:44.000Z","updated_at":"2025-04-06T04:29:27.000Z","dependencies_parsed_at":"2023-12-01T15:51:14.564Z","dependency_job_id":null,"html_url":"https://github.com/sofastack/sofa-rpc-node","commit_stats":{"total_commits":112,"total_committers":15,"mean_commits":7.466666666666667,"dds":0.6964285714285714,"last_synced_commit":"91ba177b26da71591ca3548b9894477b768e3c56"},"previous_names":[],"tags_count":54,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sofastack%2Fsofa-rpc-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sofastack%2Fsofa-rpc-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sofastack%2Fsofa-rpc-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sofastack%2Fsofa-rpc-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sofastack","download_url":"https://codeload.github.com/sofastack/sofa-rpc-node/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253351779,"owners_count":21895028,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nodejs","rpc","rpc-framework","sofa","sofa-rpc","sofastack"],"created_at":"2024-08-01T06:01:48.349Z","updated_at":"2025-05-16T04:04:42.468Z","avatar_url":"https://github.com/sofastack.png","language":"JavaScript","readme":"# sofa-rpc-node\n\n[SOFARPC](https://github.com/sofastack/sofa-rpc) Nodejs 实现版本\n\n[![NPM version][npm-image]][npm-url]\n[![Node.js CI](https://github.com/sofastack/sofa-rpc-node/actions/workflows/nodejs.yml/badge.svg)](https://github.com/sofastack/sofa-rpc-node/actions/workflows/nodejs.yml)\n[![Known Vulnerabilities][snyk-image]][snyk-url]\n[![npm download][download-image]][download-url]\n\n[npm-image]: https://img.shields.io/npm/v/sofa-rpc-node.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/sofa-rpc-node\n[snyk-image]: https://snyk.io/test/npm/sofa-rpc-node/badge.svg?style=flat-square\n[snyk-url]: https://snyk.io/test/npm/sofa-rpc-node\n[download-image]: https://img.shields.io/npm/dm/sofa-rpc-node.svg?style=flat-square\n[download-url]: https://npmjs.org/package/sofa-rpc-node\n\n## 一、SOFARPC Node 简介\n\n简单说它是 [SOFARPC](https://github.com/sofastack/sofa-rpc) 的 Nodejs 版实现，但本质上它是一个通用的 Nodejs RPC 解决方案。Nodejs RPC 在阿里和蚂蚁内部已经发展了四五年时间，如今广泛应用于各类业务场景，并经历了多次双 11 大促的考验。功能方面从基本的服务发布、寻址、点对点远程调用能力；到各种路由、负载均衡策略；再到故障隔离、熔断等高级功能，已逐渐发展成一个高可扩展性、高性能、生产级的 RPC 框架。\n\n## 二、模块划分\n\nSOFARPC Node 主要包含了四个子模块，分别是：\n\n- __client：__ RPC 的客户端实现\n- __server：__ RPC 的服务端实现\n- __registry：__ 服务注册中心抽象及实现（目前提供 zookeeper 实现）\n- __test：__ RPC 测试工具类\n\n```bash\n.\n└── lib\n    ├── client\n    ├── registry\n    ├── server\n    └── test\n```\n\n## 三、快速上手\n\n### 安装\n\n```bash\nnpm install sofa-rpc-node --save\n```\n\n### 安装并启动 zookeeper\n\nsofa-rpc-node 默认的注册中心实现基于 zookeeper，所以需要先启动一个 zookeeper 实例\n\n从 Homebrew 安装（macOs）\n\n```bash\nbrew install zookeeper\n```\n\n启动 zk server（默认端口为 2181）\n\n```bash\nzkServer start\n\n# ZooKeeper JMX enabled by default\n# Using config: /usr/local/etc/zookeeper/zoo.cfg\n# Starting zookeeper ... STARTED\n```\n\n### 代码示例\n\n- 暴露一个 RPC 服务，并发布到注册中心\n\n```js\nconst { RpcServer } = require('sofa-rpc-node').server;\nconst { ZookeeperRegistry } = require('sofa-rpc-node').registry;\nconst logger = console;\n\n// 1. 创建 zk 注册中心客户端\nconst registry = new ZookeeperRegistry({\n  logger,\n  address: '127.0.0.1:2181', // 需要本地启动一个 zkServer\n});\n\n// 2. 创建 RPC Server 实例\nconst server = new RpcServer({\n  logger,\n  registry, // 传入注册中心客户端\n  port: 12200,\n});\n\n// 3. 添加服务\nserver.addService({\n  interfaceName: 'com.nodejs.test.TestService',\n}, {\n  async plus(a, b) {\n    return a + b;\n  },\n});\n\n// 4. 启动 Server 并发布服务\nserver.start()\n  .then(() =\u003e {\n    server.publish();\n  });\n```\n\n- 调用 RPC 服务（从注册中心获取服务列表）\n\n```js\nconst { RpcClient } = require('sofa-rpc-node').client;\nconst { ZookeeperRegistry } = require('sofa-rpc-node').registry;\nconst logger = console;\n\n// 1. 创建 zk 注册中心客户端\nconst registry = new ZookeeperRegistry({\n  logger,\n  address: '127.0.0.1:2181',\n});\n\nasync function invoke() {\n  // 2. 创建 RPC Client 实例\n  const client = new RpcClient({\n    logger,\n    registry,\n  });\n  // 3. 创建服务的 consumer\n  const consumer = client.createConsumer({\n    interfaceName: 'com.nodejs.test.TestService',\n  });\n  // 4. 等待 consumer ready（从注册中心订阅服务列表...）\n  await consumer.ready();\n\n  // 5. 执行泛化调用\n  const result = await consumer.invoke('plus', [ 1, 2 ], { responseTimeout: 3000 });\n  console.log('1 + 2 = ' + result);\n}\n\ninvoke().catch(console.error);\n```\n\n- 调用 RPC 服务（直连模式）\n\n```js\nconst { RpcClient } = require('sofa-rpc-node').client;\nconst logger = console;\n\nasync function invoke() {\n  // 不需要传入 registry 实例了\n  const client = new RpcClient({\n    logger,\n  });\n  const consumer = client.createConsumer({\n    interfaceName: 'com.nodejs.test.TestService',\n    serverHost: '127.0.0.1:12200', // 直接指定服务地址\n  });\n  await consumer.ready();\n\n  const result = await consumer.invoke('plus', [ 1, 2 ], { responseTimeout: 3000 });\n  console.log('1 + 2 = ' + result);\n}\n\ninvoke().catch(console.error);\n```\n\n- 测试 RPC Server 的方法（用于单元测试）\n\n```js\nconst request = require('sofa-rpc-node').test;\nconst { RpcServer } = require('sofa-rpc-node').server;\nconst logger = console;\n\ndescribe('test/server.test.js', () =\u003e {\n  let server;\n  before(async function() {\n    server = new RpcServer({\n      logger,\n      port: 12200,\n    });\n    server.addService({\n      interfaceName: 'com.nodejs.test.TestService',\n    }, {\n      async plus(a, b) {\n        return a + b;\n      },\n    });\n    await server.start();\n  });\n  after(async function() {\n    await server.close();\n  });\n\n  it('should call plus ok', async function() {\n    await request(server)\n      .service('com.nodejs.test.TestService')\n      .invoke('plus')\n      .send([ 1, 2 ])\n      .expect(3);\n  });\n});\n```\n\n- 暴露和调用 protobuf 接口\n\n通过 *.proto 来定义接口\n\n```proto\nsyntax = \"proto3\";\n\npackage com.alipay.sofa.rpc.test;\n\n// 可选\noption java_multiple_files = false;\n\nservice ProtoService {\n  rpc echoObj (EchoRequest) returns (EchoResponse) {}\n}\n\nmessage EchoRequest {\n  string name = 1;\n  Group group = 2;\n}\n\nmessage EchoResponse {\n  int32 code = 1;\n  string message = 2;\n}\n\nenum Group {\n  A = 0;\n  B = 1;\n}\n```\n\n服务端代码\n\n```js\nconst antpb = require('antpb');\nconst protocol = require('sofa-bolt-node');\nconst { RpcServer } = require('sofa-rpc-node').server;\nconst { ZookeeperRegistry } = require('sofa-rpc-node').registry;\nconst logger = console;\n\n// 传入 *.proto 文件存放的目录，加载接口定义\nconst proto = antpb.loadAll('/path/proto');\n// 将 proto 设置到协议中\nprotocol.setOptions({ proto });\n\nconst registry = new ZookeeperRegistry({\n  logger,\n  address: '127.0.0.1:2181',\n});\n\nconst server = new RpcServer({\n  logger,\n  protocol, // 覆盖协议\n  registry,\n  codecType: 'protobuf', // 设置默认的序列化方式为 protobuf\n  port: 12200,\n});\n\nserver.addService({\n  interfaceName: 'com.alipay.sofa.rpc.test.ProtoService',\n}, {\n  async echoObj(req) {\n    req = req.toObject({ enums: String });\n    return {\n      code: 200,\n      message: 'hello ' + req.name + ', you are in ' + req.group,\n    };\n  },\n});\nserver.start()\n  .then(() =\u003e {\n    server.publish();\n  });\n```\n\n客户端代码\n\n```js\nconst antpb = require('antpb');\nconst protocol = require('sofa-bolt-node');\nconst { RpcClient } = require('sofa-rpc-node').client;\nconst { ZookeeperRegistry } = require('sofa-rpc-node').registry;\nconst logger = console;\n\n// 传入 *.proto 文件存放的目录，加载接口定义\nconst proto = antpb.loadAll('/path/proto');\n// 将 proto 设置到协议中\nprotocol.setOptions({ proto });\n\nconst registry = new ZookeeperRegistry({\n  logger,\n  address: '127.0.0.1:2181',\n});\n\nasync function invoke() {\n  const client = new RpcClient({\n    logger,\n    protocol,\n    registry,\n  });\n  const consumer = client.createConsumer({\n    interfaceName: 'com.alipay.sofa.rpc.test.ProtoService',\n  });\n  await consumer.ready();\n\n  const result = await consumer.invoke('echoObj', [{\n    name: 'gxcsoccer',\n    group: 'B',\n  }], { responseTimeout: 3000 });\n  console.log(result);\n}\n\ninvoke().catch(console.error);\n```\n\n### 最佳实践\n\n虽然上面我们提供了示例代码，但是我们并不推荐您直接使用该模块，因为它的定位是 RPC 基础模块，只提供基本的 API，对于业务开发者可能并不是非常友好。我们的最佳实践是通过插件将 RPC 能力集成到 [Egg.js](https://github.com/eggjs/egg) 框架里，提供更加直观友好的用户接口，让您就像使用本地方法一样使用 RPC。这块也会在近期开放，敬请期待！\n\n\n## 三、相关文档\n\n- [聊聊 Node.js RPC（一）— 协议](https://www.yuque.com/egg/nodejs/dklip5)\n- [聊聊 Node.js RPC（二）— 服务发现](https://www.yuque.com/egg/nodejs/mhgl9f)\n\n## 四、如何贡献\n\n请告知我们可以为你做些什么，不过在此之前，请检查一下是否有已经[存在的Bug或者意见](https://github.com/sofastack/sofa-rpc-node/issues)。\n\n如果你是一个代码贡献者，请参考[代码贡献规范](https://github.com/eggjs/egg/blob/master/CONTRIBUTING.zh-CN.md)。\n\n## 五、开源协议\n\n[MIT](LICENSE)\n\n\u003c!-- GITCONTRIBUTOR_START --\u003e\n\n## Contributors\n\n|[\u003cimg src=\"https://avatars.githubusercontent.com/u/1207064?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003egxcsoccer\u003c/b\u003e\u003c/sub\u003e](https://github.com/gxcsoccer)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/156269?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003efengmk2\u003c/b\u003e\u003c/sub\u003e](https://github.com/fengmk2)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/6897780?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003ekillagu\u003c/b\u003e\u003c/sub\u003e](https://github.com/killagu)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/2160731?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003emansonchor\u003c/b\u003e\u003c/sub\u003e](https://github.com/mansonchor)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/32174276?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003esemantic-release-bot\u003c/b\u003e\u003c/sub\u003e](https://github.com/semantic-release-bot)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/9605663?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003eChangedenCZD\u003c/b\u003e\u003c/sub\u003e](https://github.com/ChangedenCZD)\u003cbr/\u003e|\n| :---: | :---: | :---: | :---: | :---: | :---: |\n|[\u003cimg src=\"https://avatars.githubusercontent.com/u/18223471?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003eKenyeeC\u003c/b\u003e\u003c/sub\u003e](https://github.com/KenyeeC)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/9674709?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003eRabbitSion\u003c/b\u003e\u003c/sub\u003e](https://github.com/RabbitSion)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/19908330?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003ehyj1991\u003c/b\u003e\u003c/sub\u003e](https://github.com/hyj1991)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/17831480?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003emytEcust\u003c/b\u003e\u003c/sub\u003e](https://github.com/mytEcust)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/1183163?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003esmile21\u003c/b\u003e\u003c/sub\u003e](https://github.com/smile21)\u003cbr/\u003e|[\u003cimg src=\"https://avatars.githubusercontent.com/u/16103358?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003eonlylovermb\u003c/b\u003e\u003c/sub\u003e](https://github.com/onlylovermb)\u003cbr/\u003e|\n[\u003cimg src=\"https://avatars.githubusercontent.com/u/7371122?v=4\" width=\"100px;\"/\u003e\u003cbr/\u003e\u003csub\u003e\u003cb\u003echenfengjw163\u003c/b\u003e\u003c/sub\u003e](https://github.com/chenfengjw163)\u003cbr/\u003e\n\nThis project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Mon May 22 2023 14:22:46 GMT+0800`.\n\n\u003c!-- GITCONTRIBUTOR_END --\u003e\n","funding_links":[],"categories":["Repository","JavaScript","目录"],"sub_categories":["RPC"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsofastack%2Fsofa-rpc-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsofastack%2Fsofa-rpc-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsofastack%2Fsofa-rpc-node/lists"}