AWS Lambda@Edge 및 Google Cloud Functions의 이미지 크기 조정 서버 중 어느 것이 더 빠릅니까?

이미지 리사이즈 처리는 꽤 귀찮기 때문에 최근에는 이미지 리사이즈 서버를 구축해 URL 의 쿼리 스트링으로 동적으로 리사이즈 하도록 하고 있습니다. 스테디셀러는 nginx 로 구축하는 케이스입니다만, 서버의 관리를 해야 하기 때문에 개인적으로는 서버리스 구성이 좋아합니다.

따라서 AWS의 CloudFront Lambda@Edge와 Google의 Cloud Functions에서 크기 조정을 수행할 때의 성능 차이를 측정해 보았습니다.

구성도



다음과 같은 구성으로 측정했습니다.



AWS는 CloudFront + Lambda@Edge를 사용하여 크기를 조정했으며 오리진 서버는 S3입니다. Google은 Cloud Functions를 사용하여 크기를 조정하고 오리진 서버는 Cloud Storage입니다. 둘 다 사설망과 같은 연결을 할 수 없다고 합니다만, 아마 물리적으로는 가깝다고 추측해, 각각의 스토리지 서비스로의 조합으로 하고 있을 것입니다.

검증 코드



측정하기 위한 코드이므로 실용적이지는 않지만 참고까지.

Lambda@Edge


const request = require('request-promise')
const Sharp = require('sharp')

const download = (url) => {
  return request({
    url: url,
    encoding: null
  })
}

const resize = (body, format, width, height) => {
  return Sharp(body)
    .resize(width, height)
    .toFormat(format)
    .toBuffer()
    .then(buffer => {
      return buffer
    }).catch(error => {
      console.log(error)
    })
}

module.exports.perform = (event, context, callback) => {
  let response = event.Records[0].cf.response
  const request = event.Records[0].cf.request
  download(`https://s3.amazonaws.com/example-bucket-name${request.uri}`).then(body => {
    const format = 'jpeg'
    resize(body, format, 200, 100).then(body => {
      resizeFunc.save(body, format, 'sample').then(() => {
        response.status = 200
        response.body = body.toString('base64')
        response.bodyEncoding = 'base64'
        response.headers['content-type'] = [{ key: 'Content-Type', value: 'image/' + format }]
        callback(null, response)
      })
    })
  })
}

S3에서의 파일 다운로드를 S3 SDK를 사용한 버전에서도 비교했지만 변화는 없었습니다.

참고 코드
const getFile = key => {
  return S3.getObject({
    Bucket: BUCKET,
    Key: key.slice(1)
  }).promise()
}
getFile(request.uri).then(data => {
  const body = data.Body
  // snip
})

Cloud Functions


import * as functions from 'firebase-functions'
const firebaseConfig = JSON.parse(process.env.FIREBASE_CONFIG)
import * as admin from 'firebase-admin'
admin.initializeApp()
storage = admin.storage()

const sharp = require('sharp')
const fileType = require('file-type')
const os = require('os')
const path = require('path')

export const image_resize = functions.https.onRequest((req, res) => {
  const filePath = req.query.path
  const bucket = storage.bucket(firebaseConfig.storageBucket)
  const tempFilePath = path.join(os.tmpdir(), `${Math.round( Math.random() * 1000 )}`)
  bucket.file(filePath).download({
    destination: tempFilePath,
  }).then(() => {
    sharp(tempFilePath)
      .rotate()
      .resize(200, 100)
      .toBuffer()
      .then(data => {
        const type = fileType(data)
        res.set('Content-Type', type.mime)
        res.status(200).send(data)
      })
  })
})

검증 결과


ab 명령을 사용하여 각 평균 응답을 발행했습니다.


품목
요청당 응답 속도


Lambda@Edge
4.3 sec

Cloud Functions
2.6 sec


2018/11/18 현재 Cloud Functions가 더 빠릅니다.

어디에 시간이 걸리고 있는지 말하면, 각각의 오리진 서버로부터의 이미지 파일 다운로드입니다. Sharp를 사용한 리사이즈 처리 자체는 거의 차이가 없었습니다. 검증으로 사용하고 있는 코드를 개선하면 보다 퍼포먼스 좋게 할 수 있을지도 모릅니다만… 이라고 할까, 알고 싶다.

실제로는 CDN으로 캐시하기 때문에, 최초의 액세스 이후는 고속으로 응답을 돌려줄 수 있습니다만, 그렇다고는 해도 최초의 액세스를 어디에서 발생시킬까는 어플리케이션에 의해 바뀌어 오므로, 어떤 상황이라도 고속이다 쪽이 좋다고 생각합니다.

좋은 웹페이지 즐겨찾기