Poison


  • 首页

  • 归档

  • 标签

  • 搜索
close
Poison

Active Connections

发表于 2022-01-06

业务方反馈一到晚上就有接口时好时坏,用浏览器访问的话表现就是一直处于 pending 状态,直到超时,多次尝试的话有时又会恢复正常。开始怀疑是接口内部实现问题,于是我在多个请求处于 pending 状态时拉取了栈帧进行检查,发现没有符合该接口实现的栈帧。于是怀疑连接建立问题,使用 telnet 443 对负载均衡服务器发起连接,表现也是卡住,于是去查了该负载均衡实例的监控,果然是活跃连接数已经达到该实例的上限导致,因为当时选用的最低配,根本不能支撑现有的业务量,于是直接升配解决。可以猜测该实例到达连接数上限时采取的策略是丢弃 SYN 包,导致客户端重传直到超时,而没有采取直接返回 RST 的方式。当然这只是我根据现象进行的推测,具体的原因可以用 Wireshark 抓包确认,只不过这次还没用到就解决了该问题。

之前遇到类似的问题,最后排查出来是因为风控系统将特定 IP 加入了负载均衡层的黑名单,表现也是一直处于 pending 状态,猜测负载均衡服务器的实现也是丢弃 SYN 包。

References

怎么理解SLB的并发连接数和PTS里的并发? - 性能测试 PTS - 阿里云

Poison

ScheduledAnnotationBeanPostProcessor

发表于 2022-01-05

设置调度器的核心逻辑位于 ScheduledAnnotationBeanPostProcessor.java at v4.3.16.RELEASE:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (event.getApplicationContext() == this.applicationContext) {
// Running in an ApplicationContext -> register tasks this late...
// giving other ContextRefreshedEvent listeners a chance to perform
// their work at the same time (e.g. Spring Batch's job registration).
finishRegistration();
}
}

private void finishRegistration() {
if (this.scheduler != null) {
this.registrar.setScheduler(this.scheduler);
}

if (this.beanFactory instanceof ListableBeanFactory) {
Map<String, SchedulingConfigurer> beans =
((ListableBeanFactory) this.beanFactory).getBeansOfType(SchedulingConfigurer.class);
List<SchedulingConfigurer> configurers = new ArrayList<SchedulingConfigurer>(beans.values());
AnnotationAwareOrderComparator.sort(configurers);
for (SchedulingConfigurer configurer : configurers) {
configurer.configureTasks(this.registrar);
}
}

if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) {
Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type");
try {
// Search for TaskScheduler bean...
this.registrar.setTaskScheduler(resolveSchedulerBean(TaskScheduler.class, false));
}
catch (NoUniqueBeanDefinitionException ex) {
logger.debug("Could not find unique TaskScheduler bean", ex);
try {
this.registrar.setTaskScheduler(resolveSchedulerBean(TaskScheduler.class, true));
}
catch (NoSuchBeanDefinitionException ex2) {
if (logger.isInfoEnabled()) {
logger.info("More than one TaskScheduler bean exists within the context, and " +
"none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +
"(possibly as an alias); or implement the SchedulingConfigurer interface and call " +
"ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +
ex.getBeanNamesFound());
}
}
}
catch (NoSuchBeanDefinitionException ex) {
logger.debug("Could not find default TaskScheduler bean", ex);
// Search for ScheduledExecutorService bean next...
try {
this.registrar.setScheduler(resolveSchedulerBean(ScheduledExecutorService.class, false));
}
catch (NoUniqueBeanDefinitionException ex2) {
logger.debug("Could not find unique ScheduledExecutorService bean", ex2);
try {
this.registrar.setScheduler(resolveSchedulerBean(ScheduledExecutorService.class, true));
}
catch (NoSuchBeanDefinitionException ex3) {
if (logger.isInfoEnabled()) {
logger.info("More than one ScheduledExecutorService bean exists within the context, and " +
"none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +
"(possibly as an alias); or implement the SchedulingConfigurer interface and call " +
"ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +
ex2.getBeanNamesFound());
}
}
}
catch (NoSuchBeanDefinitionException ex2) {
logger.debug("Could not find default ScheduledExecutorService bean", ex2);
// Giving up -> falling back to default scheduler within the registrar...
logger.info("No TaskScheduler/ScheduledExecutorService bean found for scheduled processing");
}
}
}

this.registrar.afterPropertiesSet();
}
阅读全文 »
Poison

ByteOrder

发表于 2021-12-27

Bits 类中通过申请 8 字节的内存,然后填入一个 Long 类型的数字再根据头部字节判断出大端序还是小端序,源码位于 jdk/Bits.java at jdk8-b120:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static {
long a = unsafe.allocateMemory(8);
try {
unsafe.putLong(a, 0x0102030405060708L);
byte b = unsafe.getByte(a);
switch (b) {
case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break;
case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break;
default:
assert false;
byteOrder = null;
}
} finally {
unsafe.freeMemory(a);
}
}
Poison

System.gc()

发表于 2021-12-25

有不少观点认为调用 System.gc() 是一个不好的习惯,当我看到 JDK 8 中 FileChannelImpl 的 map 方法实现时,其中对 System.gc() 的调用让我感到诧异。在 FileChannelImpl 中存在如下代码 FileChannelImpl.java at jdk8-b120:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
try {
// If no exception was thrown from map0, the address is valid
addr = map0(imode, mapPosition, mapSize);
} catch (OutOfMemoryError x) {
// An OutOfMemoryError may indicate that we've exhausted memory
// so force gc and re-attempt map
System.gc();
try {
Thread.sleep(100);
} catch (InterruptedException y) {
Thread.currentThread().interrupt();
}
try {
addr = map0(imode, mapPosition, mapSize);
} catch (OutOfMemoryError y) {
// After a second OOME, fail
throw new IOException("Map failed", y);
}
}
阅读全文 »
Poison

Open Addressing

发表于 2021-12-25

开放定址法是哈希表冲突解决的一种方法,该方法通过探测未使用的数组槽来解决散列冲突。常见的探测方法包括:

  • 线性探测
    探测的间隔是固定的,通常为 1。
  • 平方探测
    探测的间隔呈二次方增加。
  • 两次哈希
    探测的间隔依然是固定的,只是间隔由另一个哈希函数计算得出。

这些方法的主要区别在于线性探测具有最好的缓存性能,但是对聚集敏感,虽然两次哈希的缓存性能很差,但是几乎不存在聚集的问题,平方探测介于两者之间。相比其他的探测方法,两次哈希需要更多的计算。

阅读全文 »
1…8910…27

131 日志
119 标签
GitHub LeetCode
© 2025 Poison 蜀ICP备16000644号
由 Hexo 强力驱动
主题 - NexT.Mist