You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
在实际的工作开发中,我们肯定会不断地修改代码,细心的同学肯定会发现,上述的代码无法使用 bun 提供的热更新指令 --hot。一旦修改代码,一定会报错:
E No address added out of total 1 resolved
462 |return bindResult.port;
463 | }
464 |else {
465 | const errorString = `No address added out of total ${addressList.length} resolved`;
466 | logging.log(constants_1.LogVerbosity.ERROR, errorString);
467 | throw new Error(`${errorString} errors: [${bindResult.errors.join(',')}]`);
^
error: No address added out of total 1 resolved errors: [Failed to listen at 0.0.0.0]
at /Users/jrainlau/Desktop/bun-grpc-server-demo/node_modules/@grpc/grpc-js/build/src/server.js:467:31
at processTicksAndRejections (native:7:39)
在 cnb.cool 的任务集功能区中,我们使用了 bun 作为服务端,负责任务集视图的相关读写能力,积累了一定的经验。整体来说 bun 的写法和 Nodejs 几乎一致,但对于“提供 gRPC 服务”相关的知识,现网所能找到的资料较少,因此专门记录下来。
一、初始化
参考官网的方式,首先把 bun 安装到机器上(本文开发环境为 MacOS)。
curl -fsSL https://bun.sh/install | bash
接下来就可以初始化我们的项目并安装 grpc 依赖了。
回头在
package.json
里面加入调试的启动命令:由于 bun 是一个能够直接运行 ts 代码的 runtime,所以也非常推荐直接使用 ts 来写我们的 server 端代码。
回到项目根目录,新建一个
index.ts
,随便写入一句console.log('hello world')
,执行yarn dev
,便可看到控制台输出了“hello world”字段。修改这里的代码,由于启动时加入了--hot
的缘故,所以它会实时热更新并运行新的代码,这样就免去每次都要重新手动运行的繁琐步骤了。二、代码实现
要学习在 bun 中架设 gRPC 服务,首先得要有一份符合要求的
.proto
文件。这里用一个最简单的 Hello World 来举个例子:可以很直观地看到,我们定义了一个叫做
Hello
的服务,它提供了一个 rpc 调用函数SayHello()
。接下来我们就要开始学习如何实现这个服务。回到根目录,按照如下的结构组织代码:
. ├── index.ts └── src ├── protos │ └── hello.proto ├── server.ts └── services └── sayHello.ts
核心的代码为
src/server.ts
,第一个就要去实现它。我们的思路如下:
addService()
函数,允许传入不同的.proto
文件和对应的实现代码;start()
函数,允许传入 host 和 port。因此它的雏形是这样的:
在实现具体的逻辑代码之前,不得不吐槽一下官方教程真的藏得有点深。其教程最核心的代码如下:
和我们的思路对应,它也是先通过
addService
添加服务,再通过bindAsync
绑定 host 和 port 启动服务器。理解了官网的写法后,便可以移植到我们的实现当中来。为了正确地提供
protoService
参数到addService()
,我们需要写一个getProto()
方法。该方法通过@grpc/proto-loader
加载给到的.proto
文件,返回一个grpc.GrpcObject
。接下来我们便可编写
SayHello
的具体实现代码了:注意,这里的
call: { request: any }
对应着hello.proto
中的message SayHelloRequest
,这里定义了需要传入一个类型为 string 的参数name
。callback
的第一个参数是Error
对象,在出现错误的时候可以把错误传递进去,如果没有错误则填入null
即可。第二参数则对应了hello.proto
中的message SayHelloResponse
。最后回到
index.ts
,我们便可以直接启动一个最简单的 gRPC 服务了:执行启动命令后,控制台将会输出
使用BloomRPC调试工具,可以验证到该服务已经正常运行。
三、开发模式下热更新能力的提供
在实际的工作开发中,我们肯定会不断地修改代码,细心的同学肯定会发现,上述的代码无法使用 bun 提供的热更新指令
--hot
。一旦修改代码,一定会报错:该错误的原因是在热更新的时候,并没有杀掉上一次的 gRPC 服务,导致热更新后无法再使用同样的 host 和 port。查遍了官网和 Google 都没有找到对应的解法,最后愣是在源码
@grpc/grpc-js/build/src/server.js
中找到了一个方法forceShutdown()
,强行终止服务。实现方式也很简单,在每次调用
start()
进行启动的时候,判断全局底下是否仍有残留的实例,如果有就调用forceShutdown()
方法杀掉它。最后,本文有关的代码都在仓库 bun-grpc-server-demo 中,可自行下载尝试。
The text was updated successfully, but these errors were encountered: