it编程 > 软件设计 > 架构设计

方正证券-金融科技云原生微服务建设实践

150人参与 2024-08-06 架构设计

概述:本文将详细介绍方正证券金融科技工程院在云原生微服务建设实践经验,分享包含 3 个方面:

  1. 微服务治理工作
  2. 微服务可观测性工作
  3. 微服务接口管理 上述能力统一集成到了方正公司的夸克开发平台上。

方正证券微服务建设实践介绍

2023 年年初我们启动了微服务体系建设,其中注册中心采用的 zookeeper,web 和 rpc 应用框架分别采用的 cloudwego 的 hertz  kitex

目前我们进入到了微服务建设的深水区,主要涉及到微服务治理可观测性能力接口管理等相关工作内容,下面将分别从概念、实现原理等方面来详细介绍。

微服务治理能力建设

概念

微服务架构下,随着业务量的逐步增加,服务的数量也会逐步增加。基于此背景,随着业务的发展,对服务的管控难度会越来越大,服务治理的作用就是为了解决服务拆分所引发的一系列问题,以让服务更稳定地运行,涉及的主题包含了服务注册与发现、负载均衡、服务熔断、服务降级、服务限流等。 夸克平台提供的超时、重试以及服务端限流的功能,均基于 kitex 的相关能力而来,目前所使用的注册中心为 zookeeper(缩写 zk),因此相关的动态配置也是借助 zk 来实现,通过将配置写入到 zk,来通知 server 端、client 端完成相关功能的开启。

介绍

  1. 流量控制

    流量控制的粒度为服务级别,下图所示中,该服务每秒最多处理1000个请求,超额的请求将被直接关闭掉: huaxing_ratelimit

  2. 重试配置

    重试配置的粒度为方法级别,用来配置当前服务对指定服务的某个方法发出的请求失败的情况下,如何进行重试: huaxing_retry

  3. 超时配置

    超时配置的粒度为方法级别,用来配置当前服务对指定服务的某个方法请求的最大耗时,超过该值时,当前服务会断开连接: huaxing_timeout 各个配置的具体作用详见配置说明

实现原理与细节

server 端、client 端均通过扩展 kitex 的 suite 来完成相关配置的动态注入。

server端

通过如下代码对 kitex server 进行配置:

server.withsuite(zookeeperserver.newsuite("kitex-server", zookeeperclient))
copy

其中,zookeeperserver.newsuite("kitex-server", zookeeperclient)会返回一个suite实例,注入给服务器的 options 中包含了limiter配置:

func (s *zookeeperserversuite) options() []server.option {
    opts := make([]server.option, 0, 2)
    // withlimiter实现中,在zk中注册了监听器,每当数据变化,动态更新limiter的相关配置,以达到限流目的
    opts = append(opts, withlimiter(s.service, s.zookeeperclient, s.opts))
    return opts
}
copy

基于以上内容,可以发现,server 端的 suite 中默认只配置了 limiter,kitex 框架目前只支持两类 limiter:

  1. connections limiter(限制最大连接数量)
  2. qps limiter(限制最大qps)

在使用 zk 作为注册中心时,两者都可以通过配置动态调整,变化之后配置值均通过 zk 的监听器获取到:

// zk数据变化时的回调方法
onchangecallback := func(restoredefault bool, data string, parser zookeeper.configparser) {
   lc := &limiter.limiterconfig{}
   if !restoredefault && data != "" {
      err := parser.decode(data, lc)
      if err != nil {
         klog.warnf("[zookeeper] %s server zookeeper config: unmarshal data %s failed: %s, skip...", dest, data, err)
         return
      }
   }
   // 将zk中的数据动态更新到配置中
   opt.maxconnections = int(lc.connectionlimit)
   opt.maxqps = int(lc.qpslimit)
   u := updater.load()
   if u == nil {
      klog.warnf("[zookeeper] %s server zookeeper limiter config failed as the updater is empty", dest)
      return
   }
   if !u.(limit.updater).updatelimit(opt) {
      klog.warnf("[zookeeper] %s server zookeeper limiter config: data %s may do not take affect", dest, data)
   }
}
// path,对于limiter,其值为:/kitexconfig/{servicename}/limit
zookeeperclient.registerconfigcallback(context.background(), path, uniqueid, onchangecallback)
copy

client端

类似 server 端,client 端也有同样的配置:

bizservice.newclient("kitex-client",
client.withsuite(zookeeperclient.newsuite("kitex-server", "kitex-client", zookeeperclient)))
copy

client 端的 suite,包含的 option 如下:

func (s *zookeeperclientsuite) options() []client.option {
    opts := make([]client.option, 0, 7)
    opts = append(opts, withretrypolicy(s.service, s.client, s.zookeeperclient, s.opts)...)
    opts = append(opts, withrpctimeout(s.service, s.client, s.zookeeperclient, s.opts)...)
    opts = append(opts, withcircuitbreaker(s.service, s.client, s.zookeeperclient, s.opts)...)
    return opts
}
copy

即,客户端支持重试、超时、熔断三种动态配置。相关的处理均是通过zk客户端的回调方法来达到动态更新的效果。

超时配置的额外说明

对于超时,其配置方法的具体实现如下:

func withrpctimeout(dest, src string, zookeeperclient zookeeper.client, opts utils.options) []client.option {
    // ...
    return []client.option{
        client.withtimeoutprovider(initrpctimeoutcontainer(path, uid, dest, zookeeperclient)),
        client.withclosecallbacks(func() error {
            // cancel the configuration listener when client is closed.
            zookeeperclient.deregisterconfig(path, uid)
            return nil
        }),
    }
}
copy

最终通过调用 kitex 提供的client.withtimeoutprovider方法来完成超时相关的具体配置。对于超时,存在以下不同的配置方法:

func withrpctimeout(d time.duration) option {
    // ...
}

func withconnecttimeout(d time.duration) option {
    // ...
}

func withtimeoutprovider(p rpcinfo.timeoutprovider) option {
    // ...
}
copy

其中,withtimeoutprovider设置的超时时间会被withrpctimeoutwithconnecttimeout设置的值所覆盖,因此如果在创建 kitex client 时,调用过withrpctimeout或者withconnecttimeout,会导致动态配置无法生效。

配置说明

超时

对应的zk节点:/kitexconfig/{clientname}/{servicename}/rpc_timeout

写入的配置格式如下:

{
  "*": {
    "conn_timeout_ms": 100,
    "rpc_timeout_ms": 800
  },
  "getdemoinfo": {
    "rpc_timeout_ms": 300
  },
  "getdemoinfo3": {
    "rpc_timeout_ms": 300
  }
}
copy

字段含义 conn_timeout_ms:建立一条新连接的最大等待时间; rpc_timeout_ms:一次 rpc 调用的最大用时;

重试

对应的zk节点:/kitexconfig/{clientname}/{servicename}/retry

写入的配置格式如下:

{
  "getdemoinfo": {
    "enable": true,
    "type": 0,
    "failure_policy": {
      "stop_policy": {
        "max_retry_times": 2,
        "max_duration_ms": 9000,
        "cb_policy": {
          "error_rate": 0.1
        }
      }
    }
  },
  "getdemoinfo5": {
    "enable": true,
    "type": 0,
    "failure_policy": {
      "stop_policy": {
        "max_retry_times": 2,
        "max_duration_ms": 9000,
        "cb_policy": {
          "error_rate": 0.1
        }
      }
    }
  }
}
copy

字段含义

配置项 默认值 说明 限制
max_retry_times 2 最大重试次数,不包含首次请求。如果配置为 0 表示停止重试。 合法值:[0-5]
max_duration_ms 0 累计最大耗时,包括首次失败请求和重试请求耗时,如果耗时达到了限制的时间则停止后续的重试。0 表示无限制。注意:如果配置,该配置项必须大于请求超时时间。  
error_rate 10% 重试熔断错误率阈值, 方法级别请求错误率超过阈值则停止重试。 合法值:(0-30%]

限流

此配置为服务全局配置,因此 zk 节点路径只包含 servicename:/kitexconfig/{servicename}/limit

写入的配置格式如下:

{
  "qps_limit": 100
}
copy

微服务可观测性能力建设

概念

服务观测性建设指的是在分布式系统中建立和完善监控、日志、追踪等工具和技术,以便全面、及时地了解系统的运行状态和性能指标。

一个完善的观测性工具,可以为业务系统带来诸多好处:

  1. 能及时发现和解决问题;
  2. 使团队能够更清晰地了解系统的整体运行情况和内部交互关系;
  3. 可以了解系统的负载情况、资源利用率和趋势变化,以支持容量规划和资源优化;
  4. 通过日志和追踪系统记录系统的操作日志和请求轨迹,可以跟踪和分析用户操作行为、异常请求和安全事件,提高系统的安全性和可靠性。

介绍

服务详细信息,用来展示服务本身的整体运行情况,包含了黄金监控指标(qps、latency和 error ratio)、slo 和 runtime相关信息等: huaxing_grafana

拓扑图,用来展示服务间的上下游依赖关系: huaxing_topology

调用链数据,包含了服务间每次调用的详细信息: huaxing_trace

实现原理与细节

huaxing_otel

目前模板代码中已经集成了 opentelemetry 客户端,生成的 hertzkitex 服务默认拥有可观测数据(metrics + tracing)上报能力。

详细信息可以参考:kitex-contrib/obs-opentelemetry  hertz-contrib/obs-opentelemetry

trace( 跟踪)

tracing 提供了从请求开始接收到处理完毕的整个生命周期的全貌。

服务在接收到请求后,从元信息(kitex)或 http header(hertz)中启用链路追踪。如果元信息或 http header 中没有 tracing 信息,将自动启用新的链路追踪。服务进程内通过 context 来传递链路信息。

接入方式:

// for hertz
tracer, cfg := hertztracing.newservertracer()
h := server.default(tracer)
h.use(hertztracing.servermiddleware(cfg))
copy
// for kitex
svr := echo.newserver(new(demoimpl),
    server.withsuite(tracing.newserversuite()),
    server.withserverbasicinfo(&rpcinfo.endpointbasicinfo{servicename: servicename}),)
copy

tracing 信息上报到 opentelemetry collector 中,然后透传给 jaeger。可以在 jaeger 中查询链路相关信息。

提供统一的日志打印器 fzlog,默认打印 tracing 的相关信息。

{
  "file": "get_repositories.go:33",
  "func": "gitlab.fzzqft.com/ifte-quark/quark-api/biz/service.(*getrepositoriesservice).run",
  "level": "info",
  "msg": "getrepositoriesservice run req: page:1 limit:10 service_name:\"kitex\"",
  "span_id": "aa26bab58cdf6806",
  "time": "2024-04-23 15:59:40.609",
  "trace_flags": "01",
  "trace_id": "f714dbe2a96b1882dfc4b81909e55643"
}
copy

日志被采集处理后,可以在日志平台上通过 trace_id 来查询整个链路的相关日志信息。

metrics(指标)

metrics 是衡量系统性能和行为的关键数据,如请求速率、响应时间、错误率等。指标通常被收集、聚合和可视化,以便监视系统的健康状况并进行趋势分析。

目前,每个服务各自上报自身的 metrics 数据,统一存储在 prometheus/victoriametrics 中,最终使用 grafana 形成监控面板。

下面通过qps、请求耗时、错误率这三个常见的服务描述指标来展示如何使用服务上报的 metrics 数据。

拓扑图

通过聚合中提到的 metric 数据来展示整体的服务间依赖关系,上报数据中有service_name以及sourcetarget信息,通过 promsql 的sum操作符即可获取到服务上下游信息。

微服务接口管理能力建设

概念

介绍

实现原理与细节

小结

目前的微服务体系已经能满足大部分的技术类需求,但是在云原生的体系之下计划走得更远一些:

  1. 服务治理,依赖云原生服务网格(servicemesh)能力来治理流量,同时把其他应用框架的东西向的流量一起纳入进来。
  2. 可观测性,opentelemetry 是一套与语言无关、与应用框架无关的解决方案,通过统一语义,计划将 java 的 web(springboot)和 rpc(dubbo)体系一起纳管进来。
  3. 接口管理,未来计划将 rpc 和 http 接口统一管理,自动生成接口用例。

近期活动

诚挚邀请企业用户和开发者共同参与 cloudwego 技术沙龙。活动将于2024525日(周六)在上海举办,邀请广大技术同仁共同探讨 云原生xai 浪潮之下,企业如何构建云原生微服务架构,来支持产品的快速迭代与发展。扫描图片二维码即刻报名,不见不散!

 

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

ETL数据集成丨将GreenPlum数据同步至Doris数仓

08-06

龙蜥社区 7 月度运营大事件回顾

08-06

志愿者招募|邀你一起成就 2024 龙蜥操作系统大会

08-06

龙蜥社区第五届理事大会圆满结束!深度探讨 AI 浪潮下的合作模式

08-04

河道高效治理新策略:视频AI智能监控如何助力河污防治

08-04

爱奇艺广告特征评估流程优化实践

08-04

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论