fix: prefer healthy native media edges

This commit is contained in:
winchen
2026-08-01 12:05:35 +08:00
parent e6d5dfbfc1
commit b492a5ff76
2 changed files with 70 additions and 8 deletions
+35 -4
View File
@@ -61,6 +61,27 @@ function mediaProxyCacheRoot(): string
return $root;
}
function mediaProxyPreferredIps(): array
{
$configured = preg_split('/[,\s]+/', webImEnv('JC_WEB_IM_MEDIA_PROXY_IPS')) ?: [];
$ips = [];
foreach ($configured as $ip) {
$ip = trim($ip);
if (
$ip !== ''
&& filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
) !== false
) {
$ips[$ip] = $ip;
}
}
return array_values($ips);
}
function mediaProxyMime(string $path): string
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
@@ -76,8 +97,14 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
{
$deadline = microtime(true) + WEB_MEDIA_PROXY_MAX_SECONDS;
$lastError = '媒体源无响应';
$preferredIps = mediaProxyPreferredIps();
$targets = array_merge($preferredIps, array_fill(0, max(2, 6 - count($preferredIps)), null));
for ($attempt = 1; $attempt <= 6 && microtime(true) < $deadline; $attempt++) {
foreach ($targets as $index => $preferredIp) {
if (microtime(true) >= $deadline) {
break;
}
$attempt = $index + 1;
$temporaryFile = $cacheFile . '.tmp.' . getmypid() . '.' . $attempt;
$stream = @fopen($temporaryFile, 'x+b');
if ($stream === false) {
@@ -96,7 +123,7 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
}
$remainingMs = max(1000, (int)floor(($deadline - microtime(true)) * 1000));
curl_setopt_array($curl, [
$curlOptions = [
CURLOPT_RETURNTRANSFER => false,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_CONNECTTIMEOUT_MS => min(2500, $remainingMs),
@@ -123,7 +150,11 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
$bytes += $written;
return $written;
},
]);
];
if (is_string($preferredIp) && $preferredIp !== '') {
$curlOptions[CURLOPT_RESOLVE] = [$host . ':443:' . $preferredIp];
}
curl_setopt_array($curl, $curlOptions);
$result = curl_exec($curl);
$status = (int)curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
@@ -147,7 +178,7 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
$lastError = $tooLarge
? '图片超过代理大小限制'
: ($curlError !== '' ? $curlError : ($status > 0 ? '媒体源返回 HTTP ' . $status : '媒体源无响应'));
if ($attempt < 6 && microtime(true) < $deadline) {
if ($attempt < count($targets) && microtime(true) < $deadline) {
usleep(150000);
}
}
+35 -4
View File
@@ -61,6 +61,27 @@ function mediaProxyCacheRoot(): string
return $root;
}
function mediaProxyPreferredIps(): array
{
$configured = preg_split('/[,\s]+/', webImEnv('JC_WEB_IM_MEDIA_PROXY_IPS')) ?: [];
$ips = [];
foreach ($configured as $ip) {
$ip = trim($ip);
if (
$ip !== ''
&& filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
) !== false
) {
$ips[$ip] = $ip;
}
}
return array_values($ips);
}
function mediaProxyMime(string $path): string
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
@@ -76,8 +97,14 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
{
$deadline = microtime(true) + WEB_MEDIA_PROXY_MAX_SECONDS;
$lastError = '媒体源无响应';
$preferredIps = mediaProxyPreferredIps();
$targets = array_merge($preferredIps, array_fill(0, max(2, 6 - count($preferredIps)), null));
for ($attempt = 1; $attempt <= 6 && microtime(true) < $deadline; $attempt++) {
foreach ($targets as $index => $preferredIp) {
if (microtime(true) >= $deadline) {
break;
}
$attempt = $index + 1;
$temporaryFile = $cacheFile . '.tmp.' . getmypid() . '.' . $attempt;
$stream = @fopen($temporaryFile, 'x+b');
if ($stream === false) {
@@ -96,7 +123,7 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
}
$remainingMs = max(1000, (int)floor(($deadline - microtime(true)) * 1000));
curl_setopt_array($curl, [
$curlOptions = [
CURLOPT_RETURNTRANSFER => false,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_CONNECTTIMEOUT_MS => min(2500, $remainingMs),
@@ -123,7 +150,11 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
$bytes += $written;
return $written;
},
]);
];
if (is_string($preferredIp) && $preferredIp !== '') {
$curlOptions[CURLOPT_RESOLVE] = [$host . ':443:' . $preferredIp];
}
curl_setopt_array($curl, $curlOptions);
$result = curl_exec($curl);
$status = (int)curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
@@ -147,7 +178,7 @@ function fetchMediaProxyImage(string $url, string $host, string $cacheFile): voi
$lastError = $tooLarge
? '图片超过代理大小限制'
: ($curlError !== '' ? $curlError : ($status > 0 ? '媒体源返回 HTTP ' . $status : '媒体源无响应'));
if ($attempt < 6 && microtime(true) < $deadline) {
if ($attempt < count($targets) && microtime(true) < $deadline) {
usleep(150000);
}
}