1.1.1. 调用流程
在 Run.ts 中调用 start 后,会先从容器中拿到 gateway 相关的配置,以及拿到之前在容器中绑定的 GatewayServer:
const configuration = this.container.get<GatewayConfig>(
Types.gatewayConfig
);
this._server = this.container.get(GatewayServer);
然后调用 GatewayServer 中的 startServer 方法:
this._server.startServer();
在 startServer 方法中,实际上是为 Gateway 创建了一个 HTTP Server,并使用 this.handlerRequest 方法作为 requestListener:
this._server = http.createServer(async (req, res) =>
this.handleRequest(req, res)
);
在 handleRequest 这个 handleRequest 中,除了做一些为服务器响应设置头信息等事情以外,最核心的是调用了以下这行代码:
await this.routeIModelServerReq(req, res);
在 routeIModelServerReq 方法中,会根据客户端的请求 URL,判断应该将请求转发给哪一个服务
如果 URL 是 iModelJs Backend 相关的,且 server.config.json 中 iModelJsBackends 为 true,则把请求转发给 IModelJsBackend 服务;
如果 URL 是 licensing 相关的,则先进行权限验证
await this.authenticate(req, true)
,通过验证后再把请求转发给 Licensing 服务;如果 URL 不是 iModelJs Backend 或者 licensing 相关的,那么应该就是 Repositories 请求相关的,则先进行权限验证
await this.authenticate(req, true)
,通过验证后,执行 handleRepositoriesRequest 方法去处理请求:await this.handleRepositoriesRequest( this._routingParser.parseRepositoriesPath(pathname), req, res );
客户端请求 Gateway 的 URL 一般格式为:
http://gatewayUrl/:version/Repositories/:plugin--:location/:schemaName/:className
举个例子,客户端请求创建新的 iModel,请求为:
http://localhost:4000/sv1.1/Repositories/Context--b80917a4-36e1-4362-9cca-35b5c7c93bf6/ContextScope/iModel
在 handleRepositoriesRequest 方法中,会根据 plugin 的值对请求进行不同的处理:
- 如果 plugin 是 iModel,则调用
await this.forwardToIModelBank(req, res, reposQuery.location)
将请求转发到 iModelBank 服务; - 如果 plugin 是 Global 或者 Context,则调用
await this.forwardToLocalIModelManagerServer(req, res)
把请求转发到 iModelManager 服务中。
在上面那个例子中,plugin 是 Context,所以此请求是被转发到 iModelManager 服务中。
- 如果 plugin 是 iModel,则调用
1.1.2. 那么,我们是如何知道我们要转发请求的目的服务的 URL 是什么呢?
Orchestrator 服务是我们要启动的第一个服务,在启动 Orchestrator 服务的同时,会创建一个 Fastify 服务器(End Point),这个服务器设置了以下路由,用于处理 Orchestrator Client 发送过来的请求:
GET http://orchestrator.url/service/:serviceType/:instanceId
GET http://orchestrator.url/service/:serviceType
POST http://orchestrator.url/service/:serviceType
DELETE http://orchestrator.url/service/:serviceType/:instanceId
POST http://orchestrator.url/job/:jobType
POST http://orchestrator.url/shutdown
上面那个例子中,我们是将请求转发给 IModelMananger 服务的,我们要通过 Orchestrator Client 去对 Orchestrator 的 End Point 发起 GET 请求(GET service/imodel-manager),这个请求的响应就是 iModel Manager 服务,里面保存了 protocol、hostname、port、url、category、runnableType 和 instanceId 的信息,这里的 url 正是我们要转发的目的服务的 URL,然后通过 Proxy Server 把客户端的请求转发到目的服务上。