软件技术学习笔记

个人博客,记录软件技术与程序员的点点滴滴。

EFK结构化日志

在分布式系统中,我们一般把日志集中收集到EFK或ELK中。默认情况下,Elasticsearch(ES)收集到的是一行一行日志文本,但是,这样的日志不方便业务检索,也没有充分发威ES的检索能力。

为了方便业务检索,我们做结构化日志,输出的内容均为JSON格式,经过Filebeat的简单处理,扔给ES存储与建立索引。查看日志时,可以对特定的业务字段做过滤,比如: user.id: 123。 日志输出格式如下,一条日志一行JSON:

继续阅读→

新的方式传递链路追踪上下文(NodeJS)

最近一个多月都在忙于项目,没有时间记录新的知识。我们起了一个全新的前端项目,技术选型是React + SSR + Dva。要求的起点也比较高:用户导航首屏SSR,其它时候CSR;代码要求SSR与CSR复用;所有的请求经过Node层;页面显示、接口请求均要求小于1秒。

为了容易定位调用链路的性能点,我们加入了Jaeger Open Tracing,这就涉及到链路追踪上下文的传递。

继续阅读→

NodeJS微服务间传递用户上下文

后端包含众多微服务时,如果每个微服务都是自己去查询用户信息(比如: 用户ID、登录名),会造成用户微服务压力过大、响应延时增大。为了解决这类问题,可以在网关服务中查询用户信息等共用信息,然后传递到其它的微服务中,微服务之间也相互传递。

为了前端代码复用,在NodeJS中也使用Axios完成网络请求,也方便我们拦截处理。文本演示Express + Axios + Async hooks解决微服务间用户上下文传递的问题。

继续阅读→

NodeJS微服务APM

上微服务时,我们必需有全链路追踪、应用程序性能监测(APM)。开源的Elastic Stack是一个不错的选择,它包含日志、指标、APM、搜索、Kibana等。使用Elastic Stack做NodeJS APM时,使用起来非常方便,代码也无入侵。

只需在程序的前面添加一行代码: const apm = require('elastic-apm-node').start(); 然后添加环境变量ELASTIC_APM_SERVER_URL,正常启动程序: node index.js

能如此方便地使用,也是得益于NodeJS的事件模型、async_hookselastic-apm-node,其中的elastic-apm-node已经帮我们创建好同步或异步流程中的Transaction与Span。大部分时候,我们只需写好自己的业务代码。

样例代码:apm-nodejs-app-aapm-nodejs-app-bapm-nodejs-app-c

继续阅读→

微前端与SSR微服务

随着业务的发展,单页面应用(SPA)开发的前端系统也越来越复杂,这时需要多个团队并行开发。为了提高生产效率,每个团队需要能够独立开发、部署与维护,于是引入了与后端微服务相似的“微”架构:微前端与SSR微服务。即使一个团队,为了新特性不影响其它部分、能够更快速的上线,也引入了“微”架构。无逻辑的前端静态资源服务,就不在讨论之列。

本文主要探讨React与Vue的微前端 + SSR微服务

继续阅读→

为微前端Hack Vue Router

这几天研究一下Vue,看看在Vue中如何实现微前端。期间发现Vue Router v3比较坑:

  1. 只支持动态加载从根路由(parent)开始的嵌套路由,这限制了有路由的微前端颗粒必需从根路由开始。没有路由的微前端,不受这影响。😟
  2. 在导航守卫router.beforeEach之前,Vue Router已经闭包缓存本次的匹配路由,造成router.beforeEach中动态加载新路由也无法立即匹配到。

坑1,不好解决,等待Vue Router v4出炉就好,暂时使用大颗粒的含路由微前端。坑2,我们需要在router.beforeEach之前加载微前端APP相关的JS与路由注册。本文就介绍解决坑2的简单方法。

继续阅读→

Vue CLI构建Vue SSR

Vue SSR官方的指导教程只有简单的Webpack配置,没有指导如果使用Vue CLI来构建SSR。Vue CLI构建CSR的SPA比较方便,默认不支持构建SSR。好在Vue CLI的可定制性比较强,经过一番的摸索,终于成功使用Vue CLI构建Vue SSR。

在构建SSR之前,需要按照官方的指导完成代码的改造,让SSR与CSR代码复用。

继续阅读→

前端SSR复用CSR代码拆分

前端客户端渲染(CSR)时,一般都进行代码拆分,按需懒加载页面相关的JS/CSS与数据,交互体验比较好且容易开发。但是只进行CSR时,首屏显示比较缓慢。服务端渲染(SSR)时,一次请求能拿到页面完整的HTML内容,我们用来解决首屏显示缓慢的问题。同时使用CSR与SSR,就面临如何复用所有的代码,包含CSR代码拆分。

在React/Preact中,SSR复用CSR代码拆分有两种实现:@loadable/componentpreact-cli 。@loadable/component中使用NodeJS的require()动态加载JS文件,而preact-cli则直接静态打包到一个JS文件中。

继续阅读→

Redux中间件: ChanMiddleware

在开发客户端渲染(CSR)与服务端渲染(SSR)共用的前端代码时,需要使用Redux初始化状态。但是发现Redux-saga的take等函数只能在createStore()之后才能使用,不是很方便。于是,造一个跨组件通信的Redux side-effect中间件: ChanMiddleware 。

ChanMiddleware支持以下3个函数:

interface ChanHandler {
  (state?: any, action?: AnyAction, dispatch?: Dispatch, next?: () => void): void
}

const use = (type: string, handler: ChanHandler) => void;
const useOnce = (type: string, handler: ChanHandler) => void;
const unUse = (type: string, handler: ChanHandler) => void;

type等于'‘时,handler处理所有的Action。

继续阅读→

NodeJS C++插件开发体验(N-API)

NodeJS C++插件直接扩展NodeJS V8引擎,性能比JS要高很多。同时,通过N-API跨越JS与C++的边界,不需要做序列化/反序列化,性能代价也很小。根据二八法则,使用C++插件来解决NodeJS业务系统的性能问题/密集型计算,而不是完整业务系统的主要功能。

在开发NodeJS插件时,可以选择N-API、nan、或者内部V8接口实现。但是,N-API有良好的ABI兼容性,可确保插件一次编译能够在多个NodeJS版本中运行,更新NodeJS版本之后不需要重新编译插件。学习NodeJS插件开发,可参考官方的node-addon-examples

在本示例中,我们使用C++11 std与boost实现4个导出函数:

generateNumbers(n: number, callback: (v: number) => void): void;
joinStrings(arr: string[], sep: string): string;
isPrime(n: number) => boolean;
isPrimeAsync(n: number): Promise<boolean>;

本示例源码:napi-addon-1-hello-primes

继续阅读→