background

We have some services, switching from JAVA to Node.js, so we need a good configuration center, Ctrip Apollo is great, JAVA language has official maintenance Client, great. There are several open source implementations for switching to Node.js, but it’s not perfect for us. Simple requirements:

  • Hot updates are supported, and I don’t want to restart the server every time I change the configuration
  • Preferably like Java @value(“mysql.port:3306”) a simple decorator can inject configuration
  • Fault tolerance capability. For example, when the configuration center is down, the service can still be started normally. In the case that the configuration center is unavailable, the service can proactively recover the latest configuration startup project.
  • Support the Typescript

Hence the birth of this project,

Introduction

  1. This project is the Node.js version client provided by Ctrip configuration center Framework Apollo.

  2. After the client connects successfully, it will pull a copy of all configurations to the local storage, which is mainly used for fault tolerance and degradation in the case of Apollo service unavailable.

  3. Http long polling mechanism is used to achieve hot update, and the client will automatically modify the injected attribute value to achieve the configuration modification without restart.

  4. You can get the latest configuration using the getConfigs() function;

  5. Fault tolerance mechanism, Apollo service is not available in the case of the client will automatically resume the last configuration started.

Apollo server test environment:

  • Host: http://106.54.227.205
  • Account:apollo
  • Password:admin

Features

  • Configuring hot Update
  • Support decorator @value(“mysql.port:3306”)
  • The cache is configured locally
  • Gray released
  • Support the TypeScript

Install

npm i ctrip-apollo-client
Copy the code

Usage

  • This demo has created a project apolloclient in the test environment, you can directly test locally;
  • After the user. Name value is changed in the configuration center, the latest value is automatically obtained without restart.
  • The demo source code.
import { CtripApplloClient, value, hotValue } from 'ctrip-apollo-client';
import Koa from 'koa';

const apollo = new CtripApplloClient({
    configServerUrl: 'http://106.54.227.205:8080',
    appId: 'apolloclient',
    configPath: './config/apolloConfig.json',
    namespaceList: ['application'.'development.qa']});const app = new Koa();

const run = async() = > {// Initialize the configuration
    await apollo.init();

    // The obtained configuration is not hot updated
    const port = apollo.getValue('app.port:3000');
    // To obtain the configuration, support hot update, need to obtain the final value through appname. value
    const appName = hotValue('app.name:apollo-demo');

    class User {
        // Support hot update via decorator injection
        // Only class attributes can be injected
        @value("user.name:liuwei")
        public name: string
    }
    const user = new User();

    app.use(async (ctx, next) => {
        ctx.body = {
            appName: appName.value,
            userName: user.name
        }
        await next();
    })
    app.listen(port);
    console.log('listening on port:', port);
    console.info(`curl --location --request GET \'http://localhost:${port}\' `);
}
run();
Copy the code

Javascript Demo please click the link

API

ApolloClient(Options) constructor

  • returns: apolloClient
  • options
    • configServerUrl string requiredApollo Specifies the address of the configuration service
    • appId string requiredApplication of the appId
    • clusterName stringCluster name, default:default
    • namespaceList arrayThe name of the Namespace. Default:[application]
    • configPath stringDefault value of the local configuration file path./config/apolloConfig.json
    • logger objectLogging classes must be implementedlogger.info().logger.error()Two methods

Init (timeoutMs) Initializes the configuration center, pulls the remote configuration to the end, and caches the configuration to a file. At the same time, the configuration change listener is enabled to synchronize the configuration in real time. If the pull exceeds the timeoutMs or an exception occurs, the local cache configuration file is read. If there is no cache configuration file locally, an exception is thrown.

  • return: Promise
  • TimeoutMs Specifies the timeout period

GetConfigs () gets the latest configuration file

  • returns: object
const config = apollo.getConfigs();
Copy the code

GetValue (Namespace = ‘application’) Gets the specific configuration field

  • returns: string
  • Namespace Default value:application
  • field string eg: mysql.port:3306If 3306 is not configured as the default value
class User {
    get userName () {
        return apollo.getValue({ field: 'user.name:liuwei'}); }}Copy the code

HotValue (Namespace = ‘application’) gets the specific configuration field, encapsulates the getter(hot update)

  • returns: {value}
  • Namespace Default value:application
  • field stringAttribute location eg:mysql.port:3306If 3306 is not configured as the default value
const userName = apollo.hotValue({ field: 'user.name:liuwei' });
console.log(userName.value);
Copy the code

withValue(target, key, field, namespace)

  • returns: void
  • Target Target object
  • Key requires the properties of the object to be injected
  • field stringAttribute location eg:mysql.port:3306If 3306 is not configured as the default value
  • namespace stringDefault value:application
class User {
    constructor () {
        withValue(this, 'userId', { field: 'user.id:10071'}); }} // The userId property is updated with the configuration new User().useridCopy the code

OnChange (callback(object)) Configuration change callback notification

  • returns: void

Value (Field, namespace) injector that can only inject class attributes

  • field stringThe field properties
  • namespace string
import { value } from 'ctrip-apollo-client';
class User {
    @value("user.name:liuwei")
    public name: string
}
Copy the code

Benchmark

[localValue] x 736,896,802 ops/ SEC ±1.49% (82 runs time)

Support hot update [hotValue] x 2021,310 OPS/SEC ±1.28% (87 runs time)

[hotValue default] x 1,581,645 OPS/SEC ±0.89% (87 runs sampled)

[decorator] x 2,161,312 ops/ SEC ±0.96 percent (87 runs sampled)

[dot] x 704,644,395 ops/ SEC ±1.45% (82 runs sampled)

Fastest is [localValue]

License

MIT

Program source code

Github.com/lvgithub/ct…