jstorm源码解析之bolt异常处理
问题用过storm或者jstorm的都知道,如果在bolt代码中发生了没被catch住的异常,所在worker进程会退出。本文就从源码角度分析一下具体设计,其实并不是“有异常然后进程崩了”这么简单。 实质我们先看BasicBoltExecutor的源码: 123456789101112public void execute(Tuple input) { _collector.setContext(input); try { _bolt.execute(input, _collector); _collector.getOutputter().ack(input); } catch (FailedException e) { if (e instanceof ReportedFailedException) { _collector.reportError(e); } _collector.getOutputt...
log4j动态添加appender
大多数 Java 开发者习惯通过配置文件(log4j.properties 或 log4j.xml)来管理日志输出。但在某些运维场景下,运行时动态修改日志配置会更加灵活——比如线上排查问题时临时开 DEBUG 级别,或者动态将日志推送到 Kafka 做集中分析。 Log4j 1.x 的 API 完全支持运行时代码修改配置。本文以 KafkaAppender 为例,演示如何动态添加 appender。 静态配置 vs 动态配置 方式 适用场景 优缺点 配置文件(静态) 日常开发、常规部署 简单、标准化;但修改需要重启 API 编程(动态) 线上排查、运维自动化 灵活,不需要重启;但需要对 API 熟悉 基本示例:动态添加 KafkaAppender123456789101112131415161718192021222324import org.apache.log4j.Logger;import org.apache.log4j.PatternLayout;import org.apache.log4j.Level;import org.apache.log...
【翻译】java里编写基准测试的一些经验
为什么需要基准测试有时候我们需要写一些简单的性能测试代码,恰好在stackoverflow上看到一篇经验之谈,https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java, 怎样写基准测试来尽量屏蔽掉环境的影响。 翻译出来贴在这儿: 编写可靠的基准测试来自Java HotSpot作者的撰写微基准的提示: 规则0:阅读有关JVM和微型基准测试的好论文。比如https://www.ibm.com/developerworks/java/library/j-jtp02225/。不要对这种测试有太高的期望;它们对JVM性能的测试仅能起到有限效果。 规则1:始终包含一个预热阶段,它一直运行,直到触发所有的初始化和编译。 (预热阶段的迭代次数可以减少,经验法则是几万次循环。) 规则2:始终使用-XX:+PrintCompilation -verbose:gc 等参数来运行,这样可以确定编译阶段和JVM的其他部分在计时时是否进行了一些意外的工作。 规则2.1:在计时和预热阶...
java线程池:获取运行线程数并控制线程启动速度
Java 的线程池用起来很方便——Executors.newFixedThreadPool(n) 一行代码搞定。但如果任务提交速度远快于执行速度,任务会在无界队列中无限堆积,最终导致 OOM。今天分享一个真实案例和几种解决方案。 问题场景假设你有一个批量处理任务:遍历一个目录下的 100 万个文件,每个文件提交一个任务去处理。每个任务需要加载一些数据到内存。 123456789ExecutorService executor = Executors.newFixedThreadPool(10);for (File file : files) { executor.submit(() -> { // 这个任务占用大量内存 byte[] data = loadFileContent(file); process(data); });} 问题在于:Executors.newFixedThreadPool 使用的是无界队列(LinkedBlockingQueue),任务提交速度远大于...
maven里的mirror和repository: 配置多repository
maven里的mirror和repository是两个比较容易混淆的概念,它们的作用都是配置远程maven仓库的地址。顾名思义,repository就是直接配置站点地址,mirror则是作为站点的镜像,代理某个或某几个站点的请求,实现对repository的完全代替。 repository有两种形式可以配置多个repository, 配置多个profile或者在同一个profile中配置多个repository.配置多profile时,还需要配置activeProfiles使配置生效。 配置示例: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 <profiles></profile> <profile> <id>central</id> <repositories> ...
使用maven shade plugin 打可执行Jar包
Fat Jar 是什么eclipse里有一个功能叫做“打可执行(runnable) jar包”, 用这个功能可以把一个工程自身和所有依赖包打成一个fat jar,并且指定Main方法,这样直接使用java jar xxx.jar就可以运行代码了。 Maven Shade Plugin 配置但是在不使用eclipse的时候呢?其实,借助maven,我们很容易实现同样功能。maven提供了一个shade plugin,可以用来打fat jar, 同时也提供了指定main方法的功能。 12345678910111213141516171819202122232425262728<project> ... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> ...
activemq plugin开发指南及示例
activemq提供了一种插件(plugin)开发的机制(http://activemq.apache.org/developing-plugins.html), 可以方便的添加各种自定义功能。其效果类似于直接去修改activemq的源码,无论从方便性还是风险程度上,使用plugin都要比去修改源码要好很多。通过这种方式,理论上我们可以实现几乎所有能想到的功能。 开发指南首先需要在工程中添加activemq的依赖,为了方便,可以直接用activemq-all包。 12345<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-all</artifactId> <version>5.13.2</version></dependency> Actviemq plugin的开发非常方便,只需要实现两个类。 一个是plugin类, 需要implements BrokerPlugin这个...
通过加入classpath的形式实现命令行运行java程序时引入第三方jar包
在命令行直接运行 Java 程序时,如果需要引入第三方 jar 包,通常的做法是用 Maven/Gradle 打一个 fat jar(把依赖全部打包进去)。但在某些轻量场景下——比如写了一个小脚本、做快速原型验证、或者在 CI 环境中临时跑一段 Java 代码——手动设置 classpath 反而更直接。 Classpath 是什么?Classpath 是 JVM 查找类文件的搜索路径。当你写 java com.example.Main 的时候,JVM 会在 classpath 中逐条路径搜索 com/example/Main.class。 默认情况下,classpath 只包含当前目录(.)。如果程序依赖了其他 jar 包,就需要手动把它们加到 classpath 中。 方法一:Shell 脚本拼接写一个简单的启动脚本,手动拼接所有依赖 jar 的路径: 1234567#!/bin/bash# 定义 CLASSPATHCLASSPATH=your-main.jar:lib/dep1.jar:lib/dep2.jar:"$CLASSPATH"# ...
解决fatjar的 "java.lang.SecurityException: Invalid signature file digest for Manifest main attributes" 问题
问题现象最近试图运行一个fatjar的时候报错: 1234567891011121314151617181920Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:287) at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:240) at java.util.jar.JarVerifier.processEntry(JarVerifier.java:317) at java.util.jar.JarVerifier.update(JarVerifier.java:228) at java.util.jar.JarFile...
通过实际操作理解redis cluster原理
Redis 集群是redis官方提供的一种集群方案,从3.0开始提供稳定版,应用也已经比较广泛,也经受住了时间考验,个人感觉完全可以取代codis,tweemproxy等集群方案。 cluster原理介绍cluster是使用数据分片的形式实现的,一个 Redis cluster集群包含 16384 个哈希槽, 任意一个key都可以通过 CRC16(key) % 16384 这个公式计算出应当属于哪个槽。每个槽应当落在哪个节点上,也是事先定好。这样,进行任一操作时,首先会根据key计算出对应的节点,然后操作相应的节点就可以了。 所以说,其实cluster跟单点相比,只是多了一个给key计算sharding值的过程,并没有增加多少复杂度,完全可以放心使用。 在这样的设计下,一些对节点的操作也很方便,操作过程中对client端也不会有影响。1. 增加节点:将原有节点的某些slot转移到新节点上2. 删除节点: 将节点上的槽转移到其他节点上以后,移除空节点3. 节点故障:落到故障节点上的操作会失败,而集群其他部分可以正常访问,这样就不会出现一致性哈希方案的“雪崩”问题。单点的故障也可以通...













