EFK结构化日志
在分布式系统中,我们一般把日志集中收集到EFK或ELK中。默认情况下,Elasticsearch(ES)收集到的是一行一行日志文本,但是,这样的日志不方便业务检索,也没有充分发威ES的检索能力。
为了方便业务检索,我们做结构化日志,输出的内容均为JSON格式,经过Filebeat的简单处理,扔给ES存储与建立索引。查看日志时,可以对特定的业务字段做过滤,比如: user.id: 123
。 日志输出格式如下,一条日志一行JSON:
个人博客,记录软件技术与程序员的点点滴滴。
在分布式系统中,我们一般把日志集中收集到EFK或ELK中。默认情况下,Elasticsearch(ES)收集到的是一行一行日志文本,但是,这样的日志不方便业务检索,也没有充分发威ES的检索能力。
为了方便业务检索,我们做结构化日志,输出的内容均为JSON格式,经过Filebeat的简单处理,扔给ES存储与建立索引。查看日志时,可以对特定的业务字段做过滤,比如: user.id: 123
。 日志输出格式如下,一条日志一行JSON:
最近一个多月都在忙于项目,没有时间记录新的知识。我们起了一个全新的前端项目,技术选型是React + SSR + Dva。要求的起点也比较高:用户导航首屏SSR,其它时候CSR;代码要求SSR与CSR复用;所有的请求经过Node层;页面显示、接口请求均要求小于1秒。
为了容易定位调用链路的性能点,我们加入了Jaeger Open Tracing,这就涉及到链路追踪上下文的传递。
继续阅读→后端包含众多微服务时,如果每个微服务都是自己去查询用户信息(比如: 用户ID、登录名),会造成用户微服务压力过大、响应延时增大。为了解决这类问题,可以在网关服务中查询用户信息等共用信息,然后传递到其它的微服务中,微服务之间也相互传递。
为了前端代码复用,在NodeJS中也使用Axios完成网络请求,也方便我们拦截处理。文本演示Express + Axios + Async hooks解决微服务间用户上下文传递的问题。
继续阅读→上微服务时,我们必需有全链路追踪、应用程序性能监测(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_hooks
与elastic-apm-node
,其中的elastic-apm-node
已经帮我们创建好同步或异步流程中的Transaction与Span。大部分时候,我们只需写好自己的业务代码。
样例代码:apm-nodejs-app-a、apm-nodejs-app-b、apm-nodejs-app-c
继续阅读→随着业务的发展,单页面应用(SPA)开发的前端系统也越来越复杂,这时需要多个团队并行开发。为了提高生产效率,每个团队需要能够独立开发、部署与维护,于是引入了与后端微服务相似的“微”架构:微前端与SSR微服务。即使一个团队,为了新特性不影响其它部分、能够更快速的上线,也引入了“微”架构。无逻辑的前端静态资源服务,就不在讨论之列。
本文主要探讨React与Vue的微前端 + SSR微服务
。
这几天研究一下Vue,看看在Vue中如何实现微前端。期间发现Vue Router v3比较坑:
坑1,不好解决,等待Vue Router v4出炉就好,暂时使用大颗粒的含路由微前端。坑2,我们需要在router.beforeEach之前加载微前端APP相关的JS与路由注册。本文就介绍解决坑2的简单方法。
继续阅读→Vue SSR官方的指导教程只有简单的Webpack配置,没有指导如果使用Vue CLI来构建SSR。Vue CLI构建CSR的SPA比较方便,默认不支持构建SSR。好在Vue CLI的可定制性比较强,经过一番的摸索,终于成功使用Vue CLI构建Vue SSR。
在构建SSR之前,需要按照官方的指导完成代码的改造,让SSR与CSR代码复用。
继续阅读→前端客户端渲染(CSR)时,一般都进行代码拆分,按需懒加载页面相关的JS/CSS与数据,交互体验比较好且容易开发。但是只进行CSR时,首屏显示比较缓慢。服务端渲染(SSR)时,一次请求能拿到页面完整的HTML内容,我们用来解决首屏显示缓慢的问题。同时使用CSR与SSR,就面临如何复用所有的代码,包含CSR代码拆分。
在React/Preact中,SSR复用CSR代码拆分有两种实现:@loadable/component与preact-cli 。@loadable/component中使用NodeJS的require()动态加载JS文件,而preact-cli则直接静态打包到一个JS文件中。
继续阅读→在开发客户端渲染(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++插件直接扩展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
继续阅读→