CLIENT的CACHE清理失败再记录

本文探讨了APACHE服务器中因EXPIRES模块设置导致的客户端缓存过期时间过长问题,详细分析了即使修改了HTTP.CONF文件中的CACHE-CONTROL配置仍无法即时更新缓存的原因,并讨论了可能的解决方案。

网站由于前期同事在APACHE作了EXPIRE模块,所有在CLIENTCACHE过期时间设置得过长。

现在遇到的问题是,尽管已在APACHEHTTP.CONF设置了CACHE-CONTROL的内容,但除非在CLIENT端用F5或是CTRL+F5强制刷新的话,不然,打开新的浏览器或是MOUSE重新点击不会得到新的内容。

PAGESPEED,HTTPWATCH等查看CLIENTHTTPD HEADER内容,服务器设置生效,但客户端依然故我。

于是,用WIRESHARK抓包,原来,浏览器新窗口访问网站时,网站只返回了304代码,NOT MODIFIED,然后,未推送新的内容。原因是URLEXPIRED时间设置得太久,last modified,If-Modified-Since这些时间戳完全派不上用场,于是,APACHE就直接发送304代码了。

试过以下方案,无效。

http://stackoverflow.com/questions/3752658/how-to-have-apache-always-return-code-200-with-data-instead-of-304

Add the following directive to your apache config file

RequestHeader unset If-Modified-Since

This will ignore IF-Modified-Since header sent from client so you will get not 304 Not Modified response.

据说,要这样才可以,这就搞大发了呀~~

You can force browsers to cache something, but

You can't force browsers to clear their cache.

Thus the only (AMAIK) way is to use a new URL for your resources. Something like versioning.

~~~~~~

 

今天,继续跟进看看。如果失败,那是天意~~

1.# E:\AI_System\utils\path_utils.py import os import re import json import time import logging from pathlib import Path # 尝试导入Windows相关模块 try: import win32com.client HAS_WIN32COM = True except ImportError: HAS_WIN32COM = False # 全局配置 _CONFIG = { "MODELS_ROOT": os.getenv("AI_MODELS_ROOT", "E:\\AI_Models"), # 可配置模型根目录 "CACHE_MAX_SIZE": 100, # 路径缓存最大条目 "MODEL_NAME_VARIANTS": ["-base", "-main", "", "_", "-", "."] # 模型名称变体规则 } # 路径缓存(带LRU淘汰机制) _path_cache = {} _cache_order = [] logger = logging.getLogger("PathUtils") logger.setLevel(logging.INFO) def normalize_path(path: str) -> str: """增强版路径标准化:处理环境变量、用户目录、相对路径和快捷方式""" if not path: return "" # 缓存检查(带自动清理) if path in _path_cache: if path in _cache_order: _cache_order.remove(path) _cache_order.append(path) # 更新使用时间 return _path_cache[path] # 环境变量替换 expanded = os.path.expandvars(os.path.expanduser(path)) # 快捷方式解析 if expanded.lower().endswith('.lnk'): try: target = resolve_shortcut(expanded) if target: expanded = target logger.info(f"🔗 解析快捷方式: {path} -> {expanded}") else: logger.warning(f"⚠️ 快捷方式解析失败: {path}") except Exception as e: logger.error(f"❌ 快捷方式解析异常: {path} - {str(e)}") # 绝对路径转换 abs_path = os.path.abspath(expanded) # 缓存管理 if len(_path_cache) >= _CONFIG["CACHE_MAX_SIZE"] and _cache_order: oldest = _cache_order.pop(0) del _path_cache[oldest] _path_cache[path] = abs_path _cache_order.append(path) return abs_path def resolve_shortcut(shortcut_path: str) -> str: """专用快捷方式解析函数(返回完整路径)""" if not HAS_WIN32COM: logger.error("❌ win32com未安装,无法解析快捷方式") return None try: shell = win32com.client.Dispatch("WScript.Shell") shortcut = shell.CreateShortcut(normalize_path(shortcut_path)) return shortcut.Targetpath except Exception as e: logger.error(f"❌ 快捷方式解析失败: {shortcut_path} - {str(e)}") return None def is_valid_hf_id(model_id: str) -> bool: """增强版HF ID验证""" if not isinstance(model_id, str) or '/' not in model_id: return False # 更宽松的用户名规则(允许数字开头) return all( re.match(r"^[\w\-\.]{3,50}$", part) for part in model_id.split('/', 1) ) def find_model_path(model_name: str) -> str: """智能模型路径查找(支持模糊匹配)""" base_dir = _CONFIG["MODELS_ROOT"] if not os.path.exists(base_dir): logger.warning(f"⚠️ 模型根目录不存在: {base_dir}") return None # 直接路径匹配 direct_path = os.path.join(base_dir, model_name) if os.path.exists(direct_path): return normalize_path(direct_path) # 生成候选名称变体 candidates = set() # 基础变体(大小写/符号) for sep in _CONFIG["MODEL_NAME_VARIANTS"]: candidates.add(model_name.lower() + sep) candidates.add(model_name.upper() + sep) candidates.add(model_name.replace("-", sep)) candidates.add(model_name.replace("_", sep)) # 添加子目录候选 for root, dirs, _ in os.walk(base_dir): for d in dirs: if model_name.lower() in d.lower(): candidates.add(os.path.join(root, d)) # 优先级匹配 for candidate in candidates: full_path = os.path.join(base_dir, candidate) if os.path.exists(full_path): logger.info(f"🔍 找到模型变体: {model_name} -> {candidate}") return normalize_path(full_path) # 低效但彻底的全盘扫描(仅限顶级目录) for item in os.listdir(base_dir): if model_name.lower() in item.lower(): full_path = os.path.join(base_dir, item) if os.path.isdir(full_path): return normalize_path(full_path) return None def get_all_model_paths() -> dict: """获取所有模型路径并缓存""" model_paths = {} base_dir = _CONFIG["MODELS_ROOT"] if not os.path.exists(base_dir): logger.warning(f"⚠️ 模型根目录不存在: {base_dir}") return model_paths cache_file = os.path.join(base_dir, ".model_paths.cache") # 缓存检查(1天内有效) if os.path.exists(cache_file): mtime = os.path.getmtime(cache_file) if time.time() - mtime < 86400: # 24小时 try: with open(cache_file, 'r', encoding='utf-8') as f: return json.load(f) except Exception as e: logger.error(f"❌ 缓存文件读取失败: {e}") # 重新扫描模型目录 for root, dirs, files in os.walk(base_dir): # 只收集包含模型文件的目录 model_files = [f for f in files if f.endswith(('.bin', '.safetensors', '.pth', '.pt', '.ckpt'))] if model_files: model_name = os.path.basename(root) model_paths[model_name] = normalize_path(root) # 写入缓存 try: with open(cache_file, 'w', encoding='utf-8') as f: json.dump(model_paths, f, ensure_ascii=False, indent=2) except Exception as e: logger.error(f"❌ 缓存文件写入失败: {e}") return model_paths def set_models_root(new_path: str): """动态设置模型根目录""" global _CONFIG normalized = normalize_path(new_path) if os.path.isdir(normalized): _CONFIG["MODELS_ROOT"] = normalized logger.info(f"🔄 更新模型根目录: {normalized}") clean_path_cache() else: logger.error(f"❌ 无效的模型目录: {new_path}") def clean_path_cache(): """增强版缓存清理""" global _path_cache, _cache_order _path_cache = {} _cache_order = [] logger.info("✅ 路径缓存已完全清除") def resolve_shortcut_robust(path: str) -> str: """解析Windows快捷方式(.lnk) - 修复版(多方法尝试)""" if not path.lower().endswith('.lnk'): return path # 方法1: 使用win32com (首选) if HAS_WIN32COM: try: shell = win32com.client.Dispatch("WScript.Shell") shortcut = shell.CreateShortcut(path) target = shortcut.Targetpath if target and os.path.exists(target): return target except Exception as e: logger.warning(f"win32com快捷方式解析失败: {path} - {e}") # 方法2: 手动解析 (备用) try: with open(path, 'rb') as f: content = f.read() # 查找目标路径的位置 (简化版) # 实际.lnk文件格式复杂,这里只是简单尝试 utf16_pos = content.find(b'\x00\x00\x00') if utf16_pos != -1: # 尝试提取UTF-16字符串 try: target = content[utf16_pos + 3:].split(b'\x00\x00')[0].decode('utf-16le', errors='ignore') if os.path.exists(target): return target except: pass # 尝试查找常见路径模式 for encoding in ['utf-16le', 'utf-8', 'latin-1']: try: decoded = content.decode(encoding, errors='ignore') # 查找看起来像路径的字符串 path_patterns = [ r"[A-Za-z]:\\[^<>:\"/\\|?*]{1,255}", r"\\\\[^<>:\"/\\|?*]{1,255}\\" ] for pattern in path_patterns: matches = re.findall(pattern, decoded) for match in matches: if os.path.exists(match): return match except: continue except Exception as e: logger.warning(f"手动快捷方式解析失败: {path} - {e}") return None # 兼容性别名 resolve_lnk = resolve_shortcut 2.# 添加快捷方式解析缓存 _SHORTCUT_CACHE = {} def resolve_shortcut(shortcut_path, max_retries=3): """带缓存和重试机制的快捷方式解析""" if shortcut_path in _SHORTCUT_CACHE: return _SHORTCUT_CACHE[shortcut_path] for _ in range(max_retries): try: import win32com.client shell = win32com.client.Dispatch("WScript.Shell") shortcut = shell.CreateShortCut(shortcut_path) target = shortcut.Targetpath if target and os.path.exists(target): _SHORTCUT_CACHE[shortcut_path] = target return target except Exception as e: time.sleep(0.1) # 短暂延迟后重试 return None
最新发布
08-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值