From 350258b881d3ca154c8341ebf0bb636b26953905 Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Thu, 12 Nov 2026 20:03:44 +0800 Subject: [PATCH] =?UTF-8?q?=E9=85=92=E5=BA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SmHotelDownstreamChannelConfigDTO.java | 5 ++++- .../config/HotelDownstreamProperties.java | 10 +++++----- .../huanqi/HuanqiDownstreamHotelAdapter.java | 20 ++++++++++++++----- .../impl/SmHotelChannelConfigServiceImpl.java | 3 +++ 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/SmHotelDownstreamChannelConfigDTO.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/SmHotelDownstreamChannelConfigDTO.java index 7867f05ed..6dfa8df31 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/SmHotelDownstreamChannelConfigDTO.java +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/SmHotelDownstreamChannelConfigDTO.java @@ -53,7 +53,7 @@ public class SmHotelDownstreamChannelConfigDTO { @Schema(description = "hotel/apartment 每分钟上限,默认 600;≤0 关闭") private Integer rateLimitHotelApartmentPerMin; - @Schema(description = "product/daily 每分钟上限,默认 300;≤0 关闭") + @Schema(description = "product/daily 每分钟上限,默认 150(环启 2026-10-26);≤0 关闭") private Integer rateLimitProductDailyPerMin; @Schema(description = "慧订 hoteldatepush 出站 QPS,默认 5;≤0 关闭") @@ -112,4 +112,7 @@ public class SmHotelDownstreamChannelConfigDTO { @Schema(description = "本地改价/库存/房态后是否自动推本伙伴;大批量补数可临时 false,默认 true(未配则跟进程级)") private Boolean resourceAutoPushEnabled; + + @Schema(description = "全量/日更推送酒店并发;环启建议 ≤3,默认 2;1=串行") + private Integer resourcePushConcurrency; } diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/config/HotelDownstreamProperties.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/config/HotelDownstreamProperties.java index 2b8023aa7..c8b8a317e 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/config/HotelDownstreamProperties.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/config/HotelDownstreamProperties.java @@ -67,8 +67,8 @@ public class HotelDownstreamProperties { /** /hotel/sync、/apartment/sync 每分钟上限(环启文档 600) */ private int rateLimitHotelApartmentPerMin = 600; - /** /product/sync、/daily/sync 每分钟上限(环启文档 300) */ - private int rateLimitProductDailyPerMin = 300; + /** /product/sync、/daily/sync 每分钟上限(环启文档 2026-10-26 起 150) */ + private int rateLimitProductDailyPerMin = 150; /** * 慧订 /splider/hoteldatepush 出站 QPS(对方已限流)。 @@ -193,8 +193,8 @@ public class HotelDownstreamProperties { private String resourcePushCron = "0 30 2 * * ?"; /** - * 下游全量推酒店并发(圣诺等 HTTP 出站)。1=串行;建议 4~8。 - * 对方限流时报错再调低。伙伴 YAML 可覆盖。 + * 下游全量推酒店并发。1=串行。 + * 环启文档建议并发≤3(产品/日历写重);默认 2。圣诺若对方宽松可在 YAML 调高。 */ - private int resourcePushConcurrency = 6; + private int resourcePushConcurrency = 2; } diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/integration/downstream/huanqi/HuanqiDownstreamHotelAdapter.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/integration/downstream/huanqi/HuanqiDownstreamHotelAdapter.java index 309671875..08b3afb7b 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/integration/downstream/huanqi/HuanqiDownstreamHotelAdapter.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/integration/downstream/huanqi/HuanqiDownstreamHotelAdapter.java @@ -187,14 +187,17 @@ public class HuanqiDownstreamHotelAdapter implements DownstreamHotelAdapter { } } - /** 按 appKey + 接口组做分钟窗限流(多实例共享 Redis) */ + /** + * 按 appKey + 接口组做分钟窗限流(多实例共享 Redis)。 + * 超限时必须 decrement 退回占用并等待,禁止「等超时仍继续」——否则会把对方打到「访问过于频繁」。 + */ private void acquireRatePermit(HotelDownstreamProperties props, String path) { int limit = resolveRateLimit(props, path); if (limit <= 0 || StrUtil.isBlank(props.getAppKey())) { return; } String group = rateGroup(path); - for (int i = 0; i < 60; i++) { + for (int i = 0; i < 120; i++) { long minute = System.currentTimeMillis() / 60_000L; String key = RATE_KEY + props.getAppKey() + ":" + group + ":" + minute; Long n = redisTemplate.opsForValue().increment(key); @@ -204,10 +207,17 @@ public class HuanqiDownstreamHotelAdapter implements DownstreamHotelAdapter { if (n == null || n <= limit) { return; } - long wait = 60_000L - (System.currentTimeMillis() % 60_000L) + 20L; - sleepQuiet(Math.min(wait, 5000L)); + // 超限:退回本次数,避免循环里反复 increment 把窗口计数打爆 + try { + redisTemplate.opsForValue().decrement(key); + } + catch (Exception ignored) { + // ignore + } + long wait = 60_000L - (System.currentTimeMillis() % 60_000L) + 80L; + sleepQuiet(Math.min(Math.max(wait, 200L), 3000L)); } - log.warn("|{}|限流等待超时仍继续|appKey={}|path={}|limit={}|", TAG, props.getAppKey(), path, limit); + throw new CheckedException("下游限流等待超时(" + group + "≤" + limit + "/min),请降低推送并发或错峰再试"); } private static int resolveRateLimit(HotelDownstreamProperties props, String path) { diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelChannelConfigServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelChannelConfigServiceImpl.java index a006654ac..5a8a5d280 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelChannelConfigServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelChannelConfigServiceImpl.java @@ -409,6 +409,9 @@ public class SmHotelChannelConfigServiceImpl extends ServiceImpl 0) { + target.setResourcePushConcurrency(dto.getResourcePushConcurrency()); + } } private void overlayShangyou(ShangyouHotelProperties target, SmHotelShangyouChannelConfigDTO dto) {