腾博会官网

【数据猿|金猿案例展】昆仑银行——一体化智能可观测平台全面保障昆仑银行业务稳定性

2024-01-18

根据中国人民银行 ,中国银保监会颁布的【关于金融行业贯彻<推进互联网协议第六版(IPv6)规模部署行动计划>的实施意见】要求 ,2019 年底金融服务机构门户网站需要支持 IPv6 连接访问 。2020 年底 ,金融服务机构面向公众服务的互联网应用系统支持 IPv6 连接访问 ,并具备与 IPv6 改造前同等的业务连续性保障 。2021 年起 ,在做好金融行业面向公众服务的互联网应用系统 IPv6 改造基础上 ,持续推进 IPv6 规模部署 ,逐步构建高速率 ,广普及 ,全覆盖 ,智能化的下一代互联网 。我行已根据规定 ,完成了 IPV6 的改造 。目前我行拨测监控已验证 IPV6 与 IPV4 线路连接上的性能差距 ,并实现从用户端监控 IPV6 与 IPV4 质量的功能 。

2022年腾博会官网应用性能监控平台建设覆盖了后端服务监控 、手机APP监控 、WEB前端监控 。其中包括 24个业务系统后端监控探针部署 ,4 个 APP 前端监控 SDK 部署(包括手机银行 、直销银行 、统一移动平台 、小昆在线 ,共抓取 90 万月活) 、PAAS 云平台 4 套业务系统(10 个探针) ,WEB 前端 H5 监控 JS 引用库部署(党建系统 ,70 万 PV/年) 。应用性能监控还实现了性能监控视图 、与 CMDB 接口对接 、与一体化运维平台接口对接和业务拨测等功能 。

实施时间 :

项目开始时间 :2022年

项目完结时间 :2023年

应用场景

通过2019年应用性能监控平台建设 ,昆仑银行目前已完成对二十余套业务系统 ,两个手机APP ,一个Web页面的性能监控 ,以及16套系统 、39个城市 、3个运营商的拨测任务 。主要应用于以下场景 :

1 、生产环境监控 :帮助行内开发团队实时监测生产环境中的应用程序性能 ,包括响应时间 、吞吐量 、错误率等指标 。通过监控 ,可以及时发现并解决潜在的性能问题 ,确保应用程序在高负载和高并发场景下的稳定性和可靠性 。

2 、故障排查和问题定位 :当应用程序出现故障或性能问题时 ,通过性能监控提供详细的指标和报告 ,帮助开发团队快速定位问题的根本原因 。通过分析监控数据 ,可以找到瓶颈所在 ,并采取相应的措施来修复问题 ,提高应用程序的表现和可用性 。

3 、用户体验改进 :应用性能监控可以跟踪用户在应用程序中的操作和体验 ,分析用户行为和反馈 ,了解用户对应用程序的满意度和痛点 。通过结合性能数据和用户反馈 ,开发团队可以优化应用界面和用户交互 ,提升用户体验 ,增强用户对应用程序的忠诚度和满意度 。

综上所述 ,本项目旨在帮助行内开发团队实时了解应用程序的性能 ,及时发现和解决问题 ,提高应用程序的可用性 、可维护性和用户体验 。

面临挑战

1 、复杂的系统架构 :昆仑银行拥有庞大而复杂的系统架构 ,包括核心银行系统 、支付系统 、风险管理系统等 。这些系统之间存在着复杂的依赖关系和集成需求 ,使得运维工作变得更加困难 。

2 、数据管理和一致性 :昆仑银行业务涉及大量的数据 ,包括客户信息 、交易记录等 。然而 ,这些数据可能分散在不同的系统和数据库中 ,格式不统一 ,导致数据孤立和难以进行全面的数据分析 。

3 、业务需求变化 :银行业务需求经常发生变化 ,例如推出新产品 、调整服务模式等 。需要灵活应对这些变化 ,并及时调整系统配置和功能以满足业务需求 。

4 、系统的稳定性 :银行系统的可靠性和稳定性对业务连续性至关重要 。昆仑银行需要建立完善的技术架构和运维体系 ,确保系统的稳定运行 ,同时能够快速应对各种突发事件 。

5 、业务需求变化迅速 :银行业务需求变化迅速 ,昆仑银行需要建立灵活的IT架构和运维流程 ,以支持业务的快速发展 。

6 、内部协调与沟通 :银行内部存在多个部门和团队 ,彼此之间需要密切协作和沟通 。需要与其他部门合作 ,共同解决问题并推动项目的顺利实施 。

数据支持

截止目前为止 ,昆仑银行应用性能监控项目生产环境探针采集的数据量达2T ,日处理数据量达100G ,数据来源为行内受应用性能系统监控的应用系统 ,手机APP ,Web页面 ,数据类型分为指标性数据 、会话 、调用链 、小文件 、快照 、拓扑关系 、配置信息等等 ,针对不同的数据类型有不同的数据保存周期 。

应用技术与实施过程

昆仑银行使用腾博会官网的Bonree Server 、Bonree SDK 、Bonree Browser平台分别实现对应用系统 ,手机APP ,Web页面的监控 。三个平台均由客户端及服务端组成 ,在客户端通过注入探针来获取客户端的数据 ,上报到服务端 ,由服务端对数据进行分析处理 ,最终展示出来 。

Bonree 产品总体设计采用分层架构的方式 ,层与层之间实现的功能不同 、设计原则与侧重方向也不一样 :

⚫ 数据采集层

数据采集层通过以探针的方式采集各项性能指标数据 ,主要侧重数据采集的准确性 ,在此基础上不能影响客户环境的稳定运行 。

⚫ 数据处理层

数据处理层对探针采集到的各项性能指标数据进行处理 、分类规整和入库 ,主要侧重稳定性 、高性能和高可扩展 。

⚫ 数据存储层

数据存储层主要集中在数据的存储 ,通过引入不同的存储结构 ,分类存储不同的信息 ,主要侧重数据存储的可靠性 ,稳定性和高性能 。

⚫ 数据展示层

数据展示层向客户展示各个维度的性能指标数据 ,架构上主要侧重可用性 、实时性和UI友好性 。

image-1705546718653图1 Bonree Server平台架构展示

image-1705546739163图2 Bonree SDK平台架构展示

image-1705546754200图3 Bonree Browser平台架构展示

Bonree产品主要有如下几个核心模块组成 ,分别是 :

● 探针(Agent 、SDK)

● 数据处理器(CONTROLLER

● 数据处理存储中心

● 平台(Server 、SDK 、Browser)

● AIOps智能告警/事件分析

组件间数据流如下

image-1705546768311图4 组件间数据流向

探针模块

探针主要是负责采集服务端 ,APP端以及Web端相关数据 ,包括访问次数 、请求性能 、异常访问 、以及错误详情等等 。

数据收集器(CONTROLLER)

Controller 作为探针接入和数据处理组件 ,接收探针端上报的各项指标数据 ,完成对指标数据的分类处理与入库 、探针配置的下发 。探针与 Controller 交互主要包括配置流 Config 和数据流 Upload 两类协议 。Config 协议为探针数据采集策略控制协议 ,由 Controller 根据用户配置的数据采集策略下发给探针 。Upload 协议为探针原始数据上传协议 ,负责处理探针上传的原始样本数据 ,Controller 在接收到原始数据之后 ,进行基本的有效性判断后立即响应探针 ,同时对该协议数据进行异步处理 ,包括协议分类 、规整和入库等 。

数据处理存储中心

此模块核心组件为 Druid 以及 Zeus ,Druid 主要负责元数据管理 ,离线Job 管理和 API 支持 。系统结构化业务数据由 Druid 负责存储(默认数据保留 3 个月) ,配置数据由 Mysql 集群进行永久存储 。元数据管理主要指业务数据源 、业务规则信息 、业务离线 Job 等信息的管理 ,用户可以通过 zeus 服务进行数据元信息的增删改查 、计算规则设置和离线 JOB 合并规则设置 ,所有元数据均持久化在 Mysql 中 。zeus 服务提供的 API 主要包括元数据操作 API和报表查询 API 两类 。元数据操作 API 提供对元数据的操作相关服务 ,报表查询 API 提供业务结构化数据在线查询服务 。

展示平台

报表平台前端属 Web 工程 ,用户可在报表平台创建修改 APP 数据采集配置 、查看数据报表 、创建修改自动报告 、创建修改智能告警规则等 ,所有相关配置配置数据都会持久化存储到 Mysql 数据库中 。

AIOps智能告警

AlOps整体是通过spark+springboot的基础架构 ,装载数据库配置到redis ,zookeeper ,本地缓存 ,订阅上游传递过来的 kafka 事件消息经多个分布式流处理程序使用规则引擎实现对告警规则(范围规则 ,策略规则 ,告警条件规则 ,告警窗口规则)再通过告警渲染引擎渲染告警信心 ,最后使用告警工具调用实现告警 ,同时将整个流程的数据进行持久化处理到 zeus 数据库 ,实现对事件的告警过滤 ,规则匹配 ,压缩 ,发送告警的整体告警流程 。

商业变化

故障应急排查 ,快速响应各方面要求

在某年度党费缴纳活动期间 ,昆仑银行系统突发故障 ,面对大量的告警数据 ,系统陷入无法有效聚合 、关联分析 、根因分析和故障诊断的困境 。通过腾博会官网应用性能监控系统快速定位故障节点 ,逐层问题剥离分析 ,有效提升排障效率 ,最终将问题发现和解决的时间从小时级压缩到分钟级 ,运维效率提升至80% 。

代码级调用跟踪 ,实现业务全链路可观测

昆仑银行的网贷平台系统有着很高的性能要求 ,在接入腾博会官网的产品前 ,无法准确判断与网贷相关的系统运行是否缓慢 ,部署了腾博会官网的应用性能监控系统后 ,帮助昆仑银行网贷平台实现对应用从程序入口到执行全链路的监控与追踪 ,迅速识别出下游系统存在一定的延迟问题 ,及时采取相应措施 ,确保了昆仑银行网贷平台稳定 、安全地运行 ,给用户提供了优质的服务体验 。

相关企业介绍

·腾博会官网

北京博睿宏远数据科技股份有限公司(简称腾博会官网)(股票号688229)是中国IT运维监控和可观测性领域领导者 ,中国应用性能监控及可观测性领域唯一上市公司 ,同时蝉联市场份额排名第一 。专注于构建以用户为中心的简捷 ,高效 ,智能的新型IT运维 ,有效提升云资源利用效率 ,驱动业务创新增长 ,助力企业提升核心竞争力 ,抢占数字经济先机 。

15年以来 ,腾博会官网以深厚的技术积累不断打磨产品和服务能力 ,已在IT运维领域形成了自身的独特优势 ,并将一体化运维监控和AIOps等解决方案落地到各种客户生产环境之中 ,为银行 ,证券 ,保险 ,高端制造等行业的数字化 、智能化转型持续赋能 ,已经获得中国银行 、工商银行 、中国建设银行 、农业银行 、光大银行 、华夏银行 、平安银行 、招商银行 、中信银行等多家银行及1000+头部客户的选择和信赖 。

·昆仑银行

昆仑银行是一家总部位于北京 、分支机构遍布全国性的城商行 ,提供广泛的金融产品和服务 ,主要包括个人银行业务 、企业金融服务 、资产管理 、投资银行等领域 。作为一家创新型金融机构 ,昆仑银行致力于建立特色鲜明 、富有活力的优秀商业银行 ,同时注重科技创新 ,以稳健经营为基础 ,坚持合规经营和风险控制 ,为客户提供安全 、高效 、便捷的金融服务 。

文章标签

一体化智能可观测

相关文章

FreeMarker template error (DEBUG mode; use RETHROW in production!): The string doesn't match the expected date/time/date-time format. The string to parse was: "2024年3月5日". The expected format was: "MMM d, y". The nested reason given follows: Unparseable date: "2024年3月5日" ---- FTL stack trace ("~" means nesting-related): - Failed at: #if "2024年3月5日"?date lt item.createTi... [in template "themes/halo_quickstarter/post_newsDetail.ftl" at line 106, column 25] ---- Java stack trace (for programmers): ---- freemarker.core._TemplateModelException: [... Exception message was already printed; see it above ...] at freemarker.core.BuiltInsForMultipleTypes$dateBI$DateParser.parse(BuiltInsForMultipleTypes.java:220) at freemarker.core.BuiltInsForMultipleTypes$dateBI$DateParser.getAsDateModel(BuiltInsForMultipleTypes.java:190) at freemarker.core.BuiltInsForMultipleTypes$dateBI$DateParser.getAsDate(BuiltInsForMultipleTypes.java:197) at freemarker.core.EvalUtil.modelToDate(EvalUtil.java:86) at freemarker.core.EvalUtil.compare(EvalUtil.java:270) at freemarker.core.EvalUtil.compare(EvalUtil.java:115) at freemarker.core.ComparisonExpression.evalToBoolean(ComparisonExpression.java:78) at freemarker.core.IfBlock.accept(IfBlock.java:49) at freemarker.core.Environment.visit(Environment.java:370) at freemarker.core.IteratorBlock$IterationContext.executedNestedContentForCollOrSeqListing(IteratorBlock.java:321) at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:271) at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:244) at freemarker.core.Environment.visitIteratorBlock(Environment.java:644) at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:108) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94) at freemarker.core.Environment.visit(Environment.java:334) at freemarker.core.Environment.visit(Environment.java:340) at freemarker.core.Environment.visit(Environment.java:340) at freemarker.core.Environment.process(Environment.java:313) at freemarker.template.Template.process(Template.java:383) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:391) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:304) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:255) at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:179) at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316) at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1401) at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1145) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1084) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) at javax.servlet.http.httpervlet.service(httpervlet.java:497) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.httpervlet.service(httpervlet.java:584) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799) at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1631) at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:230) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at run.halo.app.cas.UserInfoFilter.doFilter(UserInfoFilter.java:37) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.jasig.cas.client.util.AssertionThreadLocalFilter.doFilter(AssertionThreadLocalFilter.java:54) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.jasig.cas.client.util.httpervletRequestWrapperFilter.doFilter(httpervletRequestWrapperFilter.java:75) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at run.halo.app.cas.MyAbstractTicketValidationFilter.doFilter(MyAbstractTicketValidationFilter.java:215) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at run.halo.app.cas.MyAuthenticationNoLoginFilter.doFilter(MyAuthenticationNoLoginFilter.java:57) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at run.halo.app.security.filter.ContentFilter.doAuthenticate(ContentFilter.java:69) at run.halo.app.security.filter.AbstractAuthenticationFilter.doFilterInternal(AbstractAuthenticationFilter.java:229) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at run.halo.app.filter.CorsFilter.doFilter(CorsFilter.java:53) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at run.halo.app.filter.LogFilter.doFilterInternal(LogFilter.java:40) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:548) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) at org.eclipse.jetty.server.Server.handle(Server.java:516) at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487) at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883) at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034) at java.base/java.lang.Thread.run(Thread.java:834) Caused by: freemarker.core.UnparsableValueException: Unparseable date: "2024年3月5日" at freemarker.core.JavaTemplateDateFormat.parse(JavaTemplateDateFormat.java:51) at freemarker.core.JavaTemplateDateFormat.parse(JavaTemplateDateFormat.java:33) at freemarker.core.BuiltInsForMultipleTypes$dateBI$DateParser.parse(BuiltInsForMultipleTypes.java:213) ... 118 more Caused by: java.text.ParseException: Unparseable date: "2024年3月5日" at java.base/java.text.DateFormat.parse(DateFormat.java:395) at freemarker.core.JavaTemplateDateFormat.parse(JavaTemplateDateFormat.java:49) ... 120 more