All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.qiniu.storage.AutoRegion Maven / Gradle / Ivy

There is a newer version: 7.17.0
Show newest version
package com.qiniu.storage;

import com.qiniu.common.QiniuException;
import com.qiniu.http.Client;
import com.qiniu.http.Response;
import com.qiniu.util.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

class AutoRegion extends Region {

    /**
     * uc接口域名
     */
    private List ucServers = new ArrayList<>();

    /**
     * 空间机房,域名信息缓存,此缓存绑定了 token、bucket,且仅 AutoRegion 对象内部有效。
     */
    private Map regions;

    /**
     * 全局空间信息缓存,此缓存绑定了 token、bucket,全局有效。
     */
    private static final Cache globalRegionCache = new Cache.Builder<>(UCRet.class)
            .setVersion("v1")
            .builder();

    /**
     * 定义HTTP请求管理相关方法
     */
    private Client client;

    /**
     * 上传失败重试次数
     */
    private int retryMax = 1;

    /**
     * 重试时间间隔,单位:毫秒
     **/
    private int retryInterval = 300;

    /**
     * 域名冻结时间,单位:毫秒
     * 

* 当一个请求失败,会根据条件判断是否需要冻结请求的域名,冻结后在指定的冻结时间内不会使用此域名进行重试 **/ private int hostFreezeDuration = 600 * 1000; private AutoRegion() { } AutoRegion(String... ucServers) { this(1, 300, 600 * 1000, ucServers); } AutoRegion(int retryMax, int retryInterval, int hostFreezeDuration, String... ucServers) { if (ucServers != null && ucServers.length > 0) { this.ucServers = Arrays.asList(ucServers); } else { this.ucServers = Arrays.asList(Configuration.defaultUcHosts); } this.retryMax = retryMax; this.retryInterval = retryInterval; this.hostFreezeDuration = hostFreezeDuration; this.client = new Client(); this.regions = new ConcurrentHashMap<>(); } /** * 通过 API 接口查询上传域名 */ private UCRet queryRegionInfoFromServerIfNeeded(RegionIndex index) throws QiniuException { String cacheKey = getCacheId(index); UCRet ret = globalRegionCache.cacheForKey(cacheKey); if (ret != null && ret.isValid()) { return ret; } String[] ucHosts = getUcHostArray(); String address = UrlUtils.setHostScheme(getUcServer(), true) + "/v3/query?ak=" + index.accessKey + "&bucket=" + index.bucket; Api api = new Api(client, new Api.Config.Builder() .setSingleHostRetryMax(retryMax) .setRetryInterval(retryInterval) .setHostFreezeDuration(hostFreezeDuration) .setHostRetryMax(ucHosts.length) .setHostProvider(HostProvider.arrayProvider(ucHosts)) .build()); Response r = api.requestWithInterceptor(new Api.Request(address)); ret = r.jsonToObject(UCRet.class); if (ret != null) { ret.setupDeadline(); globalRegionCache.cache(cacheKey, ret); } return ret; } static Region regionGroup(UCRet ret) { if (ret == null || ret.hosts == null || ret.hosts.length == 0) { return null; } RegionGroup group = new RegionGroup(); for (ServerRets host : ret.hosts) { Region region = host.createRegion(); group.addRegion(region); } return group; } /** * 首先从缓存读取Region信息,如果没有则发送请求从接口查询 * * @param accessKey 账号 accessKey * @param bucket 空间名 * @return 机房域名信息 */ private Region queryRegionInfo(String accessKey, String bucket) throws QiniuException { RegionIndex index = new RegionIndex(accessKey, bucket); String cacheKey = getCacheId(index); Region region = regions.get(cacheKey); Exception ex = null; if (region == null || !region.isValid()) { for (int i = 0; i < 2; i++) { try { UCRet ret = queryRegionInfoFromServerIfNeeded(index); region = AutoRegion.regionGroup(ret); if (region != null) { regions.put(cacheKey, region); break; } } catch (Exception e) { ex = e; } } } // info 不能为 null // if (region == null) { if (ex instanceof QiniuException) { throw (QiniuException) ex; } throw new QiniuException(ex, "auto region get region info from uc failed."); } return region; } /** * 首先从缓存读取Region信息,如果没有则发送请求从接口查询 * * @param regionReqInfo 封装了 accessKey 和 bucket 的对象 * @return 机房域名信息 */ private Region queryRegionInfo(RegionReqInfo regionReqInfo) throws QiniuException { return queryRegionInfo(regionReqInfo.getAccessKey(), regionReqInfo.getBucket()); } @Override boolean switchRegion(RegionReqInfo regionReqInfo) { Region currentRegion = getCurrentRegion(regionReqInfo); if (currentRegion == null) { return false; } else { return currentRegion.switchRegion(regionReqInfo); } } @Override String getRegion(RegionReqInfo regionReqInfo) { Region currentRegion = getCurrentRegion(regionReqInfo); if (currentRegion == null) { return ""; } else { return currentRegion.getRegion(regionReqInfo); } } @Override boolean isValid() { return true; } @Override Region getCurrentRegion(RegionReqInfo regionReqInfo) { try { Region region = queryRegionInfo(regionReqInfo); return region.getCurrentRegion(regionReqInfo); } catch (QiniuException e) { return null; } } /** * 获取源站直传域名 */ @Override List getSrcUpHost(RegionReqInfo regionReqInfo) throws QiniuException { if (regionReqInfo == null) { return null; } Region region = queryRegionInfo(regionReqInfo); return region.getSrcUpHost(regionReqInfo); } /** * 获取加速上传域名 */ @Override List getAccUpHost(RegionReqInfo regionReqInfo) throws QiniuException { if (regionReqInfo == null) { return null; } Region region = queryRegionInfo(regionReqInfo); return region.getAccUpHost(regionReqInfo); } /** * 获取源站下载域名 */ @Override String getIovipHost(RegionReqInfo regionReqInfo) throws QiniuException { if (regionReqInfo == null) { return ""; } Region region = queryRegionInfo(regionReqInfo); return region.getIovipHost(regionReqInfo); } @Override String getIoSrcHost(RegionReqInfo regionReqInfo) throws QiniuException { if (regionReqInfo == null) { return ""; } Region region = queryRegionInfo(regionReqInfo); return region.getIoSrcHost(regionReqInfo); } /** * 获取资源管理域名 */ @Override String getRsHost(RegionReqInfo regionReqInfo) throws QiniuException { if (regionReqInfo == null) { return ""; } Region region = queryRegionInfo(regionReqInfo); return region.getRsHost(regionReqInfo); } /** * 获取资源列表域名 */ @Override String getRsfHost(RegionReqInfo regionReqInfo) throws QiniuException { if (regionReqInfo == null) { return ""; } Region region = queryRegionInfo(regionReqInfo); return region.getRsfHost(regionReqInfo); } /** * 获取资源处理HTTP域名 */ @Override String getApiHost(RegionReqInfo regionReqInfo) throws QiniuException { if (regionReqInfo == null) { return ""; } Region region = queryRegionInfo(regionReqInfo); return region.getApiHost(regionReqInfo); } @Override String getUcHost(RegionReqInfo regionReqInfo) throws QiniuException { String host = getUcServer(); return UrlUtils.removeHostScheme(host); } String getUcServer() throws QiniuException { if (ucServers.size() == 0) { throw QiniuException.unrecoverable("AutoRegion not set uc host"); } return ucServers.get(0); } @Override List getUcHosts(RegionReqInfo regionReqInfo) throws QiniuException { if (ucServers.size() == 0) { throw QiniuException.unrecoverable("AutoRegion not set uc host"); } List newList = new ArrayList<>(); for (String host : ucServers) { String h = UrlUtils.removeHostScheme(host); if (StringUtils.isNullOrEmpty(h)) { continue; } newList.add(h); } return newList; } String[] getUcHostArray() throws QiniuException { return getUcHosts(null).toArray(new String[0]); } private String getCacheId(RegionIndex index) { StringBuilder builder = new StringBuilder() .append(index.accessKey) .append("-") .append(index.bucket); if (ucServers != null && !ucServers.isEmpty()) { for (String host : ucServers) { if (host != null && !host.isEmpty()) { builder.append(host); } } } return UrlSafeBase64.encodeToString(builder.toString()); } public Object clone() { AutoRegion newRegion = new AutoRegion(); newRegion.ucServers = new ArrayList<>(ucServers); newRegion.regions = regions; newRegion.client = client; return newRegion; } private static class RegionIndex { private final String accessKey; private final String bucket; RegionIndex(String accessKey, String bucket) { this.accessKey = accessKey; this.bucket = bucket; } public int hashCode() { return accessKey.hashCode() * 37 + bucket.hashCode(); } public boolean equals(Object obj) { return obj == this || !(obj == null || !(obj instanceof RegionIndex)) && ((RegionIndex) obj).accessKey.equals(accessKey) && ((RegionIndex) obj).bucket.equals(bucket); } } private class UCRet { // 有效期, 单位秒 long deadline; ServerRets[] hosts; private boolean isValid() { return System.currentTimeMillis() < deadline * 1000; } private void setupDeadline() { long ttl = (1L << 31) - 1; if (hosts != null && hosts.length > 0) { for (ServerRets hostRet : hosts) { if (hostRet != null && hostRet.ttl < ttl) { ttl = hostRet.ttl; } } } deadline = System.currentTimeMillis() / 1000 + ttl; } } // CHECKSTYLE:OFF private class ServerRets { long ttl; String region; ServerRet up; ServerRet rs; ServerRet rsf; ServerRet uc; ServerRet api; ServerRet io; @SuppressWarnings({"MemberName"}) ServerRet io_src; Region createRegion() { long timestamp = ttl + System.currentTimeMillis() / 1000; List srcUpHosts = new ArrayList<>(); List accUpHosts = new ArrayList<>(); if (up != null) { srcUpHosts = up.allSrcHosts(); accUpHosts = up.allAccHosts(); } String iovipHost = null; if (io != null) { iovipHost = io.getOneHost(); } String ioSrcHost = null; if (io_src != null) { ioSrcHost = io_src.getOneHost(); } String rsHost = null; if (rs != null) { rsHost = rs.getOneHost(); } String rsfHost = null; if (rsf != null) { rsfHost = rsf.getOneHost(); } String apiHost = null; if (api != null) { apiHost = api.getOneHost(); } String ucHost = null; if (uc != null) { ucHost = uc.getOneHost(); } // 根据 iovipHost 反推 regionId String regionId = region; if (regionId == null) { regionId = ""; } return new Region(timestamp, regionId, srcUpHosts, accUpHosts, iovipHost, ioSrcHost, rsHost, rsfHost, apiHost, ucHost); } } // CHECKSTYLE:ON private class ServerRet { HostInfoRet src; HostInfoRet acc; private String getOneHost() { String host = null; if (src != null) { host = src.getOneHost(); } if (host == null && acc != null) { host = acc.getOneHost(); } return host; } private List allSrcHosts() { if (src != null) { return src.allHosts(); } else { return new ArrayList<>(); } } private List allAccHosts() { if (acc != null) { return acc.allHosts(); } else { return new ArrayList<>(); } } } private class HostInfoRet { List main; List backup; private String getOneHost() { if (main != null && main.size() > 0) { return main.get(0); } else if (backup != null && backup.size() > 0) { return backup.get(0); } else { return null; } } private List allHosts() { List hosts = new ArrayList<>(); if (main != null && main.size() > 0) { hosts.addAll(main); } if (backup != null && backup.size() > 0) { hosts.addAll(backup); } return hosts; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy