22. 앱엔진 vs EC2
PaaS
구글 앱 엔진
IaaS
EC2
내가 질 책임
애플리케이션
애플리케이션, 데이터베
이스, 웹서버, 운영체제,
모니터링, 로드밸런싱, 업
그레이드
sysadmin
Google
필요
(상대적) 비용
비쌈
쌈
Google Compute Engine vs EC2
23. Platform as a Service
Frontend Instance
Blobstore
Images Services
Datastore
Memcache
Backend Instance
Mail
Cron
Task Queue
Admin Console
25. Snapchat
월 활성 사용자(MAU) 3천만
55% 가 매일 사용함 - 1천6백만
하루에 1억 5천만 사진 업로드
“앱엔진은 우리가 애플리케이션을 개발하는데 집중할 수 있게 해줬어
요. 앱엔진이 우리에게 제공해준 개발의 편의없이 이렇게까지 못했을
꺼에요.”
- 바비 머피, CTO 이며 co-Founder
http://www.quora.com/Google-App-Engine/What-is-the-highest-traffic-website-built-on-top-of-Google-App-Engine-Python
http://gigaom.com/2013/05/07/snapchats-act-of-faith-in-building-on-google-compute-engine/
26. Khan Academy
380만 월 UV
수업일에 150만 프랙티스가 제공
2000 개 이상의 동영상
“만약 구글 앱엔진이 없었다면, 서버를 셋업이나 라우터 설정에 정말 많은
시간을 보냈을꺼에요. 실 서비스에 집중할 수 있게 한 건 구글 앱엔진의 장
점입니다.”
- 벤 카멘스, 리드 개발자
“개발 프로세스가 쉬워서 평균 하루에 한번, 많게는 10번도 배포를 합니다.”
https://cloud.google.com/files/KhanAcademy.pdf
27. Rovio
Angry bird friend for facebook
MAU 1천 3백만
“구글 앱엔진은 우리가 게임당 한명 또는 두명의 개발자로만 매우 빠르
게 게임을 런칭하도록 해줬어요. 구글이 모든 서버들을 관리해주기 때
문에, 유지보수에 있어 우리가 할 일이 거의 없었어요.”
- 스테판 호크, 웹 게임 리드 서버 개발자
https://cloud.google.com/files/Rovio.pdf
28. 왜 레진코믹스는 구글 앱엔진을 선택했나
•
개발이 빠르고 쉬움
•
자동으로 스케일링해줌
•
개발에만 집중
•
유용한 빌트인 기능들 제공
•
구글 노하우가 녹아있는 인프라 위에서 구동 (비즈니스)
30. Language
& Runtime
Java
Generally available features
Communications
Channel
Google Cloud
Endpoints
Mail
PHP
Python
preview
App Identity
Data Storage, Retrieval, &
Search
Datastore
SSL for
Custom
Domains
Blobstore
Remote
XMPP
Traffic Splitting
Users
Preview features
Cloud SQL
Google Cloud
Storage Client
Library
Capabilities
Multitenancy
Search
Memcache
Dedicated
Memcache
Logs
Modules
Sockets
Experimental features
Datastore Admin/
Backup/Restore
MapReduce
OAuth
OpenID
PageSpeed
Prospective Search
Task Queue
Scheduled
Tasks
experimental
App Configuration
& Management
URL Fetch
Process Management
Go
Computation
Backends
Images
HRD Migration
Tool
Task Queue REST
API
Task Queue
Tagging
Appstats
31. Language
& Runtime
Java
Generally available features
Communications
Channel
Google Cloud
Endpoints
Mail
URL Fetch
PHP
Python
preview
App Identity
Data Storage, Retrieval, &
Search
Datastore
SSL for
Custom
Domains
Blobstore
Remote
Multitenancy
Users
Task Queue
Preview features
Cloud SQL
Google Cloud
Storage Client
Library
Capabilities
Traffic Splitting
Scheduled
Tasks
experimental
App Configuration
& Management
XMPP
Process Management
Go
Search
Memcache
Dedicated
Memcache
Logs
Modules
Sockets
Experimental features
Datastore Admin/
Backup/Restore
MapReduce
OAuth
OpenID
PageSpeed
Prospective Search
Computation
Backends
Images
HRD Migration
Tool
Task Queue REST
API
Task Queue
Tagging
Appstats
32. 드리고 싶은 이야기
배포/관리
My App
App Engine API
Mail
경험한 기능들
정말 팁
Task Queue
Datastore
Blobstore
Dedicated
Memcache
Appstats
Scheduled
Tasks
참고사항
URL Fetch
Logs
Images
그 다음
북마크
44. local
•앱엔진 샌드박스 제공
dev server
•개발용 app id
•개발자 별로 버전 배포
•노출 안되게 앱엔진 admin 권한 처리
production
•새 버전 배포 -> 확인 -> 디폴트 변경
•/WEB-INF/appengine-generated/local_db.bin
앱/버전 property 로 관리 - 빌드타임에 정해지도록 함
appengine'web.xml.
!
<application>${google.app.id}</application>.
<version>${google.app.version}</version>
46. 데이터스토어 - Key
Entity Comic
String comicId *
String title
String artist
User
Long userId *
String username
boolean adult
int coinBalance
Purchase
Long purchaseId *
String episodeId
int coin
long purchaseTime
Long userId
Key - entity 의 ID / 구글앱엔진에서의 유일한 키 값
kind
identifier
ancestor path (optional)
47. 데이터스토어 - Key
Entity Comic
String comicId *
String title
String artist
User
Long userId *
String username
boolean adult
int coinBalance
Purchase
Long purchaseId *
String episodeId
int coin
long purchaseTime
Long userId
Key - entity 의 ID / 구글앱엔진에서의 유일한 키 값
kind
identifier 지정 - 미리 아는 객체들 (string, long)
ancestor path (optional)
identifier 자동할당 - 실행시 생성되는 객체들 (long)
48. 데이터스토어 - Key
Entity Comic
String comicId *
String title
String artist
Key - entity 의 ID / 구글앱엔진에서의 유일한 키 값
kind
identifier
ancestor path (optional)
User
Long userId *
String username
boolean adult
int coinBalance
Purchase
Long purchaseId *
String episodeId
int coin
long purchaseTime
Long userId
SELECT.*.FROM.Comic.
WHERE.__key__.=.Key('Comic',.'badboss')
SELECT.*.FROM.User.
WHERE.__key__.=.Key('User',.1234123412341234)
49. Global Query
User
Long userId *
String username
boolean adult
int coinBalance
Purchase
Long purchaseId *
String episodeId
int coin
long purchaseTime
Long userId
SELECT.*.FROM.Purchase.
WHERE.userId.=.1234123412341234.
AND.episodeId.=.‘badboss'''13’
53. Ancestor
User
Long userId *
String username
boolean adult
int coinBalance
Purchase
Long purchaseId *
String episodeId
int coin
long purchaseTime
Long userId
SELECT.*.FROM.Purchase.
WHERE.ancestor)is.Key(‘User’,.1234123412341234).
AND.episodeId.=.‘badboss'''13’
54. Ancestor
Entity Group
User
Long userId *
String username
boolean adult
int coinBalance
Purchase
Long purchaseId *
String episodeId
int coin
long purchaseTime
<Parent>Long userId
Key - entity 의 ID
kind
identifier
ancestor path
SELECT.*.FROM.Purchase.
WHERE.ancestor)is.Key(‘User’,.1234123412341234).
AND.episodeId.=.‘badboss'''13’
55. 데이터스토어 인덱스
User
Long userId *
String username
boolean adult
int coinBalance
Purchase
Long purchaseId *
index
String episodeId
int coin
long purchaseTime
<Parent>Long userId
SELECT.*.FROM.Purchase.
WHERE.ancestor)is.Key(‘User’,.1234123412341234).
AND.episodeId.=.‘badboss'''13’
주의
index 는 entity 를 update 할 때 생김
나중에 추가하려면 entity 를 새로update 해야 함
57. 카운트
1. 카운트하는 엔터티를 둔다.
- 동시에 엔터티를 수정하게 되면 Datastore Contention 문제
- 동시에 못하도록 한다면 한번에 한 카운트만 처리 문제
!
2. Sharding Counter
https://developers.google.com/appengine/articles/sharding_counters
- 랜덤으로 카운터를 여러개 두고, 사용하지 않은 카운터를 읽고 씀
- 나중에 합쳐 확인하는 방법
- 정확
- 매 요청마다 데이터스토어 써 느린데다 데이터 엔터티가 무수히 많이 생김
!
3. Deferred Task Queue 활용
- 데이터스토어에 permanent 카운트
- Memcache 에 current 카운트
- 주기적으로 Memcache 에서 데이터스토어로 씀
- 성능은 좋지만, 정확하지 않을 수 있다.
58. 비용 줄이기
•
Appstats 써서 요청에 대한 비용이 어느정도인지 검토
•
Memcache 를 되도록 많이 쓰기
•
Urlfetch 는 될 수 있는 한 앱에서 할 것
63. 세션 삭제, 앱엔진이 안해줌
!
/_ah/sessioncleanup
com.google.apphosting.utils.servlet.SessionCleanupServlet
!
cron 으로 주기적으로 호출할 것
http://www.radomirml.com/blog/2011/03/26/cleaning-up-expired-sessions-from-app-engine-datastore/
64. Cron 문법 주의
• 매시간마다
===> every 1 hours
• 매시간인데
15분에 실행되면 좋겠음
===> every 1 hours from 00:15 to 00:15
영원히 실행되지 않음
!
every 1 hours from 00:15 to 00:14
65. static 파일 만료 시간 조정
• Purge
• 사용자
기능 없음.
브라우저에 의존하기 때문에 (자주 바뀐다면) 시간을
조정해둘 것
68. Latency
•
데이터센터 저 멀리
•
cdn 이용
•
•
dynamic 데이터는 어쩔 수 없음
좋은 소식
•
아시아에 데이터센터 들어감
http://googleasiapacific.blogspot.kr/2013/12/our-first-data-centers-in-asia-are-up.html
69. 앱엔진 + 스프링 최적화
•
Component Scanning 줄이기/피하기
•
Relationship Autowiring 줄이기/피하기
•
상용에서 XML Validation 하지 않기
•
Lazy-Initialized Bean 사용하기
•
Constructor Injection by Name 피하기
•
https://developers.google.com/appengine/
articles/spring_optimization
70. 로그 / 파일
•
로그는 좀 많이 불편
•
File API 안됨
•
PG사 모듈 File 쓰기 안되어서 제외