mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-27 11:14:59 +00:00
Webclient fix (#173)
* fix(scanner): wire timeout config and create dedicated scanner HttpClient - Create scanner-specific HttpClient bean with proper timeout configuration - Wire SkillScannerProperties.connectTimeoutMs (5s) and readTimeoutMs (5min) into WebClient - Add logging for timeout configuration verification - Fix cloud environment 5-second timeout issue by ensuring responseTimeout is properly applied The previous global WebClient.Builder configuration was not being used correctly, causing scanner requests to timeout after 5 seconds in cloud environment. This fix creates a dedicated HttpClient for scanner with explicit timeout settings. * refactor(webclient): use WebClientCustomizer and add scanner connection pool - Replace singleton WebClient.Builder bean with WebClientCustomizer (follows Spring Boot best practice for prototype-scoped builder) - Add connection pool config to scanner HttpClient (maxConn=10, maxIdleTime=20s, evictInBackground=30s) to prevent stale connections - Add connectTimeout to global WebClient config * fix(skill): use system default timezone for auto-generated version numbers - Change AUTO_VERSION_FORMATTER from UTC to ZoneId.systemDefault() - Version format yyyyMMdd.HHmmss now uses server's local timezone - Update test to validate format instead of exact value (timezone-independent) This allows the service to adapt to deployment location: - Deployed in China → uses Asia/Shanghai timezone - Deployed in US → uses US timezone - Follows server's system timezone configuration
This commit is contained in:
parent
fb9b11e750
commit
1237d42119
4 changed files with 37 additions and 21 deletions
|
|
@ -33,7 +33,17 @@ public class SkillScannerConfig {
|
|||
log.info("Creating scanner-specific HttpClient with connectTimeout={}ms, readTimeout={}ms",
|
||||
connectTimeoutMs, readTimeoutMs);
|
||||
|
||||
reactor.netty.http.client.HttpClient reactorClient = reactor.netty.http.client.HttpClient.create()
|
||||
// Configure connection pool to avoid stale connections and improve reliability
|
||||
reactor.netty.resources.ConnectionProvider connectionProvider =
|
||||
reactor.netty.resources.ConnectionProvider.builder("scanner-pool")
|
||||
.maxConnections(10)
|
||||
.maxIdleTime(Duration.ofSeconds(20))
|
||||
.maxLifeTime(Duration.ofSeconds(60))
|
||||
.pendingAcquireTimeout(Duration.ofSeconds(45))
|
||||
.evictInBackground(Duration.ofSeconds(30))
|
||||
.build();
|
||||
|
||||
reactor.netty.http.client.HttpClient reactorClient = reactor.netty.http.client.HttpClient.create(connectionProvider)
|
||||
.followRedirect(false)
|
||||
.responseTimeout(Duration.ofMillis(readTimeoutMs))
|
||||
.option(io.netty.channel.ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeoutMs);
|
||||
|
|
@ -47,7 +57,7 @@ public class SkillScannerConfig {
|
|||
.exchangeStrategies(strategies)
|
||||
.build();
|
||||
|
||||
log.info("Scanner HttpClient created successfully with responseTimeout={}ms", readTimeoutMs);
|
||||
log.info("Scanner HttpClient created with connection pool (maxConn=10, maxIdleTime=20s, evictInterval=30s)");
|
||||
return new WebClientHttpClient(webClient);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ import java.util.zip.ZipOutputStream;
|
|||
public class SkillPublishService {
|
||||
|
||||
private static final DateTimeFormatter AUTO_VERSION_FORMATTER =
|
||||
DateTimeFormatter.ofPattern("yyyyMMdd.HHmmss").withZone(ZoneId.of("Asia/Shanghai"));
|
||||
DateTimeFormatter.ofPattern("yyyyMMdd.HHmmss").withZone(ZoneId.systemDefault());
|
||||
private static final Logger log = LoggerFactory.getLogger(SkillPublishService.class);
|
||||
|
||||
public record PublishResult(
|
||||
|
|
|
|||
|
|
@ -567,7 +567,10 @@ class SkillPublishServiceTest {
|
|||
SkillPublishService.PublishResult result = service.publishFromEntries(
|
||||
namespaceSlug, entries, publisherId, SkillVisibility.PUBLIC, Set.of());
|
||||
|
||||
assertEquals("20260318.200000", result.version().getVersion());
|
||||
// Version should be auto-generated in format yyyyMMdd.HHmmss using system timezone
|
||||
String version = result.version().getVersion();
|
||||
assertTrue(version.matches("\\d{8}\\.\\d{6}"), "Version should match format yyyyMMdd.HHmmss");
|
||||
assertTrue(version.startsWith("20260318"), "Version should start with date 20260318");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -1,33 +1,36 @@
|
|||
package com.iflytek.skillhub.infra.http;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.web.reactive.function.client.WebClientCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@Configuration
|
||||
public class WebClientConfig {
|
||||
|
||||
@Bean
|
||||
public WebClient.Builder webClientBuilder() {
|
||||
ExchangeStrategies strategies = ExchangeStrategies.builder()
|
||||
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024))
|
||||
.build();
|
||||
|
||||
reactor.netty.http.client.HttpClient reactorClient = reactor.netty.http.client.HttpClient.create()
|
||||
.followRedirect(false)
|
||||
.responseTimeout(Duration.ofMinutes(5));
|
||||
|
||||
return WebClient.builder()
|
||||
.clientConnector(new ReactorClientHttpConnector(reactorClient))
|
||||
.exchangeStrategies(strategies);
|
||||
}
|
||||
private static final Logger log = LoggerFactory.getLogger(WebClientConfig.class);
|
||||
|
||||
@Bean
|
||||
public HttpClient httpClient(WebClient.Builder webClientBuilder) {
|
||||
return new WebClientHttpClient(webClientBuilder.build());
|
||||
public WebClientCustomizer globalWebClientCustomizer() {
|
||||
log.info("Registering global WebClientCustomizer with 5-minute responseTimeout and 10-second connectTimeout");
|
||||
|
||||
return builder -> {
|
||||
ExchangeStrategies strategies = ExchangeStrategies.builder()
|
||||
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024))
|
||||
.build();
|
||||
|
||||
reactor.netty.http.client.HttpClient reactorClient = reactor.netty.http.client.HttpClient.create()
|
||||
.followRedirect(false)
|
||||
.responseTimeout(Duration.ofMinutes(5))
|
||||
.option(io.netty.channel.ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
|
||||
|
||||
builder.clientConnector(new ReactorClientHttpConnector(reactorClient))
|
||||
.exchangeStrategies(strategies);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue