2014-02-26 2 views
2

내가 http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateURL_PHP.html성능 저하 발생 CloudFront를 체결 URL을

PHP 를 사용하여 CloudFront를에 서명 URL을 만들려면이 샘플을 다음과 나는 모든 것이 잘 작동하고 모두 RTMP 배포 및 HTTP 배포판에 대한 서명 URL을 생성 할 때.

그러나 Sign URL을 생성하는 데는 상당한 시간이 걸리고 수천 개의 요청이있는 프로덕션 환경에서 어떤 영향이 미칠 수 있는지 궁금합니다.

나는 몇 가지 테스트를 수행했으며, 오랜 시간이 걸리는 것으로 보이는 이유는 php-openssl 기능 때문입니다.

<?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ÃÔ[email protected]ç÷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()을 호출하여 서명 된 URL을 생성했습니다. 500 회 서명 된 URL을 만드는 데 걸리는 시간을 확인하려면 while 루프를 수행하기로 결정했습니다.

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; 
    } 

500 개의 서명 된 URL을 생성하는 동안 루프가 내 로컬 컴퓨터에서 약 11 초 걸렸습니다. 그럼 난 등을 변경하기로 결정 :

$signature = $this->rsa_sha1_sign($canned_policy); 

$signature = $this->simulated_rsa_sha1_sign($canned_policy); 

에 openssl_sign) 모든 것이 PHP-하려면 openssl 기능 openssl_get_privatekey을 (호출을 제외하고 실행 된 경우 무슨 일이 있었는지 확인하려면(), openssl_free_key().

동일한 스크립트를 500 while 루프와 함께 실행했으며 0.090 초가 걸렸습니다. 그래서 기본적으로 php-openssl 함수는 스크립트를 훨씬 느리게 만듭니다. 내가 서명해야하는 URL이기 때문에 정상적인 것입니다. 상당한 처리 능력이 필요합니까?

몇 번 시도했는데 여기에 각각 3 번 시도한 샘플 시간이 있습니다.

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 

또한 배포판의 모든 파일에서 작동하는 서명을 어떻게 만들 수 있는지 알고 싶습니다. 내가 그 폴더 또는 배포 아래에있는 모든 파일에 사용할 수있는 서명을 생성 할 수있는 와일드 카드. 가능한 곳을 읽었지만 위의 샘플을 어떻게 사용하는지 잘 모르겠습니다. 어쩌면 요청에 반환 된 각 파일 대신 각 요청에 대해 단일 서명을 만들 수 있다면 덜 집중적 일 것입니다.

감사합니다.

답변

0

"fopen()"을 제거하고 개인 키에 하드 코딩 된 값을 사용해 보셨습니까?

예 :

function getPrivateKey() { 
    $privateKey = '-----BEGIN RSA PRIVATE KEY----- 
    abc 
    -----END RSA PRIVATE KEY-----'; 

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

당신은 여전히 ​​PHP가 포함 사용해보십시오()와 APC 캐싱을 활용 외부 파일에 키가 필요한 경우

.

개인 키 배치 처리 용. Iterator 또는 scan_dir을 사용하고, 정규 표현식을 기반으로 파일을 검색하고, 파일을 포함하고, 해당 내용을 SSL 키 배열에 지정할 수 있습니다. 다시 말하지만 APC를 활용하게됩니다. 불행히도 scandir()은 파일 시스템에 액세스해야한다고 생각합니다.일반적으로 이것은 느려지 게됩니다.

0

rsa 모듈을 사용하여 서명을 계산하는 Boto (AWS의 Python SDK)와 동일한 성능 문제가 있음을 확인했습니다. 나는이 문제가 단순히 RSA 계산이이 맥락에서 느리다는 사실에 달려 있다고 생각한다. 개인적 콘텐츠를 다루는 설정이나 워크 플로를 조정할 때 해결책이 있다고 생각합니다.