首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成CloudFront签名URL时性能较低

生成CloudFront签名URL时性能较低
EN

Stack Overflow用户
提问于 2014-02-27 05:13:09
回答 2查看 1.6K关注 0票数 2

我遵循这个示例,使用PHP在CloudFront上创建带签名的http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateURL_PHP.html

我让一切正常工作,并为RTMP分发和HTTP分发生成签名的URL。

然而,我注意到生成签名URL需要相当长的时间,我想知道在生产中使用数千个请求时会有什么影响。

我做了一些测试,似乎花了很长时间是因为php-openssl函数。

代码如下:

代码语言:javascript
复制
<?php

class Cloudfront {

    const KEYPAIRID = 'MYKEYPAIRID';
    const PVTKEYFILE = '/home/keys/myprivatekey.pem';

    public function rsa_sha1_sign($policy) {
        $signature = "";

        // load the private key
        $fp = fopen(self::PVTKEYFILE, "r");
        $priv_key = fread($fp, 8192);
        fclose($fp);
        $pkeyid = openssl_get_privatekey($priv_key);

        // compute signature
        openssl_sign($policy, $signature, $pkeyid);

        // free the key from memory
        openssl_free_key($pkeyid);

        return $signature;
    }

    public function simulated_rsa_sha1_sign($policy) {
        // create a simulated signature
        $signature = "©3•{š(|i~'{µÜr…6—\L¶…ÙiÃÔh@ç÷S„Aóö¯‡d‰‹{¦ºx­òrd)Xcª
            Áh‚°Bgþ èòëÿô Š#CßFe  ÓÒ>v1    R€¥#–þ*¸çGÀýƒ Ј¾F<t)eV7¿ø_ŒQÎiXXU s˜¦Ij:ý
            ÒR ‹ÚQ§ Çm8à  ºâ*+äÇjƒãýO  4 ~ Uöeóy˜¢93_0iy §âE– a÷f¥y¿ÈãÏ`‹ _ì`ß ½õ  ‹*
            ÁM‘çõD  jrüB •d˜¥  èp Òü¿Ö NŒ«éoI X  €v=RÌlФ /Á û9Yš¾î";

        // load the private key file although is not actually used
        $fp = fopen(self::PVTKEYFILE, "r");
        $priv_key = fread($fp, 8192);
        fclose($fp);

        return $signature;
    }

    public function url_safe_base64_encode($value) {
        $encoded = base64_encode($value);
        // replace unsafe characters +, = and / with the safe characters -, _ and ~
        return str_replace(
                array('+', '=', '/'), array('-', '_', '~'), $encoded);
    }

    public function create_stream_name($stream, $signature, $expires) {
        $result = $stream;
        // if the stream already contains query parameters, attach the new query parameters to the end
        // otherwise, add the query parameters
        $separator = strpos($stream, '?') == FALSE ? '?' : '&';
        $result .= $separator . "Expires=" . $expires . "&Key-Pair-Id=" . self::KEYPAIRID . "&Signature=" . $signature;
        // new lines would break us, so remove them
        return str_replace('\n', '', $result);
    }

    public function get_signed_stream_name($video_path, $expires) {
        // this policy is well known by CloudFront, but you still need to sign it, since it contains your parameters
        $canned_policy = '{"Statement":[{"Resource":"' . $video_path . '","Condition":{"DateLessThan":{"AWS:EpochTime":' . $expires . '}}}]}';
        // sign the original policy, not the encoded version
        $signature = $this->rsa_sha1_sign($canned_policy);
        // make the signature safe to be included in a url
        $encoded_signature = $this->url_safe_base64_encode($signature);

        // combine the above into a stream name
        $stream_name = $this->create_stream_name($video_path, $encoded_signature, $expires);

        return $stream_name;
    }

}

这基本上与CloudFront在他们的文档上提供的示例相同。然后,我创建了一个控制器,通过调用get_signed_stream_name()来生成签名的urls。我决定做一个while循环,看看创建500个带签名的urls需要多长时间。

代码语言:javascript
复制
public function signedurl() {
        // Script start
        $start = microtime(true);

        $this->load->helper('cloudfront');
        $this->cloudfront = new Cloudfront();

        $i = 1;
        while ($i <= 500) {
            $expires = time() + rand(300, 900);
            $http_video_path = 'http://mydistribution.cloudfront.net/myvideo.mp4';
            $signed_http_url = $this->cloudfront->get_signed_stream_name($http_video_path, $expires);

            echo '<strong>HTTP Signed URL:</strong> <br />' . $signed_http_url;
            echo '<br /><br />';

            $i++;
        }

        // Script end
        $time_taken = microtime(true) - $start;
        echo $time_taken;
    }

在我的本地机器上,在while循环中生成500个带签名的urls大约需要11秒。然后我决定改变一下:

代码语言:javascript
复制
$signature = $this->rsa_sha1_sign($canned_policy);

代码语言:javascript
复制
$signature = $this->simulated_rsa_sha1_sign($canned_policy);

要查看除了调用php-openssl函数openssl_get_privatekey()、openssl_sign()、openssl_free_key()以外的所有函数都运行时会发生什么。

我用500while循环运行了同样的脚本,它花了0.090秒。因此,基本上,php-openssl函数会使脚本变得更慢。这是我应该担心的事情吗,这是正常的,因为我正在生成这些签名的urls,并且它需要相当大的处理能力?

我做了几次尝试,下面是每个尝试花费3次的示例时间。

代码语言:javascript
复制
Real code using OpenSSL functions generating 500 signed url calls:
11.135037899
11.6025328636
11.0253090858

500 URLs simulated without using the OpenSSL functions:
0.0828909873962
0.0903220176697
0.0916609764099

另外,我想知道如何创建适用于发行版中任何文件的签名。可以生成可用于该文件夹或分发下的所有文件的签名的通配符。我在一些地方读到这是可能的,但不确定如何使用上面的示例。也许,如果我可以为每个请求创建一个单独的签名,而不是为请求中返回的每个文件创建一个签名,就不会那么密集了。

谢谢!

EN

回答 2

Stack Overflow用户

发布于 2014-06-05 07:07:27

您是否尝试过删除"fopen()“并使用硬编码值作为私钥?

示例:

代码语言:javascript
复制
function getPrivateKey() {
    $privateKey = '-----BEGIN RSA PRIVATE KEY-----
    abc
    -----END RSA PRIVATE KEY-----';

    return str_replace("\t", '', $privateKey);
}

如果您仍然需要外部文件中的密钥,请尝试使用php include()并利用APC缓存。

为了处理成批的私钥,可以使用迭代器或scan_dir,根据正则表达式扫描文件,包含文件并将其内容分配到SSL数组中。同样,您将利用APC。不幸的是,我认为scandir()需要访问您的文件系统。通常情况下,这会减慢速度。

票数 0
EN

Stack Overflow用户

发布于 2015-07-13 14:00:01

我观察到Boto (AWS的Python SDK)也存在同样的性能问题,它使用rsa模块来计算签名。我认为问题很简单地归结为RSA计算在这种情况下很慢。我认为/希望解决方案在于调整处理私人内容的设置或工作流程。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22053392

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档