V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  Aresxue  ›  全部回复第 2 页 / 共 21 页
回复总数  419
1  2  3  4  5  6  7  8  9  10 ... 21  
86 天前
回复了 v2zzzzz 创建的主题 Java 探讨一下 Java 系的系统监控
可观测性比较适用于大型成熟系统,小项目基础设施搞得再好如果只有零星几个开发那也没多少收益。可观测性目前主要分为几大块,log (日志)、trace(链路)、metrics (监控)、alarm (告警),对于小项目来说要有取舍,比如题中提到的 skywalking 我司目前也是用的这个并做了二开但是这是建立在核心系统有超过 60 个应用,上千个 pod 的基础之上的,小项目哪怕使用微服务应用数也很有限,链路本身就不复杂,所以链路的优先级远远低于日志(日志中有 tid 其实可以脑补串联起链路),剩下的监控和告警常常是一起的,Prometheus 几乎是事实意义上的标准了,只有告警成本较高收益不明显,资源告警和业务告警搞起来不要太复杂。所以小项目资源紧张的情况下优先保障日志(日志规范其实也很有讲究有很多技术手段可以做),其次有空余资源就把监控( jvm 内存、进程内存、gc 、cpu 、磁盘 io 、网络 io )搞起来,链路和告警可以在项目有更大的发展之后再逐步引入。
结论是没有。
好处之一有点类似我们自己工程中的多 module 结构一样,看源码的时候可以更清晰,引入依赖可以按需引入而不是全量引入,很多框架以前为了这个事情自己把使用的类从 jdk 里面 copy 出来( copy 一个类往往还没用还要 copy 依赖的类想想心累不),有了模块化以后就不用再干这种脏活了,当然上面的事情和 web 业务开发基本没啥关系,主要是框架和中间件影响比较大,但其实这一举措主要是 java 还不想放弃桌面端,java 做桌面端以前最被人诟病的就是要带着 jre 一起发布整个包大到离谱,有了模块化用户就可以自己裁剪出需要的 jre 能显著地降低包的体积有利于分发;
第二点就是精细化权限,我可太喜欢这个东西了,甚至一度想把我司的屎山从 jdk8 迁移到 17 ,虽然最后没有成型,比较典型的一个场景是框架中 A module 的类只想给自己框架内部的其它 module 使用,但是很难做到这一点,设为 default 则要求其它模块使用它的类的包名与其一致,设为 public 则存在被业务滥用的风险,现在总归存在一种机制能解决这个事情了。
96 天前
回复了 Umenezumi 创建的主题 Java JDK21 是否有必要维护虚拟线程池?
不需要,不用看其它人说的直接看官方 https://openjdk.org/jeps/444
Do not pool virtual threads
有对应的 idea 插件吗,当字段类型不一致时做提示(可配置为严格模式,严格模式直接报编译错误),还有两个实体的字段差异最好也能在悬浮窗上展现出来,感觉现有的 bean copy 在这方面都不咋的。
101 天前
回复了 liubsyy 创建的主题 Java 如何获取一个类的所有对象实例?
想法挺好,就是已经有这样的轮子了
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-vmtool</artifactId>
<version>3.7.2</version>
</dependency> 而且 arthas 已经经过大规模使用验证了
小应用随便玩,大的这么玩,基于 http 接口的文档生成工具比如 swagger 就废了,你要自己手写接口文档还要维护,静态代码分析系统也没啥用了,一个应用就一个接口要干啥肯定不知道,全链路系统好一点,但也只能用 tid 去查,其它维度的查询都废了,监控告警系统基于接口的统计比如调用量、平均 rt 、95 线、97 线、99 线也都无了,简而言之可观测性被你全废了。
107 天前
回复了 nnegier 创建的主题 Java [Spring] WebSocket 怎么做到集群?
这问题想问的是推送,如何把某个用户的信息反向推送到浏览器,浏览器到用户有 nginx 代理 tcp 直接就能找到,这问题说大不大说小不小,简单来说就是维护 user 和 server 的关系,但如果 server 的量级超过 100 就会复杂的多,多活容灾每个细节都值得大费篇章。
109 天前
回复了 baolinliu442k 创建的主题 Java 实际项目中如何使用线程池
@Aresxue 其实可以把虚拟线程学起来了,有了这玩意之后绝大多数场景就不再需要线程池了,线程不会再成为应用的瓶颈,目前 jdk21 中的功能已经勉强可用,预计下个 LTS 版本能基本稳定下来。
109 天前
回复了 baolinliu442k 创建的主题 Java 实际项目中如何使用线程池
@baolinliu442k 并发度和 cpu 核数有关系但没太大关系,cpu 哪怕是单核因为时间片是轮转的从使用者视角来看任务都是并行的,回到你这个问题从普通的使用者视角可以认为同时执行 10 个任务,但如果是按真实的占用 cpu 去执行逻辑这个角度,哪怕你有 5 个核,这 5 个核同时被你的任务使用的时间几乎是没有的,因为还有 tomcat 线程、rpc 线程池等其它活跃的线程共享你的 5 个核。
110 天前
回复了 baolinliu442k 创建的主题 Java 实际项目中如何使用线程池
1.视业务而定,如果是一个低频的业务和其它业务共享一个线程池也无伤大雅,如果相对并发较高,最好是指定用自己的线程池而不是公用的线程池,@Async 也是可以指定线程池的,和 private static 的方式基本上是等价的,大多数情况下都可以用它;
2.参数没有标准,完完全全根据业务的情况而定,这个情况不仅是当下还有对未来的适当评估;
3.线程池主要是用于隔离线程资源和多参数任务并行降低 rt ,其对于整个应用资源的利用率并不会有显著的提升;
4. execute 适用于没有返回值的任务,submit 的返回值是 Future ,基本上能用 submit 没啥必要了,CompleteableFuture 本来就是为了加强 Future 的。

对于业务中我是建议能不能则不用,作为排名靠后的一个选择,顺便贴一些使用线程池的注意点:
- 合适的任务队列及其大小,过大会造成 oom ;
- ThreadLocal(登录信息上下文或其它的业务信息)丢失;
- 全链路 id 丢失;
- 合适的线程池策略和线程数(固定数目和不定数目);
- 任务重启丢失(优雅退出);
123 天前
回复了 zshineee 创建的主题 Java 请教一个 Java 查询 elasticsearch 的问题
应该不是服务端问题 ,用 arthas trace 一下看看,实际中 es 的连接数、反序列化都会影响最终的性能。
131 天前
回复了 errorMsg0xff 创建的主题 Java Java 值得读源码的开源项目
值得的:Netty
架构设计的好看的:Dubbo
理念完善的:Spring
实现巧妙的:AQS 、ConcurrentHashMap
贴近业务的:Rocketmq
131 天前
回复了 RichardX2023 创建的主题 Java Java -多线程事务无法完美实现吗
@RichardX2023 核心原因是 java.sql.Connection 不是线程安全的,所以每个线程只能独占一个链接,对于你说的 20 个任务 10 个 work 线程的情况可以对线程池加以改造,提交任务(必须是批量提交)的时候根据剩余可用连接分配一定数目的链接(这个算法决定了这个策略的健壮性),比如 20 个任务可以分配 5 个链接,然后每 4 个任务共享一个链接,当然这四个之间就要排队了对耗时的优化肯定没有一个任务一个线程效果这么好,但并发度确实也从 1 变成了 5 。
135 天前
回复了 javak 创建的主题 Java 曾经我以为 Java21 的虚拟线程是银弹...
软件工程没有银弹。
synchronized 是可以在后续被 JVM 优化掉的,而且实在不行替换成 ReentrantLock 的操作也还是比较简单的。ThreadLocal 才麻烦,不过 scoped value 成熟后应该也可以搞的定。
就是现阶段替换虚拟线程的成本和收益不明显而已,但如果是一个长远规划的项目早做早好,小项目玩玩也可以。
135 天前
回复了 tnhmcm 创建的主题 Java Spring 里怎样正确处理 InterruptedException?
@Aresxue 有些地方有口误,InterruptedException 是个 checked exception ,翻译成中文是必须要检查( throw or catch )的异常
135 天前
回复了 tnhmcm 创建的主题 Java Spring 里怎样正确处理 InterruptedException?
尽量不要用 Thread.currentThread().interrupt() ,InterruptedException 其实最好是抛出去,业务代码里除非是为了解耦主流程和辅助流程、批处理循环时隔离单条的失败等情况不建议 catch 异常,这个事情恶心的一个点在于 InterruptedException 是个 unchecked exceptions ,向上抛 java 会强制你修改你的方法签名,如果不想这么干就直接将其包装成一个运行时异常再抛出去类似 throw new PackageException(e)这样,然后在全局异常处理的地方不捕获后 unpackage 再对其做相应处理。
典型的 apm 场景,这块做的最好是 arms ,支持接口统计、聚合和下钻,不想花钱就自己整 pinpoint 或 skywalking ,parms 就是基于 pinpoint 改的,你甚至还能在 arms 的 agent 看见 pinpoint 的包名。。pinpoint 的问题就是吃资源,性能开销大但是相对好用,可以临时上上去跑一段时间查查问题,查完了再下掉。skywalking 可以作为长久方案,性能开销确实小一些,但自带的 ui 太难用,对于你这个问题各种聚合信息你可能还需要自己去 es 里面查,而且由于其实极其复杂维护是个老大难的问题。
易用性:arms > pinpoint > skywalking
性能开销:arms = pinpoint > skywalking
可维护性: arms > pinpoint > skywalking

只针对问题本身也可以通过别的方式解决,首先保证数据库请求超时会输出异常日志,核心信息是时间,然后就是统计 http 接口的信息,nginx 、tomcat 、spring-boot-starter-actuator 、jmx 都可以做这件事情,最好用的是 spring-boot-starter-actuator 结合 promethues ,可以清楚的看到每个接口在指定时间段的频次、rt ,从 grafana 上直接就能看出流量的峰谷。
1.语法,这点说实话 go 做的也一般,C#明显做的更好;
2.预占内存, jvm 的内存是直接分配的,对于中小项目内存的利用率不充分,这一点在稍大一点的企业级项目里并不是问题;
3.启动慢,其实本身 jvm 没有那么慢,传统应用慢主要受两个东西拖累,一个是 spring(用了太多反射以及 bean 必须串行注册),另一个是 UrlClassLoader 加载类的逻辑(这一点阿里自定义了一个 FastUrlClassLoader 优化了很多,实测应用启动时间可以降低 1/2~2/3);
4.对象头、字节对齐等各种操作导致在偏硬件的软件系统中性能很低下,没法充分利用寄存器,甚至容器到现在还不支持基本类型;

但我还是看好 java 的未来,庞大的生态,我心中最好的 VM(你可以永远相信 JVM)。官方也有一直在做事情:Loom 、Valhalla 、Amber ,虚拟线程也已经发布了,准备好埋葬异步编程回到 thread-per-request 的时代吧。
https://github.com/tdebatty/java-string-similarity
推荐标准莱茵斯坦算法和余弦算法,字符串较大就用余弦,对准确率要求高就莱茵斯坦算法。
附上测试一个测试类自己修改下,用自己的实际数据多跑跑

public class SimilarityAlgorithmTest {

@Test
public void test() {
String str1 = "ares";
String str2 = "kele";

LevenshteinDistance levenshtein = LevenshteinDistance.getDefaultInstance();
System.out.println("Levenshtein distance: " + levenshtein.apply(str1, str2));
System.out.println("Levenshtein distance: " + levenshtein.apply(str2, str2));

LevenshteinDistance levenshteinWithThreshold = new LevenshteinDistance(3);
// Returns -1 since the actual distance, 4, is higher than the threshold
System.out.println("Levenshtein distance: " + levenshteinWithThreshold.apply(str1, str2));

LevenshteinDetailedDistance levenshteinDetailed = LevenshteinDetailedDistance.getDefaultInstance();
System.out.println("Levenshtein detailed distance: " + levenshteinDetailed.apply(str1, str2));
}

@Test
public void testLevenshteinDistance() {
int sLength = 13_162;
int strLength = 4_000;
String s = StringUtil.random(sLength);
String s1 = StringUtil.random(strLength) + s;
String s2 = StringUtil.random(strLength) + s;

int threshold = 4_096;
LevenshteinDistance levenshtein = new LevenshteinDistance(threshold);
long startTime = System.currentTimeMillis();
/*
threshold 为 32766 时花费 7022ms
threshold 为 16384 时花费 2164ms
threshold 为 8192 时花费 463ms
threshold 为 4096 时花费 146ms
threshold 为 2048 时花费 62ms
threshold 为 1024 时花费 41ms
threshold 为 512 时花费 29ms
*/
Integer result = levenshtein.apply(s1, s2);
System.out.println(System.currentTimeMillis() - startTime);
System.out.println("Levenshtein distance: " + result);

/*
这种是截取模式比较靠前的指定字符
threshold 为 4096 时花费 67ms
*/
levenshtein = LevenshteinDistance.getDefaultInstance();
startTime = System.currentTimeMillis();
result = levenshtein.apply(s1.substring(0, threshold), s2.substring(0, threshold));
System.out.println(System.currentTimeMillis() - startTime);
System.out.println("Levenshtein distance: " + result);
System.out.println();

result = levenshtein.apply(s1, s2);
System.out.println("Levenshtein: " + (1.0 - (double) result / (strLength + sLength)));
NormalizedLevenshtein normalizedLevenshtein = new NormalizedLevenshtein();
double similarity = normalizedLevenshtein.similarity(s1, s2);
System.out.println("NormalizedLevenshtein: " + similarity);
Jaccard jaccard = new Jaccard();
similarity = jaccard.similarity(s1, s2);
System.out.println("Jaccard: " + similarity);
Cosine cosine = new Cosine();
similarity = cosine.similarity(s1, s2);
System.out.println("Cosine: " + similarity);
QGram qGram = new QGram();
similarity = qGram.distance(s1, s2);
System.out.println("QGram: " + (1.0 - similarity / (strLength + sLength)));
}


@Test
public void testAlgorithmPerformance() {
String s1 = StringUtil.random(13_162);
String s2 = StringUtil.random(13_162);

LevenshteinDistance levenshtein = LevenshteinDistance.getDefaultInstance();
long startTime = System.currentTimeMillis();
levenshtein.apply(s1, s2);
System.out.println("LevenshteinDistance:" + (System.currentTimeMillis() - startTime));

NormalizedLevenshtein normalizedLevenshtein = new NormalizedLevenshtein();
startTime = System.currentTimeMillis();
normalizedLevenshtein.distance(s1, s2);
System.out.println("NormalizedLevenshtein: " + (System.currentTimeMillis() - startTime));

JaroWinkler jaroWinkler = new JaroWinkler();
startTime = System.currentTimeMillis();
jaroWinkler.distance(s1, s2);
System.out.println("JaroWinkler: " + (System.currentTimeMillis() - startTime));

LongestCommonSubsequence longestCommonSubsequence = new LongestCommonSubsequence();
startTime = System.currentTimeMillis();
longestCommonSubsequence.apply(s1, s2);
System.out.println("LongestCommonSubsequence: " + (System.currentTimeMillis() - startTime));

info.debatty.java.stringsimilarity.MetricLCS metricLCS = new info.debatty.java.stringsimilarity.MetricLCS();
startTime = System.currentTimeMillis();
metricLCS.distance(s1, s2);
System.out.println("MetricLCS: " + (System.currentTimeMillis() - startTime));

QGram qGram = new QGram();
startTime = System.currentTimeMillis();
qGram.distance(s1, s2);
System.out.println("QGram: " + (System.currentTimeMillis() - startTime));

Cosine cosine = new Cosine();
startTime = System.currentTimeMillis();
cosine.distance(s1, s2);
System.out.println("Cosine: " + (System.currentTimeMillis() - startTime));

Jaccard jaccard = new Jaccard();
startTime = System.currentTimeMillis();
jaccard.distance(s1, s2);
System.out.println("Jaccard: " + (System.currentTimeMillis() - startTime));
}

@Test
public void testCosine() {
String s1 = StringUtil.random(1_000_000);
String s2 = StringUtil.random(1_000_000);

Cosine cosine = new Cosine();
long startTime = System.currentTimeMillis();
cosine.distance(s1, s2);
System.out.println("Cosine: " + (System.currentTimeMillis() - startTime));
}

}
最简单的就是找文档,没文档就只能自求多福了,其实本身 dll 和 maven 依赖一样都是第三方库,但由于需求不是强所以 dll 的名单从来都没有地方管理, 我理解可以做个类似 Python requirements.txt 的东西管理起来,本来 jdk 做这个事情是最合适的,其次就是 maven 插件也可以做,但现在没有任何标准的话除了翻源码就是在测试环境多测测了(保持和生产环境一致)。
1  2  3  4  5  6  7  8  9  10 ... 21  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1286 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 39ms · UTC 23:54 · PVG 07:54 · LAX 16:54 · JFK 19:54
Developed with CodeLauncher
♥ Do have faith in what you're doing.