通过transmittable-thread-local源码理解线程池线程本地变量传递的原理
最近几周,我投入了大量的码分时间和精力,完成了UCloud服务和中间件迁移至阿里云的码分工作,因此没有空闲时间撰写文章。码分不过,码分回忆起很早之前对ThreadLocal源码的码分微信举报源码分析,其中提到了ThreadLocal存在向预先创建的码分线程中传递变量的局限性。恰好,码分我的码分一位前同事,HSBC的码分技术大牛,提到了团队引入了transmittable-thread-local(TTL)来解决此问题。码分借此机会,码分我深入分析了TTL源码,码分本文将全面分析ThreadLocal和InheritableThreadLocal的码分局限性,并深入探讨TTL整套框架的码分实现。如有对线程池和ThreadLocal不熟悉的读者,建议先阅读相关前置文章,本篇文章行文较为干硬,字数接近5万字,希望读者耐心阅读。
在Java中,没有直接的API允许子线程获取父线程的实例。获取父线程实例通常需要通过静态本地方法Thread#currentThread()。同样,为了在子线程中传递共享变量,也常采用类似的方法。然而,这种方式会导致硬编码问题,限制了方法的复用性和灵活性。为了解决这一问题,线程本地变量Thread Local应运而生,其基本原理是通过线程实例访问ThreadLocal.ThreadLocalMap来实现变量的存储与传递。
ThreadLocal与InheritableThreadLocal之间的区别主要在于控制ThreadLocal.ThreadLocalMap的创建时机和线程实例中对应的属性获取方式。通过分析源码,可以清楚地看到它们之间的联系与区别。对于不熟悉概念的读者,可以尝试通过自定义实现来理解其中的原理与关系。
ThreadLocal和InheritableThreadLocal的dapp源码后端最大局限性在于无法为预先创建的线程实例传递变量。泛线程池Executor体系、TimerTask和ForkJoinPool等通常会预先创建线程,因此无法在这些场景中使用ThreadLocal和InheritableThreadLocal来传递变量。
TTL提供了更灵活的解决方案,它通过委托机制(代理模式)实现了变量的传递。委托可以基于Micrometer统计任务执行时间并上报至Prometheus,然后通过Grafana进行监控展示。此外,TTL通过字节码增强技术(使用ASM或Javassist等工具)实现了类加载时期替换Runnable、Callable等接口的实现,从而实现了无感知的增强功能。TTL还使用了模板方法模式来实现核心逻辑。
TTL框架的核心类TransmittableThreadLocal继承自InheritableThreadLocal,通过全局静态变量holder来管理所有TransmittableThreadLocal实例。holder实际上是一个InheritableThreadLocal,用于存储所有线程本地变量的映射,实现变量的全局共享。disableIgnoreNullValueSemantics属性的设置可以影响NULL值的处理方式,影响TTL实例的行为。
发射器Transmitter是TransmittableThreadLocal的一个公有静态类,提供传输TransmittableThreadLocal实例和注册当前线程变量至其他线程的功能。通过Transmitter的静态方法,可以实现捕获、重放和复原线程本地变量的功能。
TTL通过TtlRunnable类实现了任务的封装,确保在执行任务时能够捕获和传递线程本地变量。在任务执行前后,通过capture和restore方法捕获和重放变量,实现异步执行时上下文的传递。
启用TTL的Agent模块需要通过Java启动参数添加javaagent来激活字节码增强功能。TTL通过Instrumentation回调激发ClassFileTransformer,实现目标类的字节码增强,从而在执行任务时自动完成上下文的捕捉和传递。
TTL框架提供了一种高效、灵活的方式来解决线程池中线程复用时上下文传递的问题。通过委托机制和字节码增强技术,TTL实现了无入侵地提供线程本地变量传递功能。恋爱点滴源码如果您在业务代码中遇到异步执行时上下文传递的问题,TTL库是一个值得考虑的解决方案。
部署Kafka监控
在Kafka部署过程中,监控系统的设置至关重要。本文将简述搭建Kafka监控的实践经验,包括所选工具和环境配置步骤。
首先,确保Kafka实例在本地部署了三个实例,未使用Docker。监控方案选择了kafka_exporter、Prometheus和Grafana组合,详细选择理由可自行查阅网络资源。kafka_exporter在本地编译部署,因遇到go环境不匹配问题,最终选择源码编译,通过git克隆v1.7.0版本,设置goproxy以获取依赖库。编译过程中,对`go mod vendor`指令进行了修改,成功编译出kafka_exporter可执行文件,并针对多个Kafka实例制定了启动命令。
同时,为了监控系统负载,部署了node-exporter在Docker中,确保其固定IP以方便Prometheus的配置。node-exporter的IP设为..0.2,端口为。
接下来是Prometheus的部署。首先通过Docker拉取prom/prometheus镜像,配置文件中包含了Prometheus自身、node-exporter(.网段)和kafka_exporter(..0.1)的采集项。使用命令`docker run`启动Prometheus,监听端口,与node-exporter和kafka_exporter通信。
Grafana的安装则在另一个目录B中进行,设置了读写权限后通过Docker拉取grafana/grafana镜像。部署时,开天眼源码Grafana容器的IP设为..0.4,监听端口。登录Grafana后,首先添加DataSource,指向Prometheus实例,然后导入官网提供的Linux系统模板(如、),Kafka监控模板(如),以及Prometheus模板()以设置Dashboard。
总结,通过这些步骤,成功搭建了Kafka的监控系统,包括本地部署的kafka_exporter、Docker中的node-exporter和Prometheus,以及Grafana用于可视化监控数据。
consulmanager部署和使用
书接上回 渐行渐远:prometheus的安装以及监控指标的配置
这次主要介绍如何使用consulmanager 去监控各个监控项
一 consulmanager安装
github.com/starsliao/Te... #consulmanager项目地址
consulmanager 是一个开源的项目,现在已经更名为tensuns,有兴趣的可以自行研究
要想安装consulmanager,必须先安装下面三个 docker ,docker-compase, consul
1.1 安装consul
1.1.1 安装consul-基于centos7
1.1.2 生成uuid
1.1.3 配置文件设置
1.1.4 启动consul
访问方式 ip:
1.2 安装docker和docker-compase
1.2.1 安装docker
1.2.2 安装docker-compase
二 安装 ConsulManager
2.1 下载源码
下载地址 github.com/starsliao/Co...
目录结构如下:
2.2 docker-compose.yml 内容
2.3 启动并访问
三 配置consulmanager
3.1 云主机管理
3.1.1 同步云主机
云主机管理就是可以自动同步云服务器到consulmanager这个上面
前提是需要你在云账号里面创建access key 和secret key,这个账号还需要有访问主机的权限
新增云资源
创建完成之后,你可以手动同步,也可以自动同步,然后去云主机列表查看,是否同步过来了
3.1.2 批量云主机监控
前提是每天主机需要安装好node-exporter
选定好指定的组,选择好系统,点击生成配置,然后把这个配置,粘贴到prometheus的配置文件中
进行重启prometheus
然后进去到prometheus-target里进行查看
当然如果你的node-exporter的端口不是,怎么办,打开cousul的web页面,可以自定义设置
3.1.3 导入对应的模版
导入ID:
详细URL: grafana.com/grafana/das...
3.1.4 设置告警规则
3.2 blackbox站点监控设置
3.2.1. 配置Blackbox_Exporter
在Web页面点击
Blackbox 站点监控/Blackbox 配置,点击
复制配置,如下所示:
复制配置到 blackbox.yml,清空已有的配置,把复制的内容粘贴进去,重启blackbox_exporter
3.2.2 配置Prometheus
在Web页面点击 Blackbox 站点监控/Prometheus 配置,点击复制配置。真玩源码编辑Prometheus的
prometheus.yml,把复制的内容追加到最后,reload或重启Prometheus
3.2.3. 配置Prometheus告警规则
在Web页面点击
Blackbox 站点监控/告警规则,点击复制配置。
编辑Prometheus的配置文件,添加 rules.yml,然后把复制的内容粘贴到rules.yml里面,reload或重启Prometheus。
然后去prometheus查看告警规则是否生成
3.2.4. 查看Prometheus
在Prometheus的Web页面中,点击Status-Targets,能看到新增的Job即表示数据同步到Prometheus。
3.2.5 新增tcp或者/grafana/das...
最终在grafana访问的效果如下:
四 总结
到这里基本的监控项和报警规则都已经设定好了,接下来会介绍告警的方式和具体实现
基于Prometheus + Grafana搭建IT监控报警最佳实践(2)
见字如面,大家好,我是小斐。延续前文,本文将深入探讨Prometheus和Grafana的监控体系。
首先,我们需要打开Prometheus和Grafana进行操作,访问地址分别为:...:/ 和 ...:/。
以node_exporter数据采集器为例,先确保其已安装于需要监控的主机。若要获取...主机的状态数据,需在该主机安装node_exporter采集器。
在prometheus.yml中添加需要抓取的目标源信息,具体操作为:在scrape_configs下添加job_name,指定静态目标,添加...:目标。
配置文件配置完成后,由于是静态的,需要重新加载配置文件,重启Prometheus以生效。
在targets中查看是否已抓取到目标,根据上图可见,...的主机节点数据已抓取到。在Prometheus中验证数据正确性,点击http://...:/metrics 可查看抓取的所有数据。
查看数据信息,输入node_memory_MemTotal_bytes查询该主机内存数据是否正确,可以看到G总内存,与我本机内存相符,说明数据正确。
至此,我们可以确定数据抓取是成功的。
数据生成大屏数据UI,展示放在Grafana中,打开Grafana:http://...:/,点击数据源:关联Prometheus数据源。
输入Prometheus的地址:http://...:,下载Grafana的面板,json模版可在Grafana官网模版库中找到。在此,我选择了一个模版,具体链接为:Linux主机详情 | Grafana Labs。
添加模版:点击import,导入下载下来的json文件。
或者根据ID来加载。如果对面板数据和展示的风格不适用,可单独编辑变量和数据查询语句,关于Grafana的变量和数据查询语句后续单独开篇说明,在此只采用通用的模版展示数据。
关于SNMP数据采集,我们可以通过SNMP协议来监控交换机、路由器等网络硬件设备。在一台Linux主机上,我们可以使用snmpwalk命令来访问设备通过SNMP协议暴露的数据。
简单查看后,我们需要长期监控,这个时候就要借助SNMP Exporter这个工具了。SNMP Exporter是Prometheus开源的一个支持SNMP协议的采集器。
下载docker image使用如下命令,使用中请切换对应的版本。如果使用二进制文件部署,下载地址如下。
对于SNMP Exporter的使用来说,配置文件比较重要,配置文件中根据硬件的MIB文件生成了OID的映射关系。以Cisco交换机为例,在官方GitHub上下载最新的snmp.yml文件。
关于采集的监控项是在walk字段下,如果要新增监控项,写在walk项下。我新增了交换机的CPU和内存信息。
在Linux系统中使用Docker来运行SNMP Exporter可以使用如下脚本。
在Linux系统部署二进制文件,使用系统的Systemd来控制服务启停,系统服务文件可以这么写。该脚本源自官方提供的脚本,相比于官方脚本增加了SNMP Exporter运行端口的指定。
运行好以后,我们可以访问http://localhost:来查看启动的SNMP Exporter,页面上会显示Target、Module、Submit、Config这几个选项和按钮。
在Target中填写交换机的地址,Module里选择对应的模块,然后点击Submit,这样可以查到对应的监控指标,来验证采集是否成功。
target可以填写需要采集的交换机IP,模块就是snmp.yml文件中命名的模块。
点击Config会显示当前snmp.yml的配置内容。
如果上面验证没有问题,那么我们就可以配置Prometheus进行采集了。
配置好Prometheus以后启动Prometheus服务,就可以查到Cisco交换机的监控信息了。
接下来就Prometheus配置告警规则,Grafana进行画图了。这些操作和其他组件并无区别,就不再赘述。
关于手动生成snmp.yml配置文件,当官方配置里没有支持某些设备时,我们需要通过MIB文件来自己生成配置文件。
以华为交换机为例,在单独的CentOS7.9的一台虚拟机中部署snmp_exporter,在这里我以源码编译部署。
在此我贴出generator.yml文件的模版:模块中,if_mib是指思科模块提供公共模块,HZHUAWEI是我自定义的模块名,根据walk下的OID和变量下的mib库文件路径生成snmp.yml配置文件,然后根据snmp.yml配置文件采集交换机信息。
generator.yml文件格式说明:参考官网。
这次我贴一份比较完整的snmpv3版本的模版:参考网络上,后续我内部的完整模版贴出来,形成最佳实践。
主要的消耗时间就是想清楚需要采集的交换机监控指标信息,并到官网找到OID,贴到generator.yml文件中,最后执行./generator generate命令遍历OID形成snmp.yml配置文件,启动snmp_exporter时指定新形成的snmp.yml文件路径。
启动后在浏览器中,打开http://...5:/。
在此需要说明下,交换机需要开启snmp使能。如内部交换机比较多,可采用python或者ansible批量部署snmp使能,python这块可学习下@弈心 @朱嘉盛老哥的教程,上手快并通俗易懂,ansible后续我会单独出一套针对华为设备的教程,可关注下。
一般情况下,交换机都是有多台,甚至几百上千台,在如此多的设备需要监控采集数据,需要指定不同模块和不同配置文件进行加载采集的,下面简单介绍下多机器部署采集。
编辑prometheus.yml文件,snmp_device.yml的内容参照如下格式即可。我在下面的示例中添加了architecture与model等变量,这些变量Prometheus获取目标信息时,会作为目标的标签与目标绑定。
重启服务器或重加载配置文件即可,后续贴出我的实际配置文件。
此篇到此结束,下篇重点说明配置文件细节和我目前实践的配置文件讲解。
收藏 Kafka监控组件大全
本文概述了用于监控Kafka系统的多种组件,包括Burrow、Telegraf、Grafana以及一些其他工具,如Kafka Manager、Kafka Eagle、Confluent Control Center和Kafka Offset Monitor。以下对这些工具进行了简要介绍。
Burrow是一个用于监控Kafka的组件,由Kafka社区的贡献者编写,主要关注于监控消费者端的情况。它使用Go语言编写,功能强大,但用户界面不提供,可通过GitHub获取二进制文件进行安装。
Telegraf是一个数据收集工具,与Burrow结合使用,用于收集Kafka监控数据,并将其存储到InfluxDB中,以便在Grafana中进行可视化展示。
Grafana是一个强大的数据可视化工具,允许用户创建仪表板,以直观地显示从Burrow收集的监控数据。通过配置Grafana,可以设置变量和图表,过滤集群并显示关键指标,如消费者滞后度、分区状态等。
Kafka Manager是一个受欢迎的监控组件,使用Scala编写,提供源码下载。它支持管理多个Kafka集群、副本分配、创建和管理Topic等功能,但编译过程较为复杂,且在处理大型集群时资源消耗大。
Kafka Eagle是一个由国人开发的监控工具,以其美观的界面和强大的数据展现能力受到推崇。它支持权限报警和多种报警方式,如钉钉、微信和邮件,还具备使用ksql查询数据的功能。
Confluent Control Center是一个功能齐全的Kafka监控框架,集成了多种监控和管理功能,但需购买Confluent企业版才能使用。官方文档提供了快速启动指南,但安装过程较为繁琐,需要引入特定的Kafka版本及其相关服务。
Kafka Monitor和Kafka Offset Monitor被认为是监控组件中的“炮灰”,具体信息不详。
综上所述,这些组件提供了从不同角度监控Kafka系统的能力,包括消费者监控、资源管理、性能分析和数据可视化等。选择合适的监控工具时,需要考虑功能需求、资源消耗和集成难度等因素。
2024-12-23 06:50
2024-12-23 06:08
2024-12-23 05:45
2024-12-23 05:18
2024-12-23 04:33