抿茶言码

搬砖二三事


  • Home

  • Tags

  • Categories

  • Archives

一次java-agent中字节码增强失败问题定位

Posted on 2020-09-12 | In 问题定位

1 背景

我们的项目目前使用zander(公司内部的链路追踪组件, 基于skywalking)作为日志增强组件, 在日志中打印traceId, 用于多服务请求追踪标识.
目前我们服务中遇到了traceId消失的问题, 即zander中对log4j2的字节码增强失败. 需要分析原因

2 bytebuddy实现的javaagent

zander中为了实现日志增强, 采用了javaagent的方式, 对log4j的相应方法做拦截增强, 将traceid写入到对应的log文件中.

我们的工程中使用的是log4j2, 对应的增强方法为org.apache.logging.log4j.core.config.LoggerConfig#callAppenders, 该方法位于lo4j-core-2.x.x.jar

我们知道, javaagent在执行时, 会执行Premain-Class下的premain方法, 我们找到zander的Premain-Class ZanderAgent以及对应premain方法如下(做了些删减)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static void premain(String agentArgs, Instrumentation instrumentation) {
LOGGER.info("premain begin, and load config start with agentArgs: {}", new Object[]{agentArgs});
AgentConfigInitializer.initialize();
// 心跳检测
HeartBeatBootService.doHeartBeat();
CustomMethodUtils.init();
LogInterceptorUtils.init();

final PluginFinder pluginFinder;
try {
// 载入插件. log4j2的插件也会在此处被载入
pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
} catch (Exception e) {
return;
}

new AgentBuilder.Default().type(enhanceClassMatcher(pluginFinder).and(not(isInterface()))).transform((builder, typeDescription, classLoader) -> {
// 此处会找到zander log4j2插件的Log4j2Instrumentation, Log4j2Instrumentation类中会定义所要拦截的log4j2对应的方法
List<AbstractClassEnhancePluginDefine> pluginDefines = pluginFinder.find(typeDescription.getTypeName());

for (AbstractClassEnhancePluginDefine pluginDefine : pluginDefines) {
DynamicType.Builder<?> newBuilder = pluginDefine.define(typeDescription.getTypeName(), builder, classLoader);
if (newBuilder != null) {
return newBuilder;
}
}
return builder;
}).installOn(instrumentation);
}
Read more »

一次cpu 100%问题定位实战

Posted on 2020-08-28 | In 问题定位

命令如下:

  1. top

  2. top -H -p 151

    Read more »

Jenkins集成findbugs完成静态代码检查

Posted on 2020-07-02 | In 持续集成

背景

项目组出过几次NPE事故,为保障代码健壮性, 提高项目稳定性, 在项目中引入findbugs插件, 进行静态代码检查.

任务目标

  • Jenkins CI过程中, 引入静态代码检查, 生成检查报告
  • 引入bug模板, 实现检查内容可配置
  • 代码检查发现bug时, 阻断maven构建流程, 发送邮件告警

实施过程

引入maven插件findbugs-maven-plugin

注意点:

  • 与pipeline配合, 在install阶段再报错, 让pipeline在compile阶段生成报告
  • 配置includeFilterFile, 自定义bug检查类型
  • 一些反向工程的代码可以配置节点, 不做bug检查
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>findbugs-maven-plugin</artifactId>
    <version>3.0.5</version>
    <configuration>
    <failOnError>true</failOnError>
    <findbugsXmlOutput>true</findbugsXmlOutput>
    <xmlOutput>true</xmlOutput>
    <includeFilterFile>${basedir}/src/main/resources/findbugs-include.xml</includeFilterFile>
    </configuration>
    <executions>
    <execution>
    <id>failOnError</id>
    <phase>install</phase>
    <goals>
    <goal>check</goal>
    </goals>
    <configuration>
    <effort>Max</effort>
    <threshold>High</threshold>
    <failOnError>true</failOnError>
    </configuration>
    </execution>
    </executions>
    </plugin>
Read more »

分布式id自增算法-雪花算法(snowflake)

Posted on 2020-06-03 | Edited on 2020-06-09 | In 算法

雪花算法

1. 介绍

snowflake算法, 最早是twitter内部使用的分布式环境下的唯一ID生成算法。在2014年开源。开源的版本由scala编写
附: twitter源码github地址

2. 原理

雪花算法的原理非常简单. 取long类型的64位的bit, 然后分布如下:

  1. 0位. 固定0, 正数标识

  2. 1-41位. 41位的毫秒时间差统计值. 这里的42存储的并不是时间戳. 实际上算法需要预制一个”初始时间戳”, 这个42位标识与初始时间戳的时间跨度. 可以算一把42位所能表述的时间跨度(以毫秒计).

    1
    2^41/(1000*60*60*24*365) = 69
  3. 42-51位. 10位的机器标识位. 可以标识1024个机器节点

  4. 52-63位. 12位序列号位. 标识在单机器节点下, 同一毫秒时间能够产生的最大id个数为4096个

Read more »

敏捷开发修炼之道

Posted on 2020-04-12 | In 读后感

敏捷开发就是在一个高度协作的环境中,不断地使用反馈进行自我调整和完善.

态度决定一切

做事, 追求结果:

  • 以结果为导向, 一切的工作都围绕”把事情做成”. 有问题解决问题, 不允许相互指责, 批判错误而不批判人
  • 如果一个成员一再做伤害团队的事情, 无疑显示了他的不专业, 不专业的人无法帮助团队前进
  • 当团队中大部分都不专业, 并且没有工作目标, 及早离开

戒骄戒躁,步步为营

  • 改代码之前, 要先理解代码. 同样, 要理解团队的开发方法和开发过程, 遵从统一的开发方式
  • 警惕”破窗效应”, 一次的妥协, 在不理解的基础上对代码进行类似+1-1的快速修复, 就一定会有下一次
  • 重视单元测试, 好的单元测试, 会是代码极佳的说明文档
    Read more »

hbase常用配置设置和常见问题汇总

Posted on 2020-02-16 | In hbase

一、常用配置

1.1 配置说明

配置项 值 说明
hbase.cluster.name xx-xxxxx-xx-xxxx.xx 集群名称, 区分环境
hbase.client.ipc.pool.type RoundRobin socket连接池的类型: Reusable/RoundRobin/ThreadLocal 默认RoundRobin
hbase.client.keyvalue.maxsize 2097152 存储文件中的单个entry的大小上限. 默认10485760(10M)
hbase.client.pause 40 客户端暂停时间, 常用于客户端在重试前的等待时间. 默认100ms
hbase.ipc.client.tcpnodelay true 设置tcp socket连接no delay. 默认true
hbase.client.ipc.pool.size 2 socket连接池大小
hbase.rpc.timeout 300 一次RPC的超时时间. 默认60000ms
hbase.client.operation.timeout 1000 一次操作的超时时间. 默认1200000ms
hbase.client.retries.number 10 最大重试次数. 默认35
hbase.client.prefetch.limit 100 预取region地址个数. 实际对于随机存取意义不大
hbase.client.scanner.caching 30 Scan时一次next请求获取的行数. 默认100
hbase.ipc.client.connection.maxidletime 2147483647 客户端连接最大空闲时间
zookeeper.session.timeout 10000 zk会话超时时间. 默认180000ms
zookeeper.recovery.retry 2 zk重试次数

附:官方默认配置

Read more »

RPC线程池与CPU和内存的相互关系

Posted on 2019-12-24 | In 微服务

一、RPC服务端线程池的必要性

出于性能考虑, RPC框架服务端是一定要设计线程池的. 否则, 来一个请求, 再去创建/启动线程, 就相当低效了.

二、线程池队列中有等待任务的影响

我们的RPC框架中使用的是java线程池, 初始化时, 其核心线程数和最大线程数设置为相同, 都是取threadPoolsize的值.一旦同一时间的请求数高于设置的线程数(即threadPoolsize), 则请求会进等待队列. 此时服务端开始满负荷运行(线程池中所有线程均处理执行状态, 在执行完已有任务前, 不会再产生新的线程来执行请求).

那线程池等待队列有任务对服务有什么影响呢?

最直接的影响, 是导致请求延迟. 假设服务平均响应时间100ms, 服务线程池大小100. 假设当前并发为200, 则会有100个并发请求会进队列, 需要等待线程池中先处理完100个请求, 才能轮到队列中的请求执行. 此时响应时间直接变为200ms, 服务响应时间变长.

Read more »

https 原理浅析

Posted on 2019-06-24 | In 网络协议

Https原理浅析

使用RSA算法的SSL握手图如下:

Read more »

Jackie Chen

8 posts
7 categories
25 tags
GitHub E-Mail
友情链接
  • 阮一峰
  • 江南白衣
  • 养猪大佬-vamei
© 2020 Jackie Chen