Kong熔断插件(未完成)

一、 熔断

理解熔断需要理解一下熔断要解决的问题 - 雪崩。

雪崩:分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况, 这种现象被称为服务雪崩效应。

系统的调用链如图所示。一旦下游服务C因某些原因变得不可用,积压了大量请求,服务B的请求线程也随之阻塞。线程资源逐渐耗尽,使得服务B也变得不可用。紧接着,服务A也变为不可用,整个调用链路被拖垮,这种调用链路的连锁故障,叫做雪崩。

那么就要思考了,如何解决雪崩呢?

二、 request-termination

function RequestTerminationHandler:access(conf)
  RequestTerminationHandler.super.access(self)

  local status  = conf.status_code
  local content = conf.body

  if content then
    local ctx = ngx.ctx
    if ctx.delay_response and not ctx.delayed_response then
      ctx.delayed_response = {
        status_code  = status,
        content      = content,
        content_type = conf.content_type,
      }

      ctx.delayed_response_callback = flush

      return
    end
  end

  return responses.send(status, conf.message)
end
复制代码

上面就是Kongrequest-termination的核心代码了,从access的逻辑可以分析:plugin从ctx中校验delay_response是否为true,如果delay_response(Boolean类型的标记量)和delayed_response(map类型)不为空的情况下,设置delayed_response_callback为flush函数。

ctx.delay_response 这个参数,它的原理就是把要执行的 handler wrap 在一个 coroutine 中,如果执行到一个插件需要 ngx.say 来提前执行 Nginx 的 content handler,那么它就会 yield 当前 coroutine,来延迟 content handler 的执行,并跳过之后需要执行的所有插件。这么做主要基于两点:

  • 如果请求被插件拦截就尽快退出「phase」循环。
  • 可以在输出 content 前,做一些自定义的操作。

这里没看懂(⊙﹏⊙)b,姑且猜测:熔断插件的access执行之前,会根据ctx中的标记位来决定是否需要继续执行工作,还是被拦截并按照配置的status和content放回response给客户端。

那么这里的标记位ctx.delay_response会在什么场景下被标记为true?或是ctx.delay_response初始化时就已经是true了,他的设计就是为了让请求从一个插件中跳出来,然后结束后续插件的执行。

function Kong.access()
  kong_global.set_phase(kong, PHASES.access)

  local ctx = ngx.ctx

  runloop.access.before(ctx)

  ctx.delay_response = true

  for plugin, plugin_conf in plugins_iterator(loaded_plugins, true) do
    if not ctx.delayed_response then
      kong_global.set_named_ctx(kong, "plugin", plugin_conf)
      kong_global.set_namespaced_log(kong, plugin.name)

      local err = coroutine.wrap(plugin.handler.access)(plugin.handler, plugin_conf)

      kong_global.reset_log(kong)

      if err then
        ctx.delay_response = false
        return responses.send_HTTP_INTERNAL_SERVER_ERROR(err)
      end
    end
  end
复制代码

参考:

  1. 漫画:什么是服务熔断?
  2. Kong 插件加载机制源码解析