1. 程式人生 > 實用技巧 >一種不錯的 BFF Microservice GraphQL/REST API 層的開發方式

一種不錯的 BFF Microservice GraphQL/REST API 層的開發方式

雲原生(Cloud Native)Node JS Express Reactive 微服務模板 (REST/GraphQL) 這個專案提供了完整的基於 Node JS / Typescript 的微服務模板,包括生產部署、監控、除錯、日誌記錄、安全、CI/CD 所需的所有功能。還添加了基於響應性擴充套件的示例,以演示如何將其用於構建微服務 API 邊緣服務(edge-service)、前端的後端(BFF)或將其用作構建任何型別微服務的基礎。

專案地址:nxplorerjs-microservice-starter

設計原則

  • 使用同類最佳的模組來建立可用於生產的微服務框架
  • 基於 12-factor app
    原則
  • 沒有定製程式碼或包裝器,因此任何開發人員都可以修改/替換任何模組或實現
  • 可作為參考的實現的設計模式
  • 模組化,可替換和即插即用程式碼
  • 為業務 API 和微服務平臺開發提供入門
  • DevOps 準備了程式碼質量,單元和整合測試,自動部署。

功能/特性

  • Node JS, Express, Typescript , 依賴注入(Dependency Injection base)
  • 基於 Backpack (webpack) - 構建 , 開發 , 打包
  • 啟用 Swagger - Express swagger 中介軟體 / Swagger UI 整合
  • GraphQL 基於 Apollo Server 2.0
    ,帶有 JWT 安全性、資料載入器(data loader)和 REST 資料來源示例
  • 通過 graphql-import 支援 GraphQL SDL
  • 開發期間 GraphQL mock resolvers (可選) - graphql-tools
  • 基於 GraphQL 的客戶端包裝 API - graphql-request
  • REST APIs - 使用 Inversify Controller
  • 外部化配置 - DotEnv (設定,特定於 Env 的 API URL)
  • 測試 - Jest , SuperTest , GraphQL Tester。 自動化單元和整合測試的基礎設施
  • 程式碼覆蓋率 - Istanbul
  • 程式碼質量 - tslint
  • 容器支援 - Docker , Kubernetes 叢集
  • 基於 Helm Chart 的部署支援
  • Prometheus 整合
  • API 響應日誌記錄,Express Server 日誌記錄,UUID 傳播 - Pino
  • Reactive Extensions 支援 - RxJS6
  • CORS, JSONObject 限制 , Helmet , CSRF - Express 安全
  • 基於 IOC / 依賴注入 / Express 註釋的 API - Inversify
  • 文件 - TypeDocs
  • API 異常處理實用程式
  • 標準 HTTP Code 以獲取更清蒸的 code
  • 示例 API,模式以供參考
  • Sonar Qube 整合
  • Hystrix 熔斷器支援 (使用 Brakes)
  • 基於 JWT 的 API 安全性 - jsonwebtoken, express-jwt
  • 現在使用超級快速的 pino 日誌程式來滿足所有的日誌記錄需求
  • 內建額外的效能時間記錄

檢視 REST API /examples/{id}

{
  "pid": 3984,
  "hostname": "LP-507B9DA1D355",
  "level": 30,
  "time": 1515813665734,
  "0": {
    "socket": 5.656709999995655,
    "lookup": 186.8375229999947,
    "connect": 389.5646870000055,
    "response": 594.8022639999981,
    "end": 599.1270230000082
  },
  "v": 1
}

REST APIs

  • 可以使用以下 URL 下載 API 規範
http://localhost:3000/api-docs/Api.yaml
http://localhost:3000/api-docs/
  • examples - API 中的按 ID 示例搜尋的基本示例 (/examples/:id)
  • shop - 如何使用 Reactive Extensions 進行 API 編排(FlatMap)的示例 (/shop/priceByOptionId/:id)
  • starwars - 如何使用 Reactive Extensions 進行 API 編排的示例(ForkJoin)(/starwars/people/:id)
  • hystrix - 如何對 API 使用熔斷模式的示例 (/hystrix)
  • scraper - 如何使用 scrape-it 從網站上抓取資料的示例 (/scraper)
  • 使用 swagger UI 以獲得示例 API 的完整列表
  • metrics - 為所有 API 添加了基於 Prometheus 的指標 (/metrics)
  • API 部分 JSON 響應支援
    curl http://localhost:3000/api/v1/starwars/people/1
  • Response
    {
        name: "Luke Skywalker",
        height: "172",
        mass: "77",
        hair_color: "blond",
        skin_color: "fair",
        eye_color: "blue",
        birth_year: "19BBY",
        gender: "male",
        homeworld: {
        name: "Tatooine",
        rotation_period: "23",
        orbital_period: "304",
        diameter: "10465",
        climate: "arid",
        gravity: "1 standard",
        terrain: "desert",
        surface_water: "1",
        population: "200000",
        residents: [
        "http://swapi.co/api/people/1/",
        "http://swapi.co/api/people/2/",
        "http://swapi.co/api/people/4/",
        "http://swapi.co/api/people/6/",
        "http://swapi.co/api/people/7/",
        "http://swapi.co/api/people/8/",
        "http://swapi.co/api/people/9/",
        "http://swapi.co/api/people/11/",
        "http://swapi.co/api/people/43/",
        "http://swapi.co/api/people/62/"
        ],
        films: [
        "http://swapi.co/api/films/5/",
        "http://swapi.co/api/films/4/",
        "http://swapi.co/api/films/6/",
        "http://swapi.co/api/films/3/",
        "http://swapi.co/api/films/1/"
        ],
        created: "2014-12-09T13:50:49.641000Z",
        edited: "2014-12-21T20:48:04.175778Z",
        url: "http://swapi.co/api/planets/1/"
        },
        films: [
        "http://swapi.co/api/films/2/",
        "http://swapi.co/api/films/6/",
        "http://swapi.co/api/films/3/",
        "http://swapi.co/api/films/1/",
        "http://swapi.co/api/films/7/"
        ],
        species: [
        "http://swapi.co/api/species/1/"
        ],
        vehicles: [
        "http://swapi.co/api/vehicles/14/",
        "http://swapi.co/api/vehicles/30/"
        ],
        starships: [
        "http://swapi.co/api/starships/12/",
        "http://swapi.co/api/starships/22/"
        ],
        created: "2014-12-09T13:50:51.644000Z",
        edited: "2014-12-20T21:17:56.891000Z",
        url: "http://swapi.co/api/people/1/"
        }

    curl http://localhost:3000/api/v1/starwars/people/1?data(name,gender,homeworld(gravity,population))
  • Response
    {
      "data": {
        "name": "Luke Skywalker",
        "gender": "male",
        "homeworld": {
          "gravity": "1 standard",
          "population": "200000"
        }
      }
    }

GraphQL

  • 已基於 apollo framework 和參考實現添加了 GraphQL 支援(包括來自 swapi.costarwars api

  • http://localhost:3000/playground 訪問 graphql playground

  • http://localhost:3000/graphiql 訪問 graphiql tool

  • GraphQL API 跟蹤(可配置)

  • 用於快取和批處理的資料載入器(Dataloader)

  • 添加了多個啟用 Dataloader 示例

    • RxJS API 呼叫 - peopleWithPlanets(id : )
    • Starwars APIs - people(id: ) , planet(id: ) , starship(id: ) - peopleList(keys: [number])
  • 查詢列表(請參閱 schema 詳細資訊以獲取完整列表)

    • quoteOfTheDay: String
    • random: Float
    • examples: [ExampleType] <-- JWT身份驗證
    • example(id: Int): ExampleType
    • blog(id: Int) (Paginated query)
    • rollThreeDice: [Int]
    • peopleWithPlanet(id: Int): PeopleWithPlanetType (Uses RxJS to combine results from 2 APIs)
    • peopleDS(id: Int): PersonType (Based on REST DataSource)
    • people(id: Int): PersonType (Based on data loader)
    • planet(id: Int): PlanetType
    • starship(id: Int): StarshipType
    • peopleList(keys: [Int]): [PersonType]
    • movie: MovieType
    • 示例查詢執行

  • Mutations

    • addExample(name: String!): ExampleType
    • addComment(comment: CommentInput!): Comment
    • login(email: String!,password: String!): UserType
    • 示例 Mutation 執行

  • Subscriptions

    • exampleAdded (將檢查是否通過 mutation 添加了新元素)
    • commentAdded (每當通過 mutation 新增新 comment 時都會檢查)
    • 示例 Subscription 執行

  • VSCode 除錯啟動配置(添加了預配置的除錯啟動器)
  • 在開發過程中添加了用於遙測的 Node 儀表板檢視
  • 增加了 NodeJS 叢集模式(負載均衡 worker)
    • 啟動伺服器時,它會根據 CPU 數量新增 worker
Master cluster setting up 4 workers...
Worker 2828 is online
Worker 2816 is online
Worker 13956 is online
Worker 3756 is online
up and running in development @: LP-507B9DA1D355 on port: 3000
up and running in development @: LP-507B9DA1D355 on port: 3000
up and running in development @: LP-507B9DA1D355 on port: 3000
up and running in development @: LP-507B9DA1D355 on port: 3000

Graphql 客戶端 API

  • 當我們構建基於 GraphQL 的伺服器時,可能需要從其他下游基於 GraphQL 的 API 伺服器獲取資料。

  • 作為一個示例,graphqlcool/graphql-request 模組用於演示這一點,使用 graphqlcool 演示 graphQL api https://api.graph.cool/simple/v1/movies

  • API 規範

query {
  movie {
    releaseDate
    slug
    actors {
      name
    }
  }
}
  • API 輸出
{
  "data": {
    "movie": {
      "releaseDate": "2010-08-28T20:00:00.000Z",
      "slug": "inception",
      "actors": [
        {
          "name": "Leonardo DiCaprio"
        },
        {
          "name": "Ellen Page"
        },
        {
          "name": "Tom Hardy"
        },
        {
          "name": "Joseph Gordon-Levitt"
        },
        {
          "name": "Marion Cotillard"
        }
      ]
    }
  }
}

先決條件

安裝 npm 和 nodeJS

npm version >= 3.x
node version >= 6.x

安裝它

npm install

設定 外部環境

  • 編輯 .{PROFILE}.env 檔案 —— 其中的概要檔案(PROFILE)可以是測試(test)、開發(development)、生產(production)
變數 描述 預設值
PORT 伺服器埠 3000
LOG_LEVEL 日誌級別 (info,debug,error) info
SESSION_SECRET 用於簽名 cookie 的字串
API_TIME_OUT 預設API超時(以毫秒為單位) 10000
TEST_TIME_OUT 預設測試超時(以毫秒為單位) 10000
JWT_AUTH 啟用/禁用基於 JWT 的 API 安全 true
RSA_PRIVATE_KEY_FILE RSA 私鑰路徑示例
RSA_PUBLIC_KEY_FILE RSA 公鑰路徑示例
TOKEN_EXPIRY_TIME JWT 令牌到期(從 /login 生成) 1 hour (1h)
STREAM_HYSTRIX 啟用/禁用 Hystrix streaming 伺服器 (true 或 false) false
CORS 在伺服器上啟用/禁用 CORS (true 或 false)。僅在生產版本中可用 false
CLUSTER_MODE 在伺服器上啟用/禁用 Node Clustering (true 或 false) false
SWAGGER_API_DOCS_ROOT 服務您的 Swagger API 檔案,以便它們可與 Swagger UI,PostMan 等前端工具一起使用。 /api-docs/
GRAPHQL_SUBSCRIPTIONS 啟用/禁用 GraphQL subscriptions (true 或 false) true
GRAPHQL_PLAYGROUND 啟用/禁用 GraphQL Playground (true 或 false) true
GRAPHQL_TRACING 啟用/禁用 GraphQL tracing (true 或 false) true
GRAPHQL_MOCK 啟用/禁用 GraphQL Mock,對於未實現的介面(true 或 false) true
API_MOCK 啟用/禁用 REST API Mock,對於未實現的路由(true 或 false) true

執行它

執行在 開發 模式

npm run dev

執行在 生產 模式

npm run compile
npm start

執行在 VS Code 除錯 模式

npm run compile
Press F5

執行帶有程式碼覆蓋率的測試

執行單元測試

  • 單元測試與要測試的模組或類位於同一目錄中
  • 所有單元測試都需要有一個副檔名 \*.spec.ts
npm run test

執行整合測試

  • 整合測試與要測試的模組或類位於同一目錄中
  • 所有整合測試都需要有一個副檔名 *.itest.ts
  • 首先構建整合測試。這將在構建中設定整合測試環境
npm run itest:build
  • 執行 node 伺服器並對其進行整合測試
  • 這等待伺服器啟動,執行測試,然後在完成時終止所有程序
npm itest:run

嘗試一下

  • 將您的瀏覽器指向 http://localhost:3000.
  • 直接或通過 swagger 呼叫示例 REST 端點 http://localhost:3000/swagger
  • 使用端點呼叫 Prometheus 指標 curl http://localhost:3000/metrics
  • 訪問針對 graphQL 的瀏覽器內建 IDE http://localhost:3000/graphiql
  • 訪問 graphQL playground app http://localhost:3000/playground/
  • 訪問健康檢查 api curl http://localhost:3000/healthcheck

檔案結構

├───public                      * nxplorer server 的登入頁面
├───screenshots                 * 示例截圖
└───server                      * 伺服器配置和 API
|   ├───api                     * 伺服器上定義的 REST API
|   │   ├───controllers         * 使用 RxJS,Inversify 的 API controller
|   │   │   ├───examples        * Examples controller
|   │   │   ├───hystrix-demo    * Hystrix demo controller
|   │   │   ├───security        * JWT login API controller
|   │   │   ├───shop            * 帶有產品,價格,庫存的示例商店 API
|   │   │   └───starwars        * SWAPI controller
|   │   ├───interfaces          * Service 介面
|   │   ├───models              * API 資料模型
|   │   └───services            * Service API 實現
|   ├───common                  * Server 啟動和配置
|   │   ├───config              * Server 配置
|   │   ├───constants           * Inversify 和其他通用識別符號常量
|   │   ├───interfaces          * 公共 service 介面  
|   │   ├───middleware          * 自定義中介軟體
|   │   ├───models              * 公共 API 資料模型
|   │   ├───services            * 公共 service 實現
|   │   └───swagger             * Swagger API 規範 (YAML)
|   |   └───env.ts              * DotENV 配置
|   |   └───server.ts           * Express Server 啟動和配置
|   └───graphql                 * 伺服器上定義的 GraphQL API
|   |   ├───dataloader          * GraphQL 資料載入器功能
|   |   ├───errors              * GraphQL 錯誤處理程式
|   |   ├───schema              * GraphQL Schema 型別
|   |   ├───mocks               * GraphQL Mock Resolvers
|   |   └───resolvers           * GraphQL resolvers
|   |   └───setupSchema.ts      * GraphQL schema 配置
|   └───index.ts                * 主 Server 入口點
├───helm                        * Helm chart 部署指令碼
│   ├───charts                  *
│   └───templates               *
└───backpack.config.js          * Backpack 配置
└───package.json                * npm 依賴
└───build.js                    * ShellJS 實用程式構建指令碼
└───deploy-k8s.sh               * Kubernetes 部署指令碼
└───Dockerfile                  * Docker 構建檔案
└───docker-compose.yml          * Docker 構建和執行檔案
└───build-docker.bat|sh         * Docker 構建檔案
└───itest.config.json           * Jest 整合測試配置
└───unit.config.json            * Jest 單元測試配置
└───tsconfig.json               * typescript 配置
└───tslint.json                 * tslint 配置
└───.{profile}.env              * 基於配置檔案的外部環境檔案 (development 開發,test 測試, production 生產)
└───sonar-properties.json       * sonarscanner|SonarQube 配置
└───jwtRS256.key|.key.pub       * 伺服器使用的 JWT 私鑰和公鑰示例

日誌與 UUID

  • 添加了 UUID 傳播的示例實現。這取決於在請求物件中設定的 cookie 'UUID'。LogService 將把 uuid 新增到它生成的所有日誌中。

  • 例如,如果 'UUID' 設定為 xxxx-dddd-ssss-wwww-ssss,那麼呼叫 /shop/products API 將生成

{
  "pid": 13492,
  "hostname": "LP-507B9DA1D355",
  "level": 30,
  "time": 1515859200496,
  "uuid": "xxxx-dddd-ssss-wwww-ssss",
  "fullUrl": "http://localhost:3000/api/v1/shop/products",
  "statusCode": 200,
  "responseTime": "1.187",
  "v": 1
}

GraphQL Mocks

  • 作為 TDD 的一部分,我們可能需要模擬 graphql 響應,直到我們能夠實現解析器為止
  • 該基礎結構設定為僅為當前未實現的解析器新增模擬。因此,一旦實現可用,實際的解析器就會接手。 同樣,如果解析器執行失敗,那麼這將落在模擬響應上。 此功能只能在開發期間使用,因此已新增檢查以禁用“生產”版本中的此功能。
  • 為了支援
    • 設定環境變數 GRAPHQL_MOCK 為 true
    • mocks/index.ts 檔案定義 mock 解析器(resolver)
  • 作為示例,有查詢添加了 examplesMock, peopleMock
  • 示例輸出如下

RestAPI Mocks

  • .<Profile>.env 檔案中啟用 API_MOCK=true。注意:為了安全起見,即使 API_MOCK 設定為 true,也無法在生產模式下使用
  • 針對自動產生 mockswagger-express-middleware 模組提供了開箱即用的支援
  • 步驟
    • Api.yaml 檔案 定義 API swagger 規範
    • 如果 express 路由中沒有可用的實現,那麼中介軟體將為這些 api 建立模擬
  • 訪問 nXplorer (/swagger) 提供的 swagger ui,並引用標記為 Mock API 和帶有字首 /mock 的 API。該示例有兩個主要實體 —— carsdrivers。您可以搜尋、執行 CRUD 操作以及上傳和下載影象。

構建 Docker 映象

./build-docker.sh

k8s 部署

  • 基於 Helm chart 的部署
./deploy-k8s.sh
  • 一個示例的輸出
release "nxplorerjs-microservice" deleted
NAME:   nxplorerjs-microservice
LAST DEPLOYED: Fri Sep 22 22:10:58 2017
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                          DATA  AGE
nxplorerjs-microservice-starter  5     1s

==> v1/Service
NAME                          CLUSTER-IP  EXTERNAL-IP  PORT(S)       AGE
nxplorerjs-microservice-starter  10.0.0.196  <nodes>      80:30316/TCP  1s

==> v1beta1/Deployment
NAME                          DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
nxplorerjs-microservice-starter  1        1        1           0          1s


注意:
1. 通過執行以下命令獲取應用程式 URL:
  export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services nxplorerjs-microservice-nxplorerjs-microservice-starter)
  export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT

Express 微服務被部署到  http://192.168.99.100:30316/

使用 node 儀表板檢視(僅針對開發環境)

  • 去使用 node 儀表板檢視
npm run compile
npm run dash
  • 這將啟動帶有附加的 node 儀表板的應用程式,該儀表板提供有關記憶體,cpu 和日誌的詳細資訊

安全

  • 已使用示例 JWT 私鑰和公鑰實現了基於 JWT 的安全性
  • REST API 和 GraphQL 都添加了示例實現。
  • 驗證中介軟體程式碼可以在這裡檢視

JWT Security GraphQL

  • 基於 JWT 的安全性的演示實現已啟用一個查詢“示例”。 下面是測試的步驟。
  • 如果啟用了 JWT 安全性(環境變數 JWT_AUTHtrue),我們需要使用登入突變 API 來獲取示例 JWT 令牌(當前設定為1小時到期)
  • Step 1 - 使用登入 mutation(突變)來獲取有效使用者的 jwt 令牌。出於演示目的,可以提供任何電子郵件和密碼字串。該角色是可選的。如果未提供,則預設為角色 “USER”
mutation {
  login(email: "[email protected]",
  password:"admin",role:"ADMIN") {
    id
    role
    email
    jwt
  }
}

  • Step 2 - 驗證“示例”是否無需身份驗證即可工作。 它將給出一個錯誤(注意:錯誤處理需要改進,但是這裡我們只看這個概念)

  • Step 3 - 在執行 “examples” 查詢之前,使用 Bearer token 設定授權頭。
{
  "Authorization": "Bearer xxx.xxx.xxx"
}

JWT Security REST APIs

  • 如果啟用了 JWT 安全性,那麼我們需要使用 /login API 獲取示例 JWT 令牌(當前設定為1小時到期)
curl -X POST "http://localhost:3000/api/v1/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"email\": \"[email protected]\", \"password\": \"pwd\", \"role\": \"admin\"}"
  • 示例輸出。注意,JWT token 是屬性 idToken 的值
{
  "idToken":
    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJpYXQiOjE1MTQ4NjQ3ODMsImV4cCI6MTUxNDg2ODM4Mywic3ViIjoidGVzdEBnbWFpbC5jb20ifQ.hAEa6AL1Kxxxxxxx",
  "expiresIn": "1h"
}
  • api/v1/examples API,一個有效的 JWT 令牌必須在 “Authorization” header 中,在所有查詢中傳遞。注意,這只是一個示例。您也可以類似地輕鬆啟用新增端點。
    • 請檢視 examples controller
      @controller('/examples', authMiddleware(<User>{ role: 'admin'}))
      
    • 函式 authMiddleware 負責驗證在 header 中傳遞的 JWT token。
    • 它可以擴充套件為也支援基於角色的訪問,併為此提供了支援。
    • 注意:作為演示示例,這裡提供了公鑰和私鑰。理想情況下,在真實場景中從外部維護這些JWKS (JSON Web Key Set)端點
  • “Authorization” header 中必須使用以下語法:
    Bearer xxxxxx.yyyyyyy.zzzzzz
  • 使用 swagger ui 測試
    • 點選 “Authorize” 按鈕,設定上面提到的 Bearer token
    • 現在所有 /examples 相關的 api 都可以工作了
RBAC 測試
  • 如果啟用了 JWT 安全性,並且我們使用 /login API 獲取示例 JWT token,但其角色為 “guest” 而不是 “admin”
curl -X POST "http://localhost:3000/api/v1/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"email\": \"[email protected]\", \"password\": \"pwd\", \"role\": \"guest\"}"
  • 在 “Authorization” header 中設定 Bearer token,用於後續呼叫任何 /examples api,將導致基於角色的授權失敗

GraphQL Directives

  • 這項工作正在進行中。
  • 當前添加了一個使用 @date 指令的示例(如 graphql-tools 文件中所述)
  • Query ({ today(format: "mmm-dd-yy") }) - 這裡的格式基於@date scheme Directive,該格式接受解析器的輸出並格式化日期,然後再將其傳送給客戶端。
  • Query ( { examplesWithAuth { id name } } - 這是對 JWT GraphQL APIs 部分中提到的示例查詢的一種變體。此處的區別在於,我們使用 @auth 指令根據角色來處理身份驗證,而不是對解析程式中的實現進行硬編碼。這是更清蒸的方法,並且與解析器分離。
  • 查詢 schema examplesWithAuth: [ExampleType] @auth(requires: ADMIN) 使用 @auth 指令,該指令將攔截具有適當角色的經過身份驗證的使用者的呼叫檢查。(注意:您需要在之前執行 login mutation,然後使用 Authorization token 設定 HTTP header)

CSRF Security

  • 生產模式中啟用了 CSRF 安全性
  • 所有 POST API 都需要讀取瀏覽器中設定的 cookie “XSRF-TOKEN”,然後使用以下任一 key 將其傳遞到響應頭中
    • req.headers['csrf-token'] - CSRF-Token HTTP 請求頭。
    • req.headers['xsrf-token'] - XSRF-Token HTTP 請求頭。
    • req.headers['x-csrf-token'] - X-CSRF-Token HTTP 請求頭。
    • req.headers['x-xsrf-token'] - X-XSRF-Token HTTP 請求頭。

Compression

  • 預設情況下,壓縮是在伺服器上啟用的,並且基於壓縮模組
  • 配置詳細資訊位於 compression.ts 檔案
  • 如果需要在不壓縮的情況下獲取響應,請在請求頭中傳遞 x-no-compression

Hystrix 熔斷器支援

  • 熔斷器支援已新增到專案中,並使用 hystrix 相容模組 brakes
  • Hystrix 預設禁用流支援。
  • 通過在 .env 檔案中將 STREAM_HYSTRIX 屬性設定為 “STREAM_HYSTRIX=true” 來啟用它
  • 為了方便起見,提供了 Hystrix 伺服器的 Docker 版本,並在 docker-compose.yml 檔案中進行了設定
在 Docker 上執行的步驟
npm run compile
docker-compose build
docker-compose up
  • 在 Docker 上設定 3000 和 8080 的埠轉發

  • Access the Hystrix dashboard at localhost:8080/hystrix and set the stream location to localhost:3001/hystrix.stream
  • 訪問 localhost:8080/hystrix 上的 Hystrix 儀表板,並將流位置設定為 localhost:3001/hystrix.stream
  • /api/v1/hystrix 下執行示例,並在儀表板上檢視 hystrix stream 結果

與 SonarQube 整合(保證持續的程式碼質量)

假設您已經安裝了 SonarQube 5.5.6 (LTS)

  • 使用 Sonar Typescript 外掛和 Generic Test Coverage 外掛設定 SonarQube
  • 全域性安裝 sonar-scanner (npm install --global sonar-scanner)
  • 更新屬性 sonar.host.urlsonar-project.properties 檔案以指向您的 SonarQube 伺服器。預設情況下,這假設 SonarQube 伺服器使用預設埠在本地執行
  • 執行單元測試
npm run test
  • 測試結果以 sonar 相容格式收集在結果資料夾中
  • 將結果推送到 SonarQube
npm run sonar-scanner

修改 package.json 以設定適當的 sonarQube 版本

jestSonar": {
    "reportPath": "reports",
    "reportFile": "test-reporter.xml",
    "indent": 4,
    "sonar56x": true
}

注意:對於 Sonar 6.x,將 sonar56x 設定為 “false”,這將生成使用 sonar 6 schema 的測試報告。

負載測試

  • loadtest 是用於負載測試的出色工具
  • 使用步驟
  • 將其安裝為全域性 npm 模組
npm install -g loadtest
  • 啟動 nxplorerjs-microservice
npm run start
  • 針對生產版本執行負載測試。以下是一個示例
loadtest http://localhost:3000/api/v1/examples/1 -t 20 -c 20

互相交流

一起雲原生