Node 中异常收集与监控

在一个后端服务设计中,异常捕获是必不可少需要考虑的因素

而当异常发生时,能够第一时间捕捉到并且能够获得足够的信息定位到问题至关重要 这也是本篇文章的内容

刚开始,先抛出两个问题

  1. 在生产环境中后端连接的数据库挂了,是否能够第一时间收到通知并定位到问题,而不是等到用户反馈之后又用了半天时间才找到问题 (虽然运维肯定会在第一时间知道数据库挂了)
  2. 在生产环境中有一条 API 出了问题,能否衡量该错误的紧急重要程度,并根据报告解决问题


异常监控服务 Sentry 的部署

Sentry 是一个使用 python 写的异常监控服务,并有支持很多语言的 SDK。

这里有官方部署文档和 compose file: https://github.com/getsentry/onpremise

在当前部署 sentry 时 (2019/06/20),文档处于这个 commit 的位置 https://github.com/getsentry/onpremise/tree/ae39a61d4d8a8ec8b9fd7af9c1d64e80c9bdd640

虽然每次部署服务时的首选是看看有没有官方以及社区 star 较多的 compose file,但是他们的 compose file 也是要大致看一看的

重设用户表的 ID

GET /users/:ID 是一个非常典型的 REST API。最近在浏览我的应用时,经常会有

> GET /users/3 HTTP/1.1
> Host: shanyue.tech
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
...

而我的用户表的 ID 采用了整型自增的数据类型,为了使我的网站的用户数看起来不太寒碜,我绝对把我的用户 id 拉长一些!

sed 命令实践: 升级 sequelize.js 时批量替换字符串

sequelize 是 Node 中使用比较多的一个 ORM 库,最近计划将项目中的 sequelize 升级至 V5 版本。

根据 升级文档,其中一项是即将禁用 String based operators,使用 Sequelize.Op 等 Symbol operators 来代替。

operator 主要用在查询条件中,用以生成查询条件,如

const where = {
  age: {
    $lte: 10 
  }
}

// 替换为
const replaceWhere = {
  age: {
    [Op.lte]: 10
  }
}

typescript 高级技巧

用了一段时间的 typescript 之后,深感中大型项目中 typescript 的必要性,它能够提前在编译期避免许多 bug,如很恶心的拼写问题。而越来越多的 package 也开始使用 ts,学习 ts 已是势在必行。

以下是我在工作中总结到的比较实用的 typescript 技巧。

如何实现类似 lodash 的 get 与 merge 函数

lodash 基本上成为了写 javascript 工具库的标配,它广泛应用在各种服务端以及前端应用中,但是它的包体积略大了一些。对于服务端来说,包的体积并不是十分的重要,或者换句话说,不像前端那样对包的体积特别敏感,一分一毫都会影响页面打开的性能,从而影响用户体验。

正因为前端包体积对于用户体验的重要性,因此有各种各样减小包体积的方法。针对 lodash 来说,你完全不必要引入 lodash 的所有工具函数,你只需要按需引入或者直接使用单函数包。关于按需引入你可以参考以下文章

Lessons on tree-shaking Lodash with Webpack and Babel

在针对我的个人站点中的 lodash 进行优化时,如果没记错的话,lodash 从以前 gzip 后的 80KB 变为了 20KB,相对来说还是比较大。而当我全局搜索了 lodash 的引用之后,发现 90% 的场景都是在使用 _.get

另外,随着 ES6+ 的发展,以及浏览器与 Node 对它的支持,很多 lodash 的函数都很容易自己来实现或者说已被实现,如 _.assign_.trim_.startsWith 等等已被 ES6+ 实现,而 _.uniq 又很容易通过 new Set() 来解决。有人就在 github 上总结了 you-dont-need/You-Dont-Need-Lodash-Underscore,其中囊括了很多工具函数很简易的实现。

从数据库到前端,使用 enum 代替 constant number

在我经历过的几个以node为主的后端项目中,都有一个文件 constant.js。顾名思义,里边保存着各种常量,而大多是字符串与数字的对应关系。

但是在实际工作中,根据数字来调试相当费劲,先不说后端代码中 where (status === 1) 这种可避免的神奇操作。(PS: 虽然我在吐槽它,但是有时我也会犯,给后来不熟悉业务者一脸懵逼…)。在数据库中查询也会遇到一些问题。

[登录那些事] 邮件发送,限流,漏桶与令牌桶

前段时间,我使用了 jwt 来实现邮箱验证码的校验与用户认证与登录,还特别写了一篇文章作为总结。

在那篇文章中,提到了一个点,如何限速。

在短信验证码和邮箱验证码,如果不限速,被恶意攻击造成大量的 QPS,不仅拖垮了服务,也会心疼如水的资费。鉴于君子固穷的原则,在我的邮箱服务里加上限速。

关于如何限速,有两个比较出名的算法,漏桶算法与令牌桶算法,这里对其简单介绍一下,最后再实践在我发邮件的API中

scala 入门指南

前言

环境

如果你正在学习或者只想敲几个示例,那么强烈推荐 Scastie,一个嵌在浏览器中的线上编辑器。

如果你更喜欢 REPL 环境在自己的 scala shell 中学习和测试,则需要首先安装 sbt,使用 sbt 进入 scala shell。

jwt 实践邮件验证与登录

去年我写了一篇介绍 jwt文章

文章指出如果没有特别的用户注销及单用户多设备登录的需求,可以使用 jwt,而 jwt 的最大的特征就是无状态,且不加密。

除了用户登录方面外,还可以使用 jwt 验证邮箱验证码,其实也可以验证手机验证码,但是鉴于我囊中羞涩,只能验证邮箱了。

另外,我已在我的试验田进行了实践,不过目前前端代码写的比较简陋,甚至没有失败的回馈提示。至于为什么前端写的简陋,完全是因为前端的代码量相比后端来讲实在过于庞大…

另外,如果你熟悉 graphql,也可以在本项目的 graphql-playground 中查看效果。

博客域名更换操作记录

拖延了半年后,我终于在最近把我的域名 https://shanyue.tech 通过了备案。新域名可以更好的贴合我的博客,趁此对我的域名进行更换

如果刚开始就使用新域名,倒是很简单。但是更换域名就需要做一些额外的琐碎的东西了,记录一下

使用纯 CSS 实现仿 Material Design 的 input 过渡效果

以前一段时间,基于对 nextgraphql 的调研,再加上本人的兴趣,我做了一个站点,也作为我以后各种技术折腾,实践以及兴趣交汇的试验田。

最近我需要在我的实验田使用 jwt 实践校验码的功能。校验码,就是指注册时邮箱或者短信的校验码。需要校验码则需要有登录注册,而在登录注册时,为了多写一些 CSS,我决定实现一个 Material Design 的表单过渡效果。

实现效果见 诗词弦歌 - 登录

开始之前,你先看看是否认识以下几个选择器。如果不,那么通过本文你可以学习到以下几个选择器,以及他们的试用场景

  • :not(:empty)
  • input:not([value=""])
  • input:valid
  • input:not(:placeholder-shown)



记录一个有关 curl 和 tar 的小问题

这是我今天在工作时遇到的一个有关解压的问题,先还原下问题

今天在解压一个压缩包时解压失败,以下是命令以及失败提示

$ curl -O https://github.com/alibaba/canal/releases/download/canal-1.1.3/canal.deployer-1.1.3.tar.gz
$ tar -zxvf canal.deployer-1.1.3.tar.gz

gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now

这里首先提示,造成这个问题的原因以及解决方案很简单,对你很有可能没有借鉴意义。不过寻找原因的过程以及从这个问题上学到的东西还是有点意思的。

kafka 从入门到入门

最近工作中需要使用到 Kafka,基于 mysqlbin logpostgresWAL log 把数据发布到 KafkaKafka 另外一大用途主要用作消息中间件,虽然没有在业务系统中使用它作为消息队列,但这也是一个令人心动的功能。趁此契机,从环境搭建,系统原理,到生产使用再系统过一遍 Kafka

flutter 入门指南

flutter

flutter 的出现不得不说是激动人心的,你可以以 React-Style 的方式写多端应用。而相比 RN 而言,它自身的版本迭代也比较积极。

由 GraphQL 来思考 API Design

目前我已经写了一年多 graphql,也时常思考和 Rest API 的不同,以及对 API Design 的启发。

他山之石可以攻玉。qraphql 一些天然的设计或者思想对写 Rest API 有很大的借鉴或参考意义。

这里总结下一些受启发的 API 设计规范。

浏览器中的二进制以及相关转换

浏览器中的二进制以及相关转换

最近工作中遇到了很多有关二进制的处理,如PDF的生成,多个PDF的打包,音频的拼接。为了数据的一致性,以及减少与后端通信的复杂度,工作量都在浏览器端。

浏览器,或者前端更多处理的是 View 层,即 UI = f(state),状态至界面的转化。但是也有很多关于二进制的处理,如

  • 下载 Excel
  • 文档生成 PDF
  • 对多个文件打包下载



如何使用 docker 高效部署前端应用

docker 变得越来越流行,它可以轻便灵活地隔离环境,进行扩容,方便运维管理。对开发者也更方便开发,测试与部署。

最重要的是, 当你面对一个陌生的项目,你可以照着 Dockerfile,甚至不看文档(文档也不一定全,全也不一定对)就可以很快让它在本地跑起来。

vim 快速入门

有一个段子。

如何快速学会游泳?

只需要三步,骗到河边,踢下水,用竹竿戳远点。

那如何快速学会 vim 呢?

默认编辑器设为 vim,删掉其他一切编辑器,明天上线。

以下是能够在 零配置零插件 下快速使用 vim 的一系列步骤,只需要多加练习,便能快速熟练使用 vim。 无他,唯手熟尔。

使用 Postman 做 API 自动化测试

Postman 最基本的功能用来重放请求,并且配合良好的 response 格式化工具。

高级点的用法可以使用 Postman 生成各个语言的脚本,还可以抓包,认证,传输文件。

仅仅做到这些还不能够满足一个系统的开发,或者说过于琐碎,你仍需要频繁地在开发环境,测试环境,生产环境中来回切换。单一的请求也不够,你需要维护系统所有 API 的请求,并且每个请求还带有不同的 querystringbody

30分钟SQL入门指南

本篇文章是 SQL 必知必会 的读书笔记,SQL必知必会的英文名叫做 Sams Teach Yourself in 10 Minutes 。但是,我肯定是不能够在10分钟就能学会本书所有涉及到的sql,所以就起个名字叫30分钟学会SQL语句(其实半个小时也没有学会…)。

You-Dont-Know-JS 疑难汇总

最近我看了 You-Dont-Know-JS 的两个小册,在看书的过程中,为了方便以后索引与更深入的了解,也为了避免遗忘,我对每一册的较为复杂的点做了总结,编辑如下。

[翻译] Grid 布局完全指南

原文链接见 山月的博客

英文链接

简介

CSS 栅格布局 (亦称 “Grid”),是一个基于栅格的二维布局系统,旨在彻底改变基于网格用户界面的设计。CSS 一直以来并没有把布局做的足够好。刚开始,我们使用 tables,后来是 floats,positioning 和 inline-block,这些本质上是一些 hacks 而且许多重要功能尚未解决(例如垂直居中)。Flexbox 可以做到这些,但是它主要用来一些简单的一维布局,并不适合复杂的二维布局(当然 Flexbox 与 Grid 可以一并使用)。Grid 是第一个为了解决布局问题的 CSS 模块,只要我们做过网页,就会遇到这些问题。

使用 Grid 进行常见布局

grid 布局是W3C提出的一个二维布局系统,通过 display: grid 来设置使用,对于以前一些复杂的布局能够得到更简单的解决。本篇文章通过几个布局来对对 grid 布局进行一个简单的了解。目前,grid 仅仅只有 Edge使用前缀能够支持,为了更好地体验,可以使用 Chrome 浏览器,在 chrome://flags 开启 #enable-experimental-web-platform-features 选项。

使用 Grid 进行常见布局示例

Grid Layout [class^=grid] { background-image: linear-gradient(90deg, #F5F5F5 4.16666667%, #fdfdfd 4.16666667%, #fdfdfd 8.33333333%, #F5F5F5 8.33333333%, #F5F5F5 12.5%, #fdfdfd 12.5%, #fdfdfd 16.66666667%, #F5F5F5 16.66666667%, #F5F5F5 20.83333333%, #fdfdfd 20.83333333%, #fdfdfd 25%, #F5F5F5 25%, #F5F5F5 29.16666667%, #fdfdfd 29.16666667%, #fdfdfd 33.33333333%, #F5F5F5 33.33333333%, #F5F5F5 37.5%, #fdfdfd 37.5%, #fdfdfd 41.66666667%, #F5F5F5 41.66666667%, #F5F5F5 45.83333333%, #fdfdfd 45.83333333%, #fdfdfd 50%, #F5F5F5 50%, #F5F5F5 54.16666667%, #fdfdfd 54.16666667%, #fdfdfd 58.33333333%, #F5F5F5 58.33333333%, #F5F5F5 62.5%, #fdfdfd 62.5%, #fdfdfd 66.