代码之旅

I love Coding !

这一个常在元旦附近出没的Bug,主要原因是Java 日期格式FormatString 中的yyyy 被写成了YYYY。
要注意的是,对于年份来说,大写的Y和小写的y其意义是不同的。y 是Year, Y 表示的是Week year

经过试验,得出的结果如下:Week year 意思是当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,那么这周就算入下一年。

注意上面的Week year 指format时的结果,对于YYYY格式使用parse, 会得到意想不到的结果。

1
2
3
4
5
6
7
8
SimpleDateFormat upperFormater = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
SimpleDateFormat lowerFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(lowerFormater.parse("2021-12-30 09:00:00"));
String lower = lowerFormater.format(lowerFormater.parse("2021-12-30 09:00:00"));
System.out.println(lower);
String upper = upperFormater.format(lowerFormater.parse("2021-12-30 09:00:00"));
System.out.println(upper);
System.out.println(upperFormater.parse("2021-12-30 09:00:00"));

循环冗余校验(英语:Cyclic redundancy check,通称“CRC”)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。生成的数字在传输或者存储之前计算出来并且附加到数据后面,然后接收方进行检验确定数据是否发生变化1

阅读全文 »

最近遇到一个问题,在执行长事务任务的过程中,频繁出现异常 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Communications link failure during commit(). Transaction resolution unknown.即,事务提交时发现连接已经失效。一开始以为是连接超时设置的有问题,但是这个异常重复出现,并且,数据库连接池设置了testOnBorrow。所以应该不是连接超时导致。后来发现,出现报错时,事务开启都刚好超过了5S。

经过和RDS同学的沟通。他们设置了kill_idle_transaction 这个参数,并且默认为5S

在线上遇到5.7.26的锁问题,需要解决idle事务长时间挂起的问题。同时也调研了现有的mysql timeout机制,以确保其和现有的timeout机制可以吻合。Percona从5.1.59-13.0引入了innodb_kill_idle_transaction,用于解决长事务场景,即对idle事务设定一个超时时间,对超过该时间的事务所在的用户连接进行断开。引入该参数也可以防止purge线程的长时间阻塞(长事务会一直保持在活跃状态,则会导致purge长时间的等待,从而导致undo无法清理从而造成磁盘空间的不断增加)。在实现上,开始是通过扫描InnoDB事务列表来进行判断的,在Percona Server 5.6.35-80.0则改为判断connection socket read timeout。这样优化的好处是,巡检可能会造成CPU空跑,而基于socket select超时则发生超时才会触发,使代码的运行更有效率。另外,percona现在提供了两个参数:innodb_kill_idle_transaction(后者的alias,5.7中已标记为deprecated)和kill_idle_transaction。我们在port时只保留kill_idle_transaction。

阅读全文 »

最近在线上环境遇到一个问题,nacos客户端线程池中有96个线程在等待.一开始以为是哪里配置有误,于是检查了nacos的配置。没有发现问题。于是只能看nacos源码了.

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
30
31
32
33
34
35
36
37
38
39
public ClientWorker(final HttpAgent agent, final ConfigFilterChainManager configFilterChainManager, final Properties properties) {
this.agent = agent;
this.configFilterChainManager = configFilterChainManager;

// Initialize the timeout parameter

init(properties);

executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker." + agent.getName());
t.setDaemon(true);
return t;
}
});

executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName());
t.setDaemon(true);
return t;
}
});

executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
checkConfigInfo();
} catch (Throwable e) {
LOGGER.error("[" + agent.getName() + "] [sub-check] rotate check error", e);
}
}
}, 1L, 10L, TimeUnit.MILLISECONDS);
}

如上面的代码,nacos长轮询线程池在初始化时使用了Runtime.getRuntime().availableProcessors().而宿主机恰好是48核*2。因此判断JVM获取可用核数错误,拿到的是宿主机核数而非容器可用核数1

阅读全文 »

在前面的编译原理-词法分析一文中,我们介绍了基于正则表达式方式构建NFA和DFA进行词法分析的方案。本文将基于该方案,扩展一些功能,实现正则表达式执行引擎(见参考[1])。

阅读全文 »

本篇是论文的中文简单翻译

摘要

Apache Calcite 是一个基础软件框架,可提供查询处理,优化和查询语言支持,目前已支持多种流行的开源数据处理系统,例如Apache Hive,Apache Storm,Apache Flink,Druid和MapD。Calcite 的体系结构包括具有数百种内置优化规则的模块化可扩展查询优化器,能够处理多种查询语言的查询处理器,为可扩展性设计的适配器体系结构以及对异构数据模型和存储(关系,半 结构化,流式传输和地理空间)。这种灵活,可嵌入和可扩展的架构使 Calcite 在大数据框架中采用更具有吸引力。这是一个活跃的项目,正持续引入对新型数据源,查询语言以及查询处理和优化方法的支持。

阅读全文 »

解析是编译器将一系列标记转换为树表示的过程:

1
2
3
4
5
                            Add
Parser / \
"1 + 2 * 3" -------> 1 Mul
/ \
2 3

Pratt Parser解析是手写解析最常用的技术之一。

阅读全文 »

maven 打包时HeapSpace OOM

maven打包时出现HeapSpace OOM问题。由于Maven是Java启动的,显然我们只要修改maven进程的JVM配置就可以了。

在系统的环境变量中,设置MAVEN_OPTS,用以存放JVM的参数:

1
export MAVEN_OPTS=-Xms256m -Xmx768m -XX:PermSize=128m -XX:MaxPermSize=256M

除了Maven主进程之外,单测插件surefire起的进程也可能出现OOM异常。surefire插件可以拉出几个JVM进程,以及每个进程的JVM配置是如何的,都是可以配置的(见官方文档)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--注意argLine配置可以用于传递JVM参数-->
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<forkCount>3</forkCount>
<reuseForks>true</reuseForks>
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
<systemPropertyVariables>
<databaseSchema>MY_TEST_SCHEMA_${surefire.forkNumber}</databaseSchema>
</systemPropertyVariables>
<workingDirectory>FORK_DIRECTORY_${surefire.forkNumber}</workingDirectory>
</configuration>
</plugin>
[...]
</plugins>

gradle 打包时HeapSpace OOM

在gradle工程的gradle.properties里配置org.gradle.jvmargs=-Xmx2000m -Xms500M -XX:+HeapDumpOnOutOfMemoryError

最近在maven打包的时候遇到一个问题:

1
Could not transfer artifact io.airlift:airbase:pom:128 from/to maven-default-http-blocker 

使用的maven版本是 3.8.4. 原因是maven自3.8.1升级后需要https协议的仓库地址。

我们从 Jonathan Leitchuh 收到了一份关于依赖 POM 中自定义存储库漏洞的报告。我们将其分为三个独立的问题:

由于使用 HTTP 的自定义存储库可能导致中间人攻击现在越来越多的存储库使用 HTTPS,但情况并非总是如此。这意味着 Maven Central 包含带有自定义存储库的 POM,这些存储库通过 HTTP 引用 URL。这使得通过此类存储库下载的内容成为 MITM 攻击的目标。同时,开发人员可能没有意识到某些下载使用了不安全的 URL。由于上传到 Maven Central 的 POM 是不可变的,因此需要对 Maven 进行更改。为了解决这个问题,我们使用参数扩展了镜像配置,并添加了一个新的external:http:镜像选择器(如 existing external:),意思是“使用 HTTP 的任何外部 URL”。决定默认阻止此类外部 HTTP 存储库:这是通过在conf/settings.xml阻止不安全 HTTP 外部 URL 中提供镜像来完成的。

由于使用废弃域的自定义存储库可能导致域劫持,Sonatype 分析了哪些域已被废弃并已声明这些域。

通过重定向到自定义存储库可能劫持下载。这是最难分析和解释的。简短的故事是:您很安全,依赖项仅从其上下文中的存储库下载。所以有两个主要问题:上下文是什么,顺序是什么?该订单在Repository Order 中描述页。第一组存储库在 settings.xml 中定义(用户和全局)。第二组存储库基于继承,最终超级 POM 包含指向 Maven Central 的 URL。第三组是最复杂的一组,但对于理解术语上下文很重要:从依赖路径到工件的有效 POM 的存储库。因此,如果一个依赖项是由另一个依赖项或 Maven 项目定义的,它也将包含它们的存储库。归根结底,这不是错误,而是设计功能。

原文见 Release Notes – Maven 3.8.1

有两种解决方案:

  1. 修改maven远程仓库地址为支持https的地址。比如:添加ali的maven仓库地址。
  2. 替换为3.8.1之前的maven版本。

编译器模型:

graph LR
源代码-->|词法分析器|词法单元
词法单元-->|语法分析器|语法分析树
语法分析树-->|中间代码生成器|中间代码
中间代码-->|代码优化,机器无关|中间代码
中间代码-->|代码生成器|目标代码
目标代码-->|机器相关代码优化|机器码
机器码-->output((机器码执行))
阅读全文 »