镜像回源

在存量数据迁移完成后,您可以配置镜像回源,以确保用户可以访问到尚未迁移至OSS的增量数据,以避免对业务的影响。配置镜像回源后,当请求者访问Bucket中不存在的文件(Object)时,OSS会根据回源规则指定的源站获取该文件。OSS获取到目标文件后,会将文件返回给请求者并保存到Bucket中。

使用限制

  • 支持地域

    华东1(杭州)、华东2(上海)、华北1(青岛)、华北2(北京)、华北 3(张家口)、华北5(呼和浩特)、华北6(乌兰察布)、华南1(深圳)、华南2(河源)、华南3(广州)、西南1(成都)、中国香港、美国(硅谷)、美国(弗吉尼亚)、日本(东京)、新加坡、澳大利亚(悉尼)关停中、马来西亚(吉隆坡)、印度尼西亚(雅加达)、菲律宾(马尼拉)、德国(法兰克福)、英国(伦敦)、阿联酋(迪拜)地域支持配置镜像回源。

  • 规则数量

    回源规则最多配置20条,按RuleNumber的先后顺序依次匹配。如果命中当前规则,则后续规则不再匹配。规则未命中表示没有匹配回源条件,与回源后是否成功获取目标文件无关。

  • QPS和流量限制

    单个阿里云账号在中国内地各地域默认QPS为2000、流量为2 Gbit/s;非中国内地各地域默认QPS为1000、流量为1 Gbit/s。

    如果您的业务有更大的QPS或者流量需求,请联系技术支持

  • 回源地址

    回源地址不支持内网地址。

  • 默认超时时间

    镜像回源默认超时时间为10秒。

使用场景

镜像回源主要用于数据无缝迁移到OSS的场景。例如某服务已经在自己建立的源站或者在其他云产品上运行。现因业务发展,需要将数据迁移到OSS上,但是又不能停止服务,此时可以在迁移数据的同时,使用镜像回源功能保证业务的正常进行。关于使用案例的更多信息,请参见互联网公司业务无缝迁移至阿里云OSS

说明

OSS镜像回源不产生额外的费用,但是这个请求本身需照常收费。计费规则与非镜像回源请求一样收费。更多信息,请参见请求费用

回源流程

镜像回源具体流程如下图所示。

image

回源规则

  • 回源规则触发条件

    只有当GetObject本应该返回404的情况下,OSS才会执行镜像回源,向源站请求文件。

  • 回源文件命名规则

    OSS向源站请求的URL为http(s)://MirrorURL/ObjectName,回源到OSS的文件名为ObjectName。例如某Bucket设置的回源地址为https://aliyun.com,某用户请求的文件example.jpg不在该Bucket中。则OSS会通过https://aliyun.com/example.jpg获取文件,存储到OSS的文件名为example.jpg

  • 回源请求失败返回规则

    如果镜像源也不存在此文件,即镜像源返回给OSS的HTTP状态码为404,那么OSS也会返回404给用户。如果是其他非200的状态码(包括因为网络原因等获取不到文件的错误情况),OSS将返回424 MirrorFailed给用户。

  • 回源文件更新规则

    若某个文件已经通过镜像回源到OSS,源站的源文件发生了变化,OSS不会更新该文件。

  • 回源文件元数据

    OSS会将源站返回的以下HTTP头存储为OSS文件的元数据:

    Content-Type
    Content-Encoding
    Content-Disposition
    Cache-Control
    Expires
    Content-Language
    Access-Control-Allow-Origin
  • HTTP请求规则

    • 传给OSS的Header信息以及QueryString信息默认不会传递给源站,是否会传递给源站取决于回源规则中的配置。

    • 如果源站是chunked编码返回,则OSS返回给用户的也是chunked编码。

操作步骤

使用OSS控制台

通过控制台配置多条回源规则时,默认按规则创建时间的先后顺序依次匹配。如果您希望自定义规则匹配顺序,请通过规则右侧的上移下移操作来实现。

3

当请求者访问目标Bucket中不存在的文件时,可以通过指定回源条件和回源地址,从源站中获取目标文件。例如您在华东1(杭州)有名为examplebucket的Bucket,您希望请求者访问Bucket根目录下examplefolder目录中不存在的文件时,可以从https://www.example.com/站点的examplefolder目录获取目标文件。配置步骤如下:

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择数据管理 > 镜像回源

  4. 镜像回源页面,单击创建规则

  5. 创建规则面板,按以下说明配置必要参数,其他参数保留默认配置。

    参数

    配置

    回源类型

    选中镜像

    回源条件

    选中文件名前缀,并设置为examplefolder/

    说明

    配置单条回源规则时文件名前缀和后缀可选填;配置多条回源规则时,必须设置不同的文件名前缀或后缀区分不同的回源规则。

    回源地址

    第一列设置为https,第二列设置为www.example.com,第三列设置为空。

  6. 单击确定

    规则配置完成后的访问流程如下:

    1. 请求者首次访问https://examplebucket.oss-cn-hangzhou.aliyuncs.com/examplefolder/example.txt

    2. 如果examplebucket中不存在examplefolder/example.txt文件,则OSS向https://www.example.com/examplefolder/example.txt发起请求。

    3. 如果获取到目标文件,OSS将example.txt存入examplebucket的examplefolder目录,并将文件返回给请求者;如果未获取到文件,则返回404错误给请求者。

以上配置步骤仅满足镜像回源的基础应用场景,如果您需要配置其他镜像回源规则以满足特定的应用场景时,请参见镜像回源配置示例

使用阿里云SDK

以下仅列举常见SDK的配置镜像回源规则的代码示例。关于其他SDK的配置镜像回源规则代码示例,请参见SDK简介

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.RoutingRule;
import com.aliyun.oss.model.SetBucketWebsiteRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            SetBucketWebsiteRequest request = new SetBucketWebsiteRequest(bucketName);
            // 设置默认主页后,访问以非正斜线(/)结尾的Object,且该Object不存在时的行为。
            //request.setSubDirType(null);
            // 指定访问子目录时,是否支持转到子目录下的默认主页。
            //request.setSupportSubDir(false);

            List<RoutingRule> routingRules = new ArrayList<RoutingRule>();

            RoutingRule rule = new RoutingRule();
            rule.setNumber(1);
            // 只有匹配此前缀的Object才能匹配此规则。
            rule.getCondition().setKeyPrefixEquals("examplebucket");
            // 访问指定Object时,返回status 404才能匹配此规则。
            rule.getCondition().setHttpErrorCodeReturnedEquals(404);
            // 指定跳转的类型。
            rule.getRedirect().setRedirectType(RoutingRule.RedirectType.Mirror);
            // 指定镜像回源的源站地址。例如https://www.example.com/。
            rule.getRedirect().setMirrorURL("<yourMirrorURL>");
            //rule.getRedirect().setMirrorRole("AliyunOSSMirrorDefaultRole");
            // 指定执行跳转或者镜像回源规则时,是否携带请求参数。
            rule.getRedirect().setPassQueryString(true);
            // 与PassQueryString作用相同,优先级高于PassQueryString。只有设置RedirectType为Mirror时生效。
            rule.getRedirect().setMirrorPassQueryString(true);
            // 指定跳转时返回的状态码。只有设置RedirectType为External或者AliCDN时生效。
            //rule.getRedirect().setHttpRedirectCode(302);
            // 指定跳转时的域名,域名需符合域名规范。
            //rule.getRedirect().setHostName("oss.aliyuncs.com");
            // 指定跳转时的协议。只有设置RedirectType为External或者AliCDN时才生效。
            //rule.getRedirect().setProtocol(RoutingRule.Protocol.Https);
            // Redirect时Object名称将替换成ReplaceKeyWith指定的值,ReplaceKeyWith支持设置变量。
            //rule.getRedirect().setReplaceKeyWith("${key}.jpg");
            // 如果设置此字段为true,则Object的前缀将被替换为ReplaceKeyPrefixWith指定的值。
            rule.getRedirect().setEnableReplacePrefix(true);
            // Redirect时Object名称的前缀将替换成该值。
            rule.getRedirect().setReplaceKeyPrefixWith("examplebucket");
            // 是否检查回源body的MD5。只有设置RedirectType为Mirror时生效。
            rule.getRedirect().setMirrorCheckMd5(true);

            RoutingRule.MirrorHeaders mirrorHeaders = new RoutingRule.MirrorHeaders();
            // 是否透传除以下Header之外的其他Header到源站。只有设置RedirectType为Mirror时生效。
            mirrorHeaders.setPassAll(false);
            List passes = new ArrayList<String>();
            passes.add("cache-control");
            // 透传指定的Header到源站。只有设置RedirectType为Mirror时生效。
            mirrorHeaders.setPass(passes);
            List removes = new ArrayList<String>();
            removes.add("content-type");
            // 禁止透传指定的Header到源站。只有设置RedirectType为Mirror时生效。
            mirrorHeaders.setRemove(removes);
            List sets = new ArrayList<Map<String, String>>();
            Map header1 = new HashMap<String, String>();
            header1.put("Key", "key1");
            header1.put("Value", "value1");
            Map header2 = new HashMap<String, String>();
            header2.put("Key", "key2");
            header2.put("Value", "value2");
            sets.add(header1);
            sets.add(header2);
            // 设置传到源站的Header。不管请求中是否携带这些指定的Header,回源时都会设置这些Header。
            mirrorHeaders.setSet(sets);
            // 指定回源时携带的Header。只有设置RedirectType为Mirror时才生效。
            rule.getRedirect().setMirrorHeaders(mirrorHeaders);

            routingRules.add(rule);
            request.setRoutingRules(routingRules);
            ossClient.setBucketWebsite(request);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
#-*-coding:utf-8-*-
import oss2
from oss2.models import BucketWebsite, MirrorHeadersSet, RedirectMirrorHeaders, Redirect, RoutingRule, \
    REDIRECT_TYPE_MIRROR, Condition
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# Endpoint以华东1(杭州)为例,其他Region请按实际情况填写。
# 填写Bucket名称,例如examplebucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')

# 开启静态网站托管模式,并将默认首页设置为index.html,默认404页设置为error.html。
index_file = 'index.html'
error_file = 'error.html'
# 设置匹配的条件。
condition1 = Condition(key_prefix_equals='examplefolder',
                       http_err_code_return_equals=404)

# 指定镜像回源时携带的Header。
mirror_headers_set_1 = MirrorHeadersSet("myheader-key5","myheader-value5")
mirror_headers_set_2 = MirrorHeadersSet("myheader-key6","myheader-value6")
set_list = [mirror_headers_set_1, mirror_headers_set_2]
pass_list = ['myheader-key1', 'myheader-key2']
remove_list = ['myheader-key3', 'myheader-key4']
mirror_header = RedirectMirrorHeaders(pass_all=True, pass_list=pass_list, remove_list=remove_list, set_list=set_list)
# 指定匹配此规则后执行的动作。
redirect1 = Redirect(redirect_type=REDIRECT_TYPE_MIRROR, mirror_url='https://www.example.com/',
                     mirror_pass_query_string=True, mirror_follow_redirect=True, mirror_check_md5=True, mirror_headers=mirror_header)

rule1 = RoutingRule(rule_num=1, condition=condition1, redirect=redirect1)
website_set = BucketWebsite(index_file, error_file, [rule1])

# 设置镜像回源。
bucket.put_bucket_website(website_set)
package main

import (
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"os"
)

func main() {
	// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	// 创建OSSClient实例。
	// yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
	client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	// 填写Bucket名称,例如examplebucket。
	bucketName := "examplebucket"

	var indexWebsite = "myindex.html"
	var errorWebsite = "myerror.html"

	btrue := true
	bfalse := false
	// 指定回源类型为镜像。
	ruleOk := oss.RoutingRule{
		RuleNumber: 1,
		Condition: oss.Condition{
			KeyPrefixEquals: "",
			// 指定回源条件为HTTP状态码404。
			HTTPErrorCodeReturnedEquals: 404,
		},
		Redirect: oss.Redirect{
			RedirectType: "Mirror",
			// PassQueryString: &btrue,
			// 指定回源地址。
			MirrorURL: "http://www.test.com/",
			// MirrorPassQueryString:&btrue,
			// MirrorFollowRedirect:&bfalse,
			// MirrorCheckMd5:&bfalse,
			MirrorHeaders: oss.MirrorHeaders{
				// PassAll:&bfalse,
				// 允许传递指定HTTP Header参数。
				Pass: []string{"myheader-key1", "myheader-key2"},
				// 禁止传递指定HTTP Header参数。
				Remove: []string{"myheader-key3", "myheader-key4"},
				Set: []oss.MirrorHeaderSet{
					{
						Key:   "myheader-key5",
						Value: "myheader-value5",
					},
				},
			},
		},
	}

	// 指定回源类型为重定向。
	ruleArrOk := []oss.RoutingRule{
		{
			RuleNumber: 2,
			Condition: oss.Condition{
				// 指定回源条件为HTTP状态码404,文件名前缀为abc/。
				KeyPrefixEquals:             "abc/",
				HTTPErrorCodeReturnedEquals: 404,
				IncludeHeader: []oss.IncludeHeader{
					{
						Key:    "host",
						Equals: "test.oss-cn-beijing-internal.aliyuncs.com",
					},
				},
			},
			Redirect: oss.Redirect{
				RedirectType:     "AliCDN",
				Protocol:         "http",
				HostName:         "www.test.com",
				PassQueryString:  &bfalse,
				ReplaceKeyWith:   "prefix/${key}.suffix",
				HttpRedirectCode: 301,
			},
		},
		// 指定回源类型为镜像。
		{
			RuleNumber: 3,
			Condition: oss.Condition{
				KeyPrefixEquals:             "",
				HTTPErrorCodeReturnedEquals: 404,
			},
			Redirect: oss.Redirect{
				RedirectType:          "Mirror",
				PassQueryString:       &btrue,
				MirrorURL:             "http://www.test.com/",
				MirrorPassQueryString: &btrue,
				MirrorFollowRedirect:  &bfalse,
				MirrorCheckMd5:        &bfalse,
				MirrorHeaders: oss.MirrorHeaders{
					PassAll: &btrue,
					Pass:    []string{"myheader-key1", "myheader-key2"},
					Remove:  []string{"myheader-key3", "myheader-key4"},
					Set: []oss.MirrorHeaderSet{
						{
							Key:   "myheader-key5",
							Value: "myheader-value5",
						},
					},
				},
			},
		},
	}

	wxmlOne := oss.WebsiteXML{
		IndexDocument: oss.IndexDocument{
			Suffix: indexWebsite,
		},
		ErrorDocument: oss.ErrorDocument{
			Key: errorWebsite,
		},
	}
	wxmlOne.RoutingRules = append(wxmlOne.RoutingRules, ruleOk)
	wxmlOne.RoutingRules = append(wxmlOne.RoutingRules, ruleArrOk...)
	err = client.SetBucketWebsiteDetail(bucketName, wxmlOne)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
}

     

使用命令行工具ossutil

关于使用ossutil配置镜像回源规则的具体操作,请参见添加或修改Website配置

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见PutBucketWebsite

相关文档

您可以通过日志查询通过回源上传的文件。具体操作,请参见实时日志查询