/images/avatar.png

LexusLee's blog

Golang 实现装饰器

Go 实现装饰器 类似于 Java 中的装饰器模式, 在 go 中也会有需要 patch 一个函数的需求. 一个常见的场景就是比如计算某个函数耗时的 decorator, 那么利用 functional programming 思想. 在 go 中的实现如下: 1 2 3 4 5 6 7 8 func timeSpent(inner func(n int) int) func(op int) int { return func(n int){ start := time.Now() ret := inner(n) fmt.Println("time spent: ", time.Since(start).Seconds()) return ret } } 当然实际场景中可能更多需要的是一种 pipeline 装饰器的用法, 比如一个 http handler 需要进行 Auth 认证, 认证通过后需要进行耗时计算, 计算完耗时需要进行 statsd 打点. 那么对应的实现如下:

坦率地讲 服务熔断 & 服务降级

坦率地讲 服务熔断 & 服务降级

背景

之前遇到个问题,发现一个系统如果拆分了太多业务类服务,或者依赖于大量的第三方服务,就很容易因为某个服务的故障导致整个系统不可用,比如

  • 模块中使用了 Elastic Search 进行监控,但是 ES 突然挂了,相关的 api 的调用报错导致级联的服务全部阻塞,那么应该要有规避由 ES 调用 raise 出的异常或者调用超时而导致整个模块或整个系统崩溃的保护措施。
  • 使用 AWS 或 阿里云 的 ECS 服务来作为 micro-service 的载体,但是 ECS 服务故障或者过载了导致整个业务链无法正常进行,那么应有对应的降级或者限制调用频度的方案来进行保护。

浅谈 Workflow 设计

浅谈 Workflow 设计 LexusLee 背景 最近刚接触到 workflow 相关的东西,之前都没有造过这方面的轮子,所以看了一些框架总结了一下我认为的好的 Workflow 的设计应该是怎样的。 什么是 Workflow ? Workflow 是一些可重复执行的事件按特定的顺序&路径组合成的事件流,这个组成的事件流通常是为了满足某一个流程较长的任务。 这些事件通常是不可再被细分,是具有原子性的。每个原子事件可能包含执行任务、文档或数据。这些事件按照提前声明好的规则组合起来就成了一个 Workflow . e.g. 如上图所示,Workflow 类似软件工程中的流程图,指定了每个节点可能出现的路径分支,节点执行的事情以及节点的终结状态。 如何设计 Workflow ? 比较经典的 Workflow design pattern 应该满足以下几个元素: 路径覆盖 事件原子性 有效的状态迁移 路径覆盖 路径覆盖是和节点状态相关的,通常的节点状态有如下几种: Start —— 开始 jobs ,标明 workflow 起点 Maybe —— 表示这个任务可能会执行,但不一定会执行,它的执行依赖于一定条件,比如上层节点的输出 Likely —— 和 Maybe 节点类似,但是比它的优先级更高,是作为与 Maybe 节点共享父节点的默认路径节点 Future —— 表示 workflow 执行体认为该路径一定会到达的节点,Future 节点的任务在不被 cancel 的情况下一定会执行 Waiting —— 表示当前任务是个阻塞任务,还在执行中,需要等待执行完毕才能进入下个路径 Ready —— 表示 Waiting 节点的任务已执行完,作为 Waiting 节点的 handler Complete —— 表示整个 workflow 的 Jobs 已经全部执行完毕,为终结节点 Cancel —— 表示任务被明确终止了,在状态迁移过程中不作为最终状态 事件原子性 pass

《向阳处的她》浩介先生终于有猫啦!

《向阳处的她》浩介先生终于有猫啦!

有一年的搞笑诺贝尔物理学奖颁给了课题:

「一只猫能同时处于固体状态和液体状态吗?」

通过第三人称视角研究了猫的各种形态,《向阳处的她》这部电影就给研究了一个狠狠的耳光。

关于关闭 Socket 的一些坑

关于关闭 Socket 的一些坑

LexusLee

背景

最近踩到一个 “Socket 连接持续处于 Fin_Wait2 和 Close_Wait 状态无法关闭” 的坑中。起因是在维护大量连接时调用 socket.close() 时,看到部分连接并没有正常关闭,而是从 ESTABLISHED 的状态变成 FIN_WAIT2 并且连接状态没有后续迁移,而对端的连接状态则是从 ESTABLISHED 变成了 CLOSE_WAIT