likes
comments
collection
share

NestJS小技巧32-在NestJS应用中使用Unleash实现功能切换的指南

作者站长头像
站长
· 阅读数 13

原文链接

在这篇文章中,我将会描述如何使用功能切换在NestJS中控制开发好的API。

介绍

场景非常简单,如果您观察上面的高级架构,客户端应用将使用应用程序暴露的API。在这个流程中,我们可以使用功能切换能力开始限制那些处于实验开发模式的API,使其只对部分客户可用,这样普通可用性(GA)的客户就不会受到这些实验功能的影响。在这篇文章中我将会描述如何创建一个NestJS工程并结合Unleash功能切换来限制API。

安装NestJS

安装NestJS非常简单。您的机器必须事先安装Node然后只要执行下面的命令来全局安装NestJS.

npm i -g @nestjs/cli  
nest new project-name (创建一个新的项目)

想要了解更多关于nestjs-cli以及安装的信息请参照 NestJS官网。然后我在基础的代码上做了一些小小的修改。

NestJS小技巧32-在NestJS应用中使用Unleash实现功能切换的指南

安装unleash服务

我是Docker的忠实粉丝,因此我选择了基于Docker的Unleash服务器安装。使用下面的docker compose文件来创建您的unleash服务。

docker-compose up -d --buil (在dockercompose的同目录下执行这段代码)
# This docker compose setup configures:  
# - the Unleash server instance + the necessary backing Postgres database  
# - the Unleash proxy  
#  
# To learn more about all the parts of Unleash, visit  
# https://docs.getunleash.io  
#  
# NOTE: please do not use this configuration for production setups.  
# Unleash does not take responsibility for any data leaks or other  
# problems that may arise as a result.  
#  
# This is intended to be used for demo, development, and learning  
# purposes only.  
  
version: "3.9"  
services:  
  
  # The Unleash server contains the Unleash configuration and  
  # communicates with server-side SDKs and the Unleash Proxy  
  web:  
    image: unleashorg/unleash-server:latest  
    ports:  
      - "4242:4242"  
    environment:  
      # This points Unleash to its backing database (defined in the `db` section below)  
      DATABASE_URL: "postgres://postgres:unleash@db/postgres"  
      # Disable SSL for database connections. @chriswk: why do we do this?  
      DATABASE_SSL: "false"  
      # Changing log levels:  
      LOG_LEVEL: "warn"  
      # Proxy clients must use one of these keys to connect to the  
      # Proxy. To add more keys, separate them with a comma (`key1,key2`).  
      INIT_FRONTEND_API_TOKENS: "default:development.unleash-insecure-frontend-api-token"  
      # Initialize Unleash with a default set of client API tokens. To  
      # initialize Unleash with multiple tokens, separate them with a  
      # comma (`token1,token2`).  
      INIT_CLIENT_API_TOKENS: "default:development.unleash-insecure-api-token"  
    depends_on:  
      db:  
        condition: service_healthy  
    command: [ "node", "index.js" ]  
    healthcheck:  
      test: wget --no-verbose --tries=1 --spider http://localhost:4242/health || exit 1  
      interval: 1s  
      timeout: 1m  
      retries: 5  
      start_period: 15s  
  db:  
    expose:  
      - "5432"  
    image: postgres:15  
    environment:  
      # create a database called `db`  
      POSTGRES_DB: "db"  
      # trust incoming connections blindly (DON'T DO THIS IN PRODUCTION!)  
      POSTGRES_HOST_AUTH_METHOD: "trust"  
    healthcheck:  
      test:  
        [  
          "CMD",  
          "pg_isready",  
          "--username=postgres",  
          "--host=127.0.0.1",  
          "--port=5432"  
        ]  
      interval: 2s  
      timeout: 1m  
      retries: 5  
      start_period: 10s

实现

现在我有了基本的代码和unleash服务,在我执行之前我需要做一些其他事情,安装一些依赖。

yarn add unleash-client @nestjs/config

现在添加一个.env到项目根目录

APP_NAME=nestjs-experimental-feature-toggle  
API_KEY=<YOUR SERVER KEY>  
UNLEASH_API_ENDPOINT=http://localhost:4242/api  
METRICS_INTERVAL=1  
REFRESH_INTERVAL=1  
SERVER_PORT=3000

让我们从app.module.ts文件开始。这个文件主要是用来初期化并注入到main.ts文件中去。在这个文件中我注入所有的控制,服务还有像下面这样的其他的模型。ConfigModule.forRoot()将会扫描根目录.env文件,将它的内容加载得到应用中去。

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './controllers/app.controller';
import { AppService } from './services/app.service';

@Module({
  imports: [ConfigModule.forRoot()],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

main.ts的内容

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as process from 'process';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(process.env.SERVER_PORT);
}
bootstrap();

现在让我们来构建服务层app.service.ts。响应内容我先硬编码,如果您们需要的话可以在评论栏中说,我可以创建一个文章模型通过TypeORM来连接到数据库,并返回动态的结果。

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  private response = {};
  constructor() {
    this.response['XS'] = '5';
    this.response['S'] = '15';
    this.response['M'] = '25';
    this.response['L'] = '38';
    this.response['XL'] = '28';
    this.response['XXL'] = '15';
  }

  dataAnalytics = (): any => {
    return this.response;
  };
}

是时候来创建控制器app.controller.ts了,有多个部分组成。

constructor:在类中的依赖注入需要使用到它。

init:初始化Unleash客户端

dataAnalytics:根据我决定做什么来验证切换开关的状态

import { Controller, Get, Logger } from '@nestjs/common';
import { AppService } from '../services/app.service';
import { startUnleash, Unleash } from 'unleash-client';
import { ConfigService } from '@nestjs/config';

@Controller('/api/v1')
export class AppController {
  private unleash: Unleash;
  private readonly logger: Logger = new Logger(AppController.name);

  constructor(
    private readonly appService: AppService,
    private readonly configService: ConfigService,
  ) {
    this.init();
  }

  private init = async (): Promise<void> => {
    this.unleash = await startUnleash({
      url: this.configService.get<string>('UNLEASH_API_ENDPOINT'),
      appName: 'beta-api',
      metricsInterval: parseInt(this.configService.get('METRICS_INTERVAL'), 10),
      refreshInterval: parseInt(this.configService.get('REFRESH_INTERVAL'), 10),
      customHeaders: {
        Authorization: this.configService.get<string>('API_KEY'),
      },
    });
  };

  @Get('/analytics')
  dataAnalytics(): any {
    // Unleash SDK has now fresh state from the unleash-api
    const isEnabled: boolean = this.unleash.isEnabled('beta-api');
    this.logger.log(`feature switch "beta-api" is ${isEnabled}`);
    if (isEnabled) {
      return this.appService.dataAnalytics();
    } else {
      return {
        response: 'can not access this api as its in experimental mode',
      };
    }
  }
}

现在都完成了,我只要运行应用就行了,首先,我们需要在Unleash中创建一个功能切换,通过URL访问Unleash的网络控制台:http://localhost:4242,点击默认项目并创建一个新的切换,然后为我们的切换添加策略。在这种情况下,我选择了逐步推出策略。一旦您创建了功能切换,然后转到项目设置并创建一个项目访问令牌(创建一个服务器端访问令牌)。

网络控制台应该看上去像下面这样

NestJS小技巧32-在NestJS应用中使用Unleash实现功能切换的指南

NestJS小技巧32-在NestJS应用中使用Unleash实现功能切换的指南

NestJS小技巧32-在NestJS应用中使用Unleash实现功能切换的指南

执行下面的代码并察看结果

yarn start:dev

NestJS小技巧32-在NestJS应用中使用Unleash实现功能切换的指南

选一个任何您喜欢的API测试工具比如postman或者其他的。现在让我们通过切换来测试这些api看看应用程序会有哪些行为。

NestJS小技巧32-在NestJS应用中使用Unleash实现功能切换的指南

NestJS小技巧32-在NestJS应用中使用Unleash实现功能切换的指南

结论:

实际的使用场景在文章开始的架构中描述。我们实现了其中的一小部分,这次我们使用了Nestjs框架。与原生的Nodejs和express相比,我个人非常喜欢Nestjs。整个代码库都提供在我的gitee账户上,请克隆并玩一玩。请通过鼓掌和订阅来支持我。祝您学得愉快。

本章代码