镜像回源常见问题

更新时间:2025-02-20 05:53:03

本文介绍使用OSS镜像回源功能的常见问题和排查方法。

镜像回源文件大小与源站文件大小不一致?

如果镜像回源文件大小与源站文件大小不一致,可以按照以下步骤进行排查。

  1. 检查镜像回源文件和源站文件的Last-Modified时间戳。

    import oss2
    import requests
    from datetime import datetime
    from oss2.credentials import EnvironmentVariableCredentialsProvider
    
    # 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
    auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
    
    # 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
    
    # 填写Endpoint对应的Region信息,例如cn-hangzhou。注意,v4签名下,必须填写该参数
    region = "cn-hangzhou"
    
    # yourBucketName填写配置镜像回源规则的Bucket名称。
    bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
    # 填写镜像回源文件的完整路径。
    object_key = 'yourObjectKey'
    # 填写源站文件的完整路径。
    source_url = 'yourSourceUrl'
    
    # 获取镜像回源文件的Last-Modified时间戳
    oss_object_info = bucket.get_object_meta(object_key)
    oss_last_modified = oss_object_info.headers['last-modified']
    print(f"OSS Last-Modified: {oss_last_modified}")
    
    # 获取源站文件的Last-Modified时间戳。
    response = requests.head(source_url)
    source_last_modified = response.headers.get('last-modified')
    print(f"Source Last-Modified: {source_last_modified}")
    
    # 将字符串格式的时间戳转换为datetime对象以便比较。
    oss_time = datetime.strptime(oss_last_modified, '%a, %d %b %Y %H:%M:%S %Z')
    source_time = datetime.strptime(source_last_modified, '%a, %d %b %Y %H:%M:%S %Z')
    
    if oss_time < source_time:
        print("源站文件更新了")
    elif oss_time > source_time:
        print("镜像回源文件较新")
    else:
        print("两个文件的时间戳一致")
    • 如果源文件的Last-Modified时间戳 > 镜像回源文件的Last-Modified时间戳,表明镜像回源文件生成之后,源文件可能更新过。

      说明

      OSS从源站获取文件并写入目标Bucket时,不会保留源文件的Last-Modified时间戳(即源文件最后一次修改的时间)。相反,OSS会将镜像回源文件的Last-Modified时间戳设置为该文件通过镜像回源功能被创建或更新到OSS上的时间。

    • 如果源文件的Last-Modified时间戳镜像回源文件的Last-Modified时间戳,表明镜像回源文件生成之后,源文件没有更新。需要继续下一步,检查两者的MD5CRC64校验值。

  2. 比较镜像回源文件和源文件的MD5CRC64校验值。

    # -*- coding: utf-8 -*-
    import oss2
    import hashlib
    import requests
    from oss2.credentials import EnvironmentVariableCredentialsProvider
    
    # 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
    auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
    
    # 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
    
    # 填写Endpoint对应的Region信息,例如cn-hangzhou。注意,v4签名下,必须填写该参数
    region = "cn-hangzhou"
    
    # yourBucketName填写配置镜像回源规则的Bucket名称。
    bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
    # 填写镜像回源文件的完整路径。
    object_key = 'yourObjectKey'
    # 填写源站文件的完整路径。
    source_url = 'yourSourceUrl'
    
    # 获取镜像回源文件的元数据。
    oss_object_info = bucket.get_object_meta(object_key)
    
    oss_md5 = oss_object_info.headers.get('etag', '').strip('"')  # ETag通常为MD5
    oss_crc64 = oss_object_info.headers.get('x-oss-hash-crc64ecma', '')
    
    print(f"OSS MD5: {oss_md5}")
    print(f"OSS CRC64: {oss_crc64}")
    
    # 获取源站文件的内容并计算MD5和CRC64。
    response = requests.get(source_url)
    if response.status_code == 200:
        source_content = response.content
        source_md5 = hashlib.md5(source_content).hexdigest()
        print(f"Source MD5: {source_md5}")
    
        # 如果需要比较CRC64,由于Python标准库不支持CRC64,可以使用第三方库如`crcmod`
        # 安装crcmod:pip install crcmod
        import crcmod
        crc64_func = crcmod.predefined.mkCrcFun('crc-64')
        source_crc64 = hex(crc64_func(source_content))[2:].upper().zfill(16)  # 转换为16进制字符串并格式化
        print(f"Source CRC64: {source_crc64}")
    
        # 比较MD5值。
        if oss_md5 == source_md5:
            print("MD5校验值一致")
        else:
            print("MD5校验值不一致")
    
        # 比较CRC64值。
        if oss_crc64.upper() == source_crc64:
            print("CRC64校验值一致")
        else:
            print("CRC64校验值不一致")
    else:
        print(f"Failed to fetch source file. HTTP Status Code: {response.status_code}")
        
    • 如果两者的MD5CRC64校验值一致,表明这两个文件内容相同。这种情况下,这两个文件的大小是一致的。

    • 如果两者的MD5CRC64校验值不一致,表明这两个文件的内容并不相同。需要继续下一步,检查是否存在特殊请求头。

  3. 检查特殊请求头。

    screenshot_2025-02-18_17-04-03

    1. 检查镜像回源请求中是否包含特殊的HTTP请求头部,例如Accept-Encoding: gzip, deflate, br,该头部表示客户端能够接受压缩格式的数据。

    2. 如果镜像回源请求使用了HTTP压缩逻辑,并且请求的文件满足压缩条件,也会导致这两个文件大小不一致。

    3. 如果存在Accept-Encoding头部,需要禁止传递该头部。

      • 如果设置了允许传递所有HTTP header,需要在禁止传递指定HTTP header中指定accept-encoding。

        p917892

      • 如果设置了传递指定HTTP header,确保指定的header不包含accept-encoding。

        screenshot_2025-02-19_14-30-45

没有生成镜像回源文件?

  • HEAD请求

    客户端发起HEAD请求来获取文件元数据,但是不下载实际文件内容。HEAD请求仅用于获取文件的基本信息(如大小、类型等),并不会触发镜像回源规则到源站请求写入OSS 目标Bucket。

镜像回源返回非预期状态码

当请求触发镜像回源时,如果源站返回的状态码不是404、 200或者206,需要具体分析源站的响应情况。

  • 源站为OSS

    如果源站为OSS,需要检查以下配置项。

    • 禁止传递指定HTTP header参数

      screenshot_2025-02-19_14-31-42

      禁止传递host头:host头用于避免暴露源站信息的同时确保回源请求能按照预期正确处理。如果不配置禁止传递host,则回源请求会透传目标Buckethost值到源站。由于每个Buckethost值是唯一的,如果请求的host与源站的实际host不匹配,源站会返回403错误(403 from mirror host),然后OSS会向客户端返回424错误,表示由于源站未能成功处理请求导致操作失败。

    • 回源OSS私有Bucket

      • 未配置:确认目标Bucket及其ObjectACL权限是否设置为公共读。如果都不是公共读,说明对目标Bucket下的Object没有访问权限,此时源站会返回403错误。

      • 已配置:确认使用的镜像回源的角色授权策略是否变更,导致权限不足。默认使用的角色为AliyunOSSMirrorDefaultRole,该角色的默认系统策略是AliyunOSSReadOnlyAccess

  • 源站不是OSS

    结合服务侧的日志,检查携带SNI(服务器名称指示)、回源参数、header传递等配置,以分析具体的源站异常原因。源站可能会返回401(未授权)、403(禁止访问)、5xx(服务器内部错误)等状态码。

  • 本页导读 (1)
  • 镜像回源文件大小与源站文件大小不一致?
  • 没有生成镜像回源文件?
  • 镜像回源返回非预期状态码
AI助理

点击开启售前

在线咨询服务

你好,我是AI助理

可以解答问题、推荐解决方案等