在 nest.js 的动态配置模块中注册微服务客户端并通过参数加载到服务中
Microservice client registration in dynamicaly configured module for nest.js and loading into service by parameter
我在应用程序中使用了具有动态配置的 shared
模块。
共享模块包含 interceptor
和 service
,其中包含从共享参数配置的客户端。
我通过预定义的名称将 service
注入到 interceptor
中(将 SharedModule
动态导入到 SecondAppModule
中)。所以客户端名称可以有不同的值。在服务内部,我需要在客户端注入之前知道客户端名称。现在它是硬编码的:
@Injectable()
export class SumClientService {
constructor(@Inject('MATH_SERVICE') private client: ClientProxy) {
console.log('[SumClientService] - created')
}
sumCalculation(row: number[]): Observable<number> {
return this.client.send<number>({ cmd: 'sum' }, row);
}
}
问题
如果名称仅在构建时已知,是否有任何方法可以通过名称从上下文加载服务?
我在列表中检测到两种方法可以将过去的名称作为参数投入使用,而不会破坏由 nest.js
管理的 DI。但是我不知道如何通过指定名称访问模块上下文以加载服务(想法片段的代码如下)
@Injectable()
export class SumClientService {
constructor(@Inject('service_name') private name: string) {
console.log('[SumClientService] - created')
}
client: (clientName: string) => ClientProxy = (clientName: string): ClientProxy => // TODO load by clientName real client from `nest.js` context
// ...
}
P.S.
想法是在同一应用程序中使用多个客户端。我第一次考虑每个模块一个客户端的场景。
在动态模块中创建微服务客户端的选项很少:
第一个选项
在模块配置级别:
import { Module } from '@nestjs/common';
import { ClientModule } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({
imports: [
ClientModule.register([
{ 'NAME_FOR_DI', ...configForYourClient }
])
],
...
})
...
用法:
import { Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
...
constructor(@Inject('NAME_FOR_DI') private readonly client: ClientProxy) { }
第二个选项
对于动态配置的模块:
import { Module, DynamicModule } from '@nestjs/common';
import { ClientModule } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({})
export class YourModule{
static register(): DynamicModule {
return {
module: YourModule,
imports: [
ClientModule.register([
{ 'NAME_FOR_DI', ...configForYourClient }
])
],
}
}
}
第三个选项
import { ClientProxy, ClientProxyFactory } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
...
private client: ClientProxy = ClientProxyFactory.create(configForYourClient)
按照第二个选项,它可以直接在服务中创建,也可以在提供程序中为指定 DI 密钥的模块注册,例如:
import { Module } from '@nestjs/common';
import { ClientProxyFactory } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({
providers: [
{
provide: 'NAME_FOR_DI',
useValue: ClientProxyFactory.create(configForYourClient)
},
],
...
})
...
通过指定键进行后续注入。
P.S.
我在这里描述了动态注入的一般概念。这个想法可以通过不同的组合来丰富(为单个提供者注入值列表,或将配置列表注入 ClientModule.register
中,您应该在 DI 方法中应用一些更正)
我在应用程序中使用了具有动态配置的 shared
模块。
共享模块包含 interceptor
和 service
,其中包含从共享参数配置的客户端。
我通过预定义的名称将 service
注入到 interceptor
中(将 SharedModule
动态导入到 SecondAppModule
中)。所以客户端名称可以有不同的值。在服务内部,我需要在客户端注入之前知道客户端名称。现在它是硬编码的:
@Injectable()
export class SumClientService {
constructor(@Inject('MATH_SERVICE') private client: ClientProxy) {
console.log('[SumClientService] - created')
}
sumCalculation(row: number[]): Observable<number> {
return this.client.send<number>({ cmd: 'sum' }, row);
}
}
问题
如果名称仅在构建时已知,是否有任何方法可以通过名称从上下文加载服务?
我在列表中检测到两种方法可以将过去的名称作为参数投入使用,而不会破坏由 nest.js
管理的 DI。但是我不知道如何通过指定名称访问模块上下文以加载服务(想法片段的代码如下)
@Injectable()
export class SumClientService {
constructor(@Inject('service_name') private name: string) {
console.log('[SumClientService] - created')
}
client: (clientName: string) => ClientProxy = (clientName: string): ClientProxy => // TODO load by clientName real client from `nest.js` context
// ...
}
P.S.
想法是在同一应用程序中使用多个客户端。我第一次考虑每个模块一个客户端的场景。
在动态模块中创建微服务客户端的选项很少:
第一个选项
在模块配置级别:
import { Module } from '@nestjs/common';
import { ClientModule } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({
imports: [
ClientModule.register([
{ 'NAME_FOR_DI', ...configForYourClient }
])
],
...
})
...
用法:
import { Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
...
constructor(@Inject('NAME_FOR_DI') private readonly client: ClientProxy) { }
第二个选项
对于动态配置的模块:
import { Module, DynamicModule } from '@nestjs/common';
import { ClientModule } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({})
export class YourModule{
static register(): DynamicModule {
return {
module: YourModule,
imports: [
ClientModule.register([
{ 'NAME_FOR_DI', ...configForYourClient }
])
],
}
}
}
第三个选项
import { ClientProxy, ClientProxyFactory } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
...
private client: ClientProxy = ClientProxyFactory.create(configForYourClient)
按照第二个选项,它可以直接在服务中创建,也可以在提供程序中为指定 DI 密钥的模块注册,例如:
import { Module } from '@nestjs/common';
import { ClientProxyFactory } from '@nestjs/microservices';
import { configForYourClient } from '../configs';
@Module({
providers: [
{
provide: 'NAME_FOR_DI',
useValue: ClientProxyFactory.create(configForYourClient)
},
],
...
})
...
通过指定键进行后续注入。
P.S.
我在这里描述了动态注入的一般概念。这个想法可以通过不同的组合来丰富(为单个提供者注入值列表,或将配置列表注入 ClientModule.register
中,您应该在 DI 方法中应用一些更正)