Skip to content

Commit ce49241

Browse files
authored
Merge pull request #1588 from yue9944882/feat/informer-processor-zero-readtimeout
Enforcing read-timeout for informer-factory processor via property "kubernetes.informer.clientReadTimeout" (default 5min)
2 parents 9b25290 + 63abb43 commit ce49241

File tree

4 files changed

+62
-1
lines changed

4 files changed

+62
-1
lines changed

spring/src/main/java/io/kubernetes/client/spring/extended/controller/KubernetesInformerFactoryProcessor.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,14 @@
2020
import io.kubernetes.client.openapi.ApiClient;
2121
import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformer;
2222
import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers;
23+
import io.kubernetes.client.spring.extended.controller.config.KubernetesInformerProperties;
24+
import io.kubernetes.client.spring.extended.controller.factory.KubernetesControllerFactory;
2325
import io.kubernetes.client.util.generic.GenericKubernetesApi;
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
2428
import org.springframework.beans.BeansException;
2529
import org.springframework.beans.factory.BeanFactory;
30+
import org.springframework.beans.factory.annotation.Autowired;
2631
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2732
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
2833
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -45,6 +50,10 @@ public class KubernetesInformerFactoryProcessor
4550

4651
public static final int ORDER = 0;
4752

53+
private static final Logger log = LoggerFactory.getLogger(KubernetesControllerFactory.class);
54+
55+
@Autowired private KubernetesInformerProperties informerProperties;
56+
4857
private ConfigurableListableBeanFactory beanFactory;
4958

5059
@Override
@@ -122,6 +131,20 @@ private <T extends KubernetesObject> Lister<T> lister(Class<T> type) {
122131
private <T extends KubernetesObject> SharedInformer<T> informer(
123132
Class<T> type, KubernetesInformer kubernetesInformer) {
124133
ApiClient apiClient = this.beanFactory.getBean(ApiClient.class);
134+
135+
if (apiClient.getHttpClient().readTimeoutMillis() > 0) {
136+
log.warn(
137+
"Enforcing read-timeout of the ApiClient {} to {} so that the watch connection won't abort from client-side",
138+
apiClient,
139+
informerProperties.getClientReadTimeout());
140+
apiClient.setHttpClient(
141+
apiClient
142+
.getHttpClient()
143+
.newBuilder()
144+
.readTimeout(informerProperties.getClientReadTimeout())
145+
.build());
146+
}
147+
125148
SharedInformerFactory sharedInformerFactory =
126149
this.beanFactory.getBean(SharedInformerFactory.class);
127150
final GenericKubernetesApi api =

spring/src/main/java/io/kubernetes/client/spring/extended/controller/config/KubernetesInformerAutoConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
import io.kubernetes.client.util.ClientBuilder;
1919
import java.io.IOException;
2020
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
21+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2122
import org.springframework.context.annotation.Bean;
2223
import org.springframework.context.annotation.Configuration;
2324

2425
@Configuration(proxyBeanMethods = false)
2526
@ConditionalOnKubernetesInformerEnabled
27+
@EnableConfigurationProperties({
28+
KubernetesInformerProperties.class,
29+
})
2630
public class KubernetesInformerAutoConfiguration {
2731

2832
@Bean
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
package io.kubernetes.client.spring.extended.controller.config;
14+
15+
import io.kubernetes.client.informer.cache.ReflectorRunnable;
16+
import java.time.Duration;
17+
import org.springframework.boot.context.properties.ConfigurationProperties;
18+
19+
@ConfigurationProperties("kubernetes.informer")
20+
public class KubernetesInformerProperties {
21+
22+
private Duration clientReadTimeout = ReflectorRunnable.REFLECTOR_WATCH_CLIENTSIDE_TIMEOUT;
23+
24+
public Duration getClientReadTimeout() {
25+
return clientReadTimeout;
26+
}
27+
28+
public KubernetesInformerProperties setClientReadTimeout(Duration clientReadTimeout) {
29+
this.clientReadTimeout = clientReadTimeout;
30+
return this;
31+
}
32+
}

util/src/main/java/io/kubernetes/client/informer/cache/ReflectorRunnable.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class ReflectorRunnable<
3737
ApiType extends KubernetesObject, ApiListType extends KubernetesListObject>
3838
implements Runnable {
3939

40+
public static Duration REFLECTOR_WATCH_CLIENTSIDE_TIMEOUT = Duration.ofMinutes(5);
41+
4042
private static final Logger log = LoggerFactory.getLogger(ReflectorRunnable.class);
4143

4244
private String lastSyncResourceVersion;
@@ -113,7 +115,7 @@ public void run() {
113115
new CallGeneratorParams(
114116
Boolean.TRUE,
115117
lastSyncResourceVersion,
116-
Long.valueOf(Duration.ofMinutes(5).getSeconds()).intValue()));
118+
Long.valueOf(REFLECTOR_WATCH_CLIENTSIDE_TIMEOUT.getSeconds()).intValue()));
117119

118120
synchronized (this) {
119121
if (!isActive.get()) {

0 commit comments

Comments
 (0)