远子 💖 Vina

读 homedo-nodejs-base-framework

远子 â€¢  2020å¹´09月27日 â€¢ è¯„论

文章内容已脱敏, 不包含任何隐私信息.

homedo-nodejs-base-framework 是河姆渡内部基于 eggjs 封装的上层框架 (为了和 eggjs 框架区分开, 以下简称 base 框架), 公司内部有大量基于此框架的项目, 最近我又仔细读了一遍源码, 简单的分析一下.

base 框架有以下功能:

  1. 统一的 logger;
  2. 可以连接到公司的 apollo 配置中心;
  3. 可以访问其他 Java 微服务;
  4. 可以连接到 Eureka;

目前不支持 Node 项目直接操作 Mysql 数据库, 数据的存取逻辑需要通过 Java 服务提供的接口, 由 Java 的同事完成, 但可以连接 redis.

先看一下文件结构:
image.png

接下来一一阐述我的理解.

统一的 logger 是怎么挂载到子应用中的?

按照 eggjs 框架的约定, extend 目录中的文件会扩展到 ctx 上下文中.

app/extend/helper.js 的核心代码如下:

'use strict';

module.exports = {
    logDebug(msg, options) {
        this._logLog(msg, options, "debug");
    },
    logInfo(msg, options) {
        this._logLog(msg, options, "info");
    },
    logWarn(msg, options) {
        this._logLog(msg, options, "warn");
    },
    logError(msg, options) {
        this._logLog(msg, options, "error");
    },
    _logLog(msg, options, level) {
        let title = options ? options.title : "~";
        if (!title) {
            title = "~";
        }

        let obj = this.ctx ? this.ctx : this.app;

        if (this.ctx) {
            msg = `-${title} - ${msg}`;
        } else {
            msg = `~-${title} - ${msg}`;
        }

        if (level === 'debug') {
            obj.logger.debug(msg);
        }
        if (level === 'info') {
            obj.logger.info(msg);
        }
        if (level === 'warn') {
            obj.logger.warn(msg);
        }
        if (level === 'error') {
            obj.logger.error(msg);
        }
    },

};

可以看到此文件暴露了 ctx.helper.logDebug()、 ctx.helper.logInfo()、 ctx.helper.logWarn()、ctx.helper.logError() 等几个方法用来打印各个级别的日志.

其中 config.logger.dir 做了全局配置, 根据不同的项目将日志输出到指定目录:

// process.env['APP_ID'] 为项目的唯一编号
config.logger.dir = '/opt/logs/' + process.env['APP_ID'] + '/applog';

如果需要查看日志的话, 可以登录服务器在 /opt/logs 中寻找, 如下图:

image.png

可以看到日志以天为单位做了分割;

eggjs 的日志分为以下几类:

  1. common-error.log: 程序员通过 ctx.logger.error 方法打印的日志会输出到这里;
  2. egg-agent.log: agent 进程日志, 框架和使用到 agent 进程执行任务的插件会打印一些日志到这里;
  3. egg-schedule.log: 定时任务的日志;
  4. egg-web.log: 框架内核、插件日志;
  5. ${appInfo.name}-web.log: 应用日志, 主要用来程序员调试, ctx.logger.log 等方法打印的日志会输出到这里;

kibana 平台会以一定规则来延时搜集这些日志到 web 平台, 便于程序员定位错误:

image.png

error 级别的错误频繁出现的话, 会通过钉钉提供的 webhook 通知到指定群组;

程序员用起来很方便:

  1. 在编写代码的时候调用 ctx.helper.logError 打印错误信息;
  2. 在频繁报错的时候, 会收到 kibana 推送的钉钉消息;
  3. 根据钉钉消息的报错时间点, 到 kibana 平台锁定具体的错误信息;
  4. 如果依旧解决不了的话, 登录服务器自行排查;

base 框架是怎么连接到 apollo 配置中心的?

首先 apollo 也是一个微服务, 提供了供外部访问的 API.

base 框架连接 apollo 还依赖另一个名为 homedo-egg-apollojs 的包, 主要功能: 通过 http 请求 apollo 配置中心, 获取并返回当前项目的配置文件:

  • remoteConfigService: apollo 开放平台接入方式
  • remoteConfigServiceFromCache: 获取项目的 apollo 配置(走缓存)
  • remoteConfigServiceSikpCache: 获取项目的 apollo 配置(不走缓存)
  • setEnv: 将项目的 apollo 配置注入到 process.env
  • getConfig: 获取缓存的配置 (json 格式)

apollo 的配置有单独的 web 页面, 分为 dev、fat、uat、pro 四个环境, 并集成了整个公司的用户数据和用户权限 (以项目或项目组为单位);

homedo-egg-apollojs 还内置了一个 30s 的定时器, 定时更新 apollo 配置文件到项目的 process.env 中, 这样程序员在修改了 apollo 配置以后, 最多 30s 线上项目就会生效, 因此在项目中读取 apollo 配置的地方, 要通过 process.env.yourConfigName, 而不能将 process.env 缓存到某个变量中.

程序员的使用流程:

  1. 向领导申请 apollo 配置权限;
  2. 在 apollo 中设定自己的配置, 比如: userCacheTimestamp 为 3600s;
  3. 在项目中通过 process.env.userCacheTimestamp 获取;

base 框架是怎么调用微服务的?

base 框架是怎么连接到 eureka 的?

如有遗漏或者描述不准确之处, 欢迎和我交流.

End.


我要发表看法

«-必填
«-必填,不公开