前言
??????前段时间,公司的一个前端项目中需要展示3D模型和材质,其中模型是固定的,但材质所用到的贴图是渲染段动态生成的。实测前端加载模型+材质,总耗时将近20s,产品当然不满意。然后需要程序这边给出优化方案,首先想到的是方案一:减少资源大小,提高加载效率。另外一方面,由于图片由渲染端上传到OSS上,并通过了CDN加速,那有没有可能因为前端第一次下载时,资源没有被加速的问题呢?所以提出了方案二:图片上传后,主动调用CDN资源预热API,然后再通知前端加载被加速过的资源。 ??????通过两个方案的实施,发现方案一已经解决了问题,前端基本上可以秒加载,但为了以后考虑,还是决定将方案二的实施过程在此记录一下。
正文
一、阿里云新版API
??????在官网新版的API页面找到对应功能的位置
二、运行示例
??????在对象存储里找到你想预热的文件,勾选后,导出URL。
??????在中间一栏的 [ ObjectPath ] 处填写需要预热的文件URL,如果有多个,使用 [ \r ] 或 [ \r\n ] 间隔。切换到C#,点击运行示例,等待片刻。 ??????当底部控制台出现以下提示时,敲下回车即可继续
Type 'dotnet run' to make an api request with Aliyun C# SDK
shell@Alicloud:~/alibabacloud_sdk_demo/cdn/GfTCX95Fu/csharp/core$ dotnet run
??????若出现如下提示,即说明调试成功
ASP.NET Core
------------
Successfully installed the ASP.NET Core HTTPS Development Certificate.
To trust the certificate run 'dotnet dev-certs https --trust' (Windows and macOS only). For establishing trust on other platforms refer to the platform specific documentation.
For more information on configuring HTTPS see https:
Unhandled Exception: Tea.TeaException: code: 404, The domain [hologarment-update.oss-cn-shanghai.aliyuncs.com] does not belong to you. request id: 28D96D69-4C39-5412-9CBB-37A5214928AB
at AlibabaCloud.OpenApiClient.Client.DoRPCRequest(String action, String version, String protocol, String method, String authType, String bodyType, OpenApiRequest request, RuntimeOptions runtime)
at AlibabaCloud.SDK.Cdn20180510.Client.PushObjectCacheWithOptions(PushObjectCacheRequest request, RuntimeOptions runtime)
at AlibabaCloud.SDK.Sample.Sample.Main(String[] args) in /home/shell/alibabacloud_sdk_demo/cdn/GfTCX95Fu/csharp/core/Sample.cs:line 46
三、下载示例工程
??????细心的你可能已经发现,刚才调试时并没有填写AccessKeyId、AccessKeySecret(即AK),而且示例工程的代码也发生了变化(刚才填写的ObjectPath已经在代码中赋值),这都要归功于Aliyun,已经帮我们自动获取了当前登录账户的AK。
四、调试工程
??????1. 打开压缩包,使用记事本打开 Sample.csproj ,将 netcoreapp2.1 修改为 net45 ,保存后,使用 vs201x 打开, ??????2. 这里要填写自己的账户AK
AlibabaCloud.SDK.Cdn20180510.Client client = CreateClient("accessKeyId", "accessKeySecret");
??????3. 修改ObjectPath中URL的域名,为CDN加速域名 例如:https://hologarment-update.oss-cn-shanghai.aliyuncs.com/1111111111111.jpg 改为:https://update.hologarment.tech/1111111111111.jpg
ps. 请提前在CDN-域名管理配置好需要加速的域名。然后在域名列表里将刚才配置好的加速域名绑定到二级域名,像这样
??????4. 启动调试,如果控制台出现如下提示,说明初步调试成功。
五、根据API,完成测试代码的编写
参考API: 【 获取缓存刷新预热信息 DescribeRefreshQuota 】主要用于获取当前缓存刷新预热的余量 【 预热源站内容到缓存节点 PushObjectCache 】将URL预热到缓存节点 【 通过任务编号查询刷新预热任务信息 DescribeRefreshTaskById 】根据任务id查询预热状态
为了调试方便,我将URL放入到了一个txt文档中,这样就可以一键预热多个URL了。
完整代码如下:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AlibabaCloud.SDK.Cdn20180510.Models;
using Tea;
using Newtonsoft.Json;
using TaskInfo = AlibabaCloud.SDK.Cdn20180510.Models.DescribeRefreshTaskByIdResponseBody.DescribeRefreshTaskByIdResponseBodyTasks;
using System.IO;
using System.Text;
namespace AlibabaCloud.SDK.Sample
{
public class Sample
{
public class Config
{
public const string AccessKeyId = "AccessKeyId";
public const string AccessKeySecret = "AccessKeySecret";
}
public static void Main(string[] args)
{
Cdn20180510.Client client = CreateClient(Config.AccessKeyId, Config.AccessKeySecret);
string objectPath = GetObjectPathFromAsset();
int objectPathCount = GetSubStrCountInStr(objectPath, "http", 0);
int refreshRemain = GetRefreshRemain(client);
if (refreshRemain < objectPathCount)
{
return;
}
PushObjectCacheRequest request = new PushObjectCacheRequest
{
ObjectPath = objectPath,
};
string pushTaskId = PushObjectCache(client, request);
System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
long start = (long)(DateTime.Now - startTime).TotalMilliseconds;
if (!pushTaskId.Equals("-1"))
{
TeaConsole.Client.Log("--------------------检查预热请求状态--------------------");
CheckCacheStatusById(client, pushTaskId, objectPathCount);
}
long end = (long)(DateTime.Now - startTime).TotalMilliseconds;
TeaConsole.Client.Log($"预热 {objectPathCount} 个URL,共用时:{end - start}");
}
public static Cdn20180510.Client CreateClient(string accessKeyId, string accessKeySecret)
{
OpenApiClient.Models.Config config = new OpenApiClient.Models.Config
{
AccessKeyId = accessKeyId,
AccessKeySecret = accessKeySecret,
};
config.Endpoint = "cdn.aliyuncs.com";
return new Cdn20180510.Client(config);
}
public static string PushObjectCache(Cdn20180510.Client client, PushObjectCacheRequest request)
{
try
{
PushObjectCacheResponse resp = client.PushObjectCache(request);
TeaConsole.Client.Log("--------------------预热源站内容成功--------------------");
TeaConsole.Client.Log(TeaUtil.Common.ToJSONString(resp.Body.ToMap()));
return resp.Body.PushTaskId;
}
catch (TeaException error)
{
TeaConsole.Client.Log(error.Message);
}
catch (Exception _error)
{
TeaException error = new TeaException(new Dictionary<string, object>
{
{ "message", _error.Message }
});
TeaConsole.Client.Log(error.Message);
}
return "-1";
}
public static async Task PushObjectCacheAsync(Cdn20180510.Client client, PushObjectCacheRequest request)
{
try
{
PushObjectCacheResponse resp = await client.PushObjectCacheAsync(request);
TeaConsole.Client.Log("--------------------预热源站内容成功--------------------");
TeaConsole.Client.Log(TeaUtil.Common.ToJSONString(resp.Body.ToMap()));
}
catch (TeaException error)
{
TeaConsole.Client.Log(error.Message);
}
catch (Exception _error)
{
TeaException error = new TeaException(new Dictionary<string, object>
{
{ "message", _error.Message }
});
TeaConsole.Client.Log(error.Message);
}
}
public static void CheckCacheStatusById(Cdn20180510.Client client, string pushTaskId, int pushObjCount)
{
DescribeRefreshTaskByIdRequest request = new DescribeRefreshTaskByIdRequest()
{
TaskId = pushTaskId
};
while (true)
{
try
{
DescribeRefreshTaskByIdResponse response = client.DescribeRefreshTaskById(request);
DescribeRefreshTaskByIdResponseBody responseBody = response.Body;
Dictionary<string, object> keyValuePairs = responseBody.ToMap();
TeaConsole.Client.Log(TeaUtil.Common.ToJSONString(keyValuePairs));
if (Convert.ToInt32(keyValuePairs["TotalCount"]) == pushObjCount)
{
if (isAllCompleted(keyValuePairs["Tasks"]))
{
TeaConsole.Client.Log("---------------------预热请求已完成---------------------");
TeaConsole.Client.Log("--------------------------------------------------------");
break;
}
}
}
catch (TeaException error)
{
TeaConsole.Client.Log(error.Message);
}
catch (Exception _error)
{
TeaException error = new TeaException(new Dictionary<string, object>
{
{ "message", _error.Message }
});
TeaConsole.Client.Log(error.Message);
}
Thread.Sleep(100);
}
}
public static bool isAllCompleted(object tasks)
{
List<object> taskInfos = (List<object>)tasks;
for (int i = 0; i < taskInfos.Count; i++)
{
string json = TeaUtil.Common.ToJSONString(taskInfos[i]);
TaskInfo taskInfo = JsonConvert.DeserializeObject<TaskInfo>(json);
if (!taskInfo.Status.Equals("Complete"))
{
return false;
}
}
return true;
}
public static int GetRefreshRemain(Cdn20180510.Client client)
{
try
{
DescribeRefreshQuotaRequest request = new DescribeRefreshQuotaRequest();
DescribeRefreshQuotaResponse response = client.DescribeRefreshQuota(request);
TeaConsole.Client.Log("--------------------缓存刷新预热余量--------------------");
Dictionary<string, object> keyValuePairs = response.Body.ToMap();
TeaConsole.Client.Log(TeaUtil.Common.ToJSONString(keyValuePairs));
TeaConsole.Client.Log($"当前剩余预热余量:{keyValuePairs["PreloadRemain"]}");
return Convert.ToInt32(keyValuePairs["PreloadRemain"]);
}
catch (TeaException error)
{
TeaConsole.Client.Log(error.Message);
}
catch (Exception _error)
{
TeaException error = new TeaException(new Dictionary<string, object>
{
{ "message", _error.Message }
});
TeaConsole.Client.Log(error.Message);
}
return 0;
}
static string GetObjectPathFromAsset()
{
string objectPath = "";
using (FileStream fs = new FileStream("ObjectPath.txt", FileMode.Open, FileAccess.Read))
{
StreamReader reader = new StreamReader(fs, Encoding.Default);
objectPath = reader.ReadToEnd();
reader.Close();
fs.Close();
}
return objectPath;
}
public static int GetSubStrCountInStr(string str, string substr, int StartPos)
{
int foundPos = -1;
int count = 0;
do
{
foundPos = str.IndexOf(substr, StartPos);
if (foundPos > -1)
{
StartPos = foundPos + 1;
count++;
}
} while (foundPos > -1 && StartPos < str.Length);
return (count);
}
}
}
最后
看完记得【点赞、评论、收藏】三连哦~
|