생활코딩

Coding Everybody

코스 전체목록

닫기

SQS SDK - PHP

수업개요

이번 수업은 PHP를 이용해서 SQS를 이용하는 방법에 대한 내용이다. 하지만 PHP의 복잡한 기능을 사용하지 않을 것이기 때문에 PHP를 모른다고해도 실제 에플리케이션에서 어떻게 SQS를 활용 할 수 있는지에 대한 아이디어를 얻을 수 있을 것이다. 

선행지식

구성

환경

 EC2 인스턴스는 아래와 같은 환경에서 동작할 것이다. 

  • 운영체제 : Ubuntu (필자는 12.04)
  • 웹서버 : Apache
  • 에플리케이션 : PHP
  • SDK : AWS PHP SDK 2

위의 환경을 구축한 후에 AMI를 만들고 각각의 환경에 따라서 PHP 에플리케이션을 작성할 것이다. 

설치

PHP sdk 2 설치 방법에서 설명하고 있는 EC2 인스턴스 생성, Apache, PHP 설치, SDK 설치를 참고한다.

PHP SDK 2 설치 방법 바로가기

큐생성

 

encoding, email 큐를 생성한다. 이에 대한 방법은 SQS 수업을 참고한다.

SQS의 큐는 한달동안 사용하지 않으면 AWS에 의해서 삭제될 수 있다. 따라서 에플리케이션 레벨에서 SQS의 큐가 자동 삭제되었을 때 이를 생성하는 로직을 구현해야 안전하다. 본 수업에서는 이 방법에 대해서 다루지는 않는다. 

파일 수신자

 

test.php 파일을 생성하고 테스트를 해본다. 아래 내용은 1.avi라는 메시지를 encoding 큐에 추가한다. 자세한 설명은 동영상을 참고한다.

아래는 파일을 전송하는 html 페이지다. 

sender.html

1
2
3
4
5
6
7
8
<html>
<body>
<form enctype="multipart/form-data" action="./receiver.php" method="POST">
<input type="file" name="userfile" />
<input type="submit" />
</form>
</body>
</html>

receiver.php

send.html이 아래는 전송한 파일을 수신 받는 php 에플리케이션이다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
require 'aws-sdk-php-master/vendor/autoload.php';
use Aws\Sqs\SqsClient;
use Aws\S3\S3Client;
$key = 'AKIAJKWXNJYIQPXOP14SQ';
$secret = 'K39qUQYjMW8jBUQlxki1MY/OlC2QejcDsHKZXRf4/';
$bucket = 'codingeverybodysqs';
if(move_uploaded_file($_FILES['userfile']['tmp_name'], '/var/www/original/'.$_FILES['userfile']['name'])){
$s3_client = S3Client::factory(array(
'key' => $key,
'secret' => $secret
));
$result = $s3_client->putObject(array(
'Bucket' => $bucket,
'Key' => $_FILES['userfile']['name'],
'SourceFile' => '/var/www/original/'.$_FILES['userfile']['name']
));
unlink('/var/www/original/'.$_FILES['userfile']['name']);
$sqs_client = SqsClient::factory(array(
'key' => $key,
'secret' => $secret,
'region' => 'ap-northeast-1'
));
$sqs_client->sendMessage(array(
'MessageBody' => $_FILES['userfile']['name'],
));
}
?>

인코더 서버

 

인코더 서버는 encoding 큐에 반복적으로 접속해서 새로운 큐가 생성된 것이 있는지를 확인한다. 새로운 큐가 있다면 이를 받아온다. 

인코더 서버는 GD 라이브러리를 사용한다. 따라서 GD 라이브러리를 설치해야 한다. 아래와 같은 방법으로 설치 할 수 있다.

1
2
sudo apt-get install php5-gd;
sudo service apache2 reload;

resizeImage.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<?php
/**
* Resize image class will allow you to resize an image
*
* Can resize to exact size
* Max width size while keep aspect ratio
* Max height size while keep aspect ratio
* Automatic while keep aspect ratio
*/
class ResizeImage
{
private $ext;
private $image;
private $newImage;
private $origWidth;
private $origHeight;
private $resizeWidth;
private $resizeHeight;
/**
* Class constructor requires to send through the image filename
*
* @param string $filename - Filename of the image you want to resize
*/
public function __construct( $filename )
{
if(file_exists($filename))
{
$this->setImage( $filename );
} else {
throw new Exception('Image ' . $filename . ' can not be found, try another image.');
}
}
/**
* Set the image variable by using image create
*
* @param string $filename - The image filename
*/
private function setImage( $filename )
{
$size = getimagesize($filename);
$this->ext = $size['mime'];
switch($this->ext)
{
// Image is a JPG
case 'image/jpg':
case 'image/jpeg':
// create a jpeg extension
$this->image = imagecreatefromjpeg($filename);
break;
// Image is a GIF
case 'image/gif':
$this->image = @imagecreatefromgif($filename);
break;
// Image is a PNG
case 'image/png':
$this->image = @imagecreatefrompng($filename);
break;
// Mime type not found
default:
throw new Exception("File is not an image, please use another file type.", 1);
}
$this->origWidth = imagesx($this->image);
$this->origHeight = imagesy($this->image);
}
/**
* Save the image as the image type the original image was
*
* @param String[type] $savePath - The path to store the new image
* @param string $imageQuality - The qulaity level of image to create
*
* @return Saves the image
*/
public function saveImage($savePath, $imageQuality="100", $download = false)
{
switch($this->ext)
{
case 'image/jpg':
case 'image/jpeg':
// Check PHP supports this file type
if (imagetypes() & IMG_JPG) {
imagejpeg($this->newImage, $savePath, $imageQuality);
}
break;
case 'image/gif':
// Check PHP supports this file type
if (imagetypes() & IMG_GIF) {
imagegif($this->newImage, $savePath);
}
break;
case 'image/png':
$invertScaleQuality = 9 - round(($imageQuality/100) * 9);
// Check PHP supports this file type
if (imagetypes() & IMG_PNG) {
imagepng($this->newImage, $savePath, $invertScaleQuality);
}
break;
}
if($download)
{
header('Content-Description: File Transfer');
header("Content-type: application/octet-stream");
header("Content-disposition: attachment; filename= ".$savePath."");
readfile($savePath);
}
imagedestroy($this->newImage);
}
/**
* Resize the image to these set dimensions
*
* @param int $width - Max width of the image
* @param int $height - Max height of the image
* @param string $resizeOption - Scale option for the image
*
* @return Save new image
*/
public function resizeTo( $width, $height, $resizeOption = 'default' )
{
switch(strtolower($resizeOption))
{
case 'exact':
$this->resizeWidth = $width;
$this->resizeHeight = $height;
break;
case 'maxwidth':
$this->resizeWidth = $width;
$this->resizeHeight = $this->resizeHeightByWidth($width);
break;
case 'maxheight':
$this->resizeWidth = $this->resizeWidthByHeight($height);
$this->resizeHeight = $height;
break;
default:
if($this->origWidth > $width || $this->origHeight > $height)
{
if ( $this->origWidth > $this->origHeight ) {
$this->resizeHeight = $this->resizeHeightByWidth($width);
$this->resizeWidth = $width;
} else if( $this->origWidth < $this->origHeight ) {
$this->resizeWidth = $this->resizeWidthByHeight($height);
$this->resizeHeight = $height;
}
} else {
$this->resizeWidth = $width;
$this->resizeHeight = $height;
}
break;
}
$this->newImage = imagecreatetruecolor($this->resizeWidth, $this->resizeHeight);
imagecopyresampled($this->newImage, $this->image, 0, 0, 0, 0, $this->resizeWidth, $this->resizeHeight, $this->origWidth, $this->origHeight);
}
/**
* Get the resized height from the width keeping the aspect ratio
*
* @param int $width - Max image width
*
* @return Height keeping aspect ratio
*/
private function resizeHeightByWidth($width)
{
return floor(($this->origHeight/$this->origWidth)*$width);
}
/**
* Get the resized width from the height keeping the aspect ratio
*
* @param int $height - Max image height
*
* @return Width keeping aspect ratio
*/
private function resizeWidthByHeight($height)
{
return floor(($this->origWidth/$this->origHeight)*$height);
}
}
?>

encoder.php 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
require 'aws-sdk-php-master/vendor/autoload.php';
require 'resizeImage.php';
use Aws\Sqs\SqsClient;
use Aws\S3\S3Client;
$key = 'AKIAJKWXNJYIQPXaOP4SQ';
$secret = 'K39qUQYjMW8jBUaQlxkiMY/OlC2QejcDsHKZXRf4/';
$bucket = 'codingeverybodysqs';
$sqs_client = SqsClient::factory(array(
'key' => $key,
'secret' => $secret,
'region' => 'ap-northeast-1'
));
$s3_client = S3Client::factory(array(
'key' => $key,
'secret' => $secret
));
while(true){
sleep(1);
$result = $sqs_client->receiveMessage(array(
'QueueUrl' => $encoding_queue,
));
$msgs = $result->getPath('Messages');
if(count($msgs)===0){
echo ".";
continue;
}
foreach ($msgs as $msg) {
$messageBody = $msg['Body'];
$receiptHandle = $msg['ReceiptHandle'];
echo "\n".$messageBody.".... start encoding process\n";
$result = $s3_client->getObject(array(
'Bucket' => $bucket,
'Key' => $messageBody,
'SaveAs' => '/var/www/temp/'.$messageBody
));
echo $messageBody.".....downloaded\n";
$resize = new ResizeImage('/var/www/temp/'.$messageBody);
$resize->resizeTo(100, 100, 'exact');
$resize->saveImage('/var/www/encoded/'.$messageBody);
echo $messageBody.".....resized \n";
$result = $s3_client->putObject(array(
'Bucket' => $bucket,
'Key' => 'thumb.'.$messageBody,
'SourceFile' => '/var/www/encoded/'.$messageBody
));
echo $messageBody.".....upload s3\n";
$sqs_client->sendMessage(array(
'QueueUrl' => $email_queue,
'MessageBody' => json_encode(array('file'=>'thumb.'.$messageBody, 'email'=>'egoing@gmail.com')),
));
echo $messageBody.".....send message to the email queue\n";
$sqs_client->deleteMessage(array(
'QueueUrl' => $encoding_queue,
'ReceiptHandle' =>$receiptHandle
));
echo $messageBody.".....remove message from the encoding queue\n";
}
}
?>

이메일 발송 서버

이메일 발송 서버는 email 큐에 반복적으로 접속해서 처리해야 할 메시지가 없는지 확인한다. 메시지를 발견하면 해당 메시지를 이용해서 이메일을 발송한다. 

이메일을 발송하기 위해서는 sendmail이 설치 되어 있어야 한다. 아래와 같은 방법으로 설치하면 된다.

1
2
sudo apt-get install sendmail;
sudo service apache2 reload;

emailer.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
require 'aws-sdk-php-master/vendor/autoload.php';
use Aws\Sqs\SqsClient;
use Aws\S3\S3Client;
$key = 'AKIAJALGGRUXMMQERZKQ';
$secret = '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';
$bucket = 'codingeverybodysqs';
$sqs_client = SqsClient::factory(array(
'key' => $key,
'secret' => $secret,
'region' => 'ap-northeast-1'
));
while(true){
sleep(1);
$result = $sqs_client->receiveMessage(array(
'QueueUrl' => $email_queue,
));
$msgs = $result->getPath('Messages');
if(count($msgs)===0){
echo ".";
continue;
}
foreach ($msgs as $msg) {
$body = json_decode($msg['Body']);
$file = $body->file;
$mailto = $body->email;
$receiptHandle = $msg['ReceiptHandle'];
echo "\n".$file.".... start email process\n";
mail($mailto, $file.'의 인코딩이 끝났습니다.', $file);
echo $file.".....sended email to {$mailto}\n";
$sqs_client->deleteMessage(array(
'QueueUrl' => $email_queue,
'ReceiptHandle' =>$receiptHandle
));
echo $file.".....remove message from the email queue\n";
}
}
?>

댓글

댓글 본문
버전 관리
egoing
현재 버전
선택 버전
공동공부
graphittie 자세히 보기