45
KEEP IT SIMPLE, WEB DEVELOPMENT STACK PYCONHK - 2015 ERIC(BYUNGWOOK) AHN 1

Keep it simple web development stack

Embed Size (px)

Citation preview

Page 1: Keep it simple web development stack

K E E P I T S I M P L E , W E B D E V E L O P M E N T S TA C K

P Y C O N H K - 2 0 1 5 E R I C ( B Y U N G W O O K ) A H N

1

Page 2: Keep it simple web development stack

Who am I

Eric (ByungWook) Ahn G+ : https://plus.google.com/+EricAhns

Experienced : Device driver(windows, linux) Media streaming CDN Docker

Platform Architecture Team at SK planet co., Ltd.

Page 3: Keep it simple web development stack
Page 4: Keep it simple web development stack

D O C K E R S A M P L E A P P A R C H I T E C T U R E T E S T E N V I R O N M E N T P E R F O R M A N C E

TODAY…

Page 5: Keep it simple web development stack

https://www.docker.com/B U I L D , S H I P, R U N

A n o p e n p l a t f o r m f o r d i s t r i b u t e d a p p l i c a t i o n s f o r d e v e l o p e r s a n d s y s a d m i n s

W H A T I S D O C K E R

Page 6: Keep it simple web development stack

C O N TA I N E R

Page 7: Keep it simple web development stack

F R O M u b u n t u R U N \ a p t - g e t u p d a t e & & \ a p t - g e t i n s t a l l - y p y t h o n p y t h o n - d e v p y t h o n -p i p p y t h o n - v i r t u a l e n v & & \ r m - r f / v a r / l i b / a p t / l i s t s / *

$ c a t D o c k e r f i l e

Page 8: Keep it simple web development stack

$ docker build -t=“mypython” . $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE mypython latest ecc926c495f8 7 seconds ago 373.6 MB ubuntu latest 91e54dfb1179 4 days ago 188.4 MB mysql latest c45e4ba02f47 12 days ago 283.8 MB python 2.7 e1857ee1f3b5 5 weeks ago 674.4 MB nginx latest 6886fb5a9b8d 5 weeks ago 132.9 MB

$ docker run -it mypython python Python 2.7.6 (default, Jun 22 2015, 17:58:13) [GCC 4.8.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>

$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b596713d6934 mypython "python" 2 seconds ago Exited (0) 2 seconds ago clever_hypatia

image create ( referenced at Dockerfile of current directoy)

Execute a Container

Print a containers on docker hosts

Page 9: Keep it simple web development stack

Docker Host example - docker container : ubuntu 2ea - container : ubuntu(nginx) $ top

Page 10: Keep it simple web development stack

D O C K E R - M A C H I N E VirtualBox Microsoft Hyper-V SOFTLAYER openstack Microsoft Azure AWS rackspace DigitalOcean

create & remove

run

$ d o c k e r- m a c h i n e l s N A M E A C T I V E D R I V E R S TAT E U R L S WA R M d e f a u l t v i r t u a l b o x S t o p p e d d e v v i r t u a l b o x S t o p p e d p y c o n h k v i r t u a l b o x S t o p p e d p y c o n h k 0 2 v i r t u a l b o x S t o p p e d p y c o n h k 0 3 v i r t u a l b o x S t o p p e d p y c o n h k 0 4 v i r t u a l b o x S t o p p e d p y c o n h k 0 5 v i r t u a l b o x S t o p p e d

$ d o c k e r- m a c h i n e

$ d o c k e r

Page 11: Keep it simple web development stack

DOCKER-COMPOSE

W E B

D B

$ docker-compose up -d

C O N F I G U R AT I O N ? = > YA M L

$ cat docker-compose.yml db: image: mysql environment: - MYSQL_ROOT_PASSWORD=hellopython - MYSQL_DATABASE=shopping_db ports: - "3306:3306" web: build: ./web_api/ command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/web_api ports: - "8000:8000" links: - db:db

Page 12: Keep it simple web development stack

{“product_code":"1004", "product_title":"BLOOMSBURY BOUQUET WHEELED SUITCASE”, "product_price":115}

Sample Application

Page 13: Keep it simple web development stack

Sample Application

A N G U L A R J S O N

P Y T H O N R E S T A P I

P Y T H O N R E S T A P I

D BL O A D B A L A N C E R

L O A D B A L A N C E R

A N G U L A R J S O N

Page 14: Keep it simple web development stack

A N G U L A R J S O N

P Y T H O N R E S T A P I

P Y T H O N R E S T A P I

D BL O A D B A L A N C E R

L O A D B A L A C E R

A N G U L A R J S O N

J AVA R E S T A P I

J AVA R E S T A P I

G O L A N G R E S T A P I

G O L A N G R E S T A P I

R O U T I N G

R E D I SRestful API…

Page 15: Keep it simple web development stack

T E S T E N V I R O N M E N T

Traffic Generation Server Dell R620 2.0 GHz/2P/12C 32G

Docker Host. HP DL380G7 2.13GHz/1P/4C 24GB

load testing tool? nGrinder/Apache ab/locust.io

Page 16: Keep it simple web development stack

T E S T E N V I R O N M E N T$ docker inspect web1 [{ "AppArmorProfile": "", "Args": [ "-g", "daemon off;" ], "Config": { "AttachStderr": false, "AttachStdin": false, "AttachStdout": false, "Cmd": [ "nginx", "-g", "daemon off;" ], "CpuShares": 1024, => "Cpuset": "", "Domainname": “", … …

$ docker inspect web2 [{ "AppArmorProfile": "", "Args": [ "-g", "daemon off;" ], "Config": { "AttachStderr": false, "AttachStdin": false, "AttachStdout": false, "Cmd": [ "nginx", "-g", "daemon off;" ], "CpuShares": 512, => "Cpuset": "", "Domainname": “", … …

$ docker inspect web3 [{ "AppArmorProfile": "", "Args": [ "-g", "daemon off;" ], "Config": { "AttachStderr": false, "AttachStdin": false, "AttachStdout": false, "Cmd": [ "nginx", "-g", "daemon off;" ], "CpuShares": 512, => "Cpuset": "", "Domainname": “", … …

C P U :5 0 %

C P U :2 5 %

C P U :2 5 %

Page 17: Keep it simple web development stack

Browser http://demo/

A P P L I C AT I O N S TA C K

A n g u l a r J S

A P I s : h t t p : / / w e b _ a p i : 8 0 0 0 / s h o p p i n g / P y t h o n 1 . 7 . 0 D j a n g o 1 . 8 . 3 M y S Q L 5 . 6 . 2 3 , P o s t g r e S Q L 9 . 4 . 4 m e m c a c h e d

Page 18: Keep it simple web development stack

T E S T C A S E

Django Cache Database -

Case_01 1.8.3 - Mysql 5.6.23 -

Case_02 1.8.3 - - -

Case_03 1.8.3 - Postgresql 9.4.4 -

Case_04 1.8.3 Memcache Mysql 5.6.23 -

Demo 1.8.3 Memcache Mysql 5.6.23 Load Balancer

Page 19: Keep it simple web development stack

N G R I N D E R / A PA C H E A B / L O C U S T. I O nGrinder : create 1 controller and 5 agents container

// controller $ docker run -d -v ~/.ngrinder:/root/.ngrinder --name ngrinder -p 80:80 -p 16001:16001 -p 12000-12009:12000-12009 ngrinder/controller:3.3

// agent : 5th $ docker run -d -e 'CONTROLLER_ADDR=ngrinder:80' --link ngrinder:ngrinder ngrinder/agent:3.3 $ docker run -d -e 'CONTROLLER_ADDR=ngrinder:80' --link ngrinder:ngrinder ngrinder/agent:3.3 $ docker run -d -e 'CONTROLLER_ADDR=ngrinder:80' --link ngrinder:ngrinder ngrinder/agent:3.3 $ docker run -d -e 'CONTROLLER_ADDR=ngrinder:80' --link ngrinder:ngrinder ngrinder/agent:3.3 $ docker run -d -e 'CONTROLLER_ADDR=ngrinder:80' --link ngrinder:ngrinder ngrinder/agent:3.3

Page 20: Keep it simple web development stack

container nginx : 1.9.2 index.html, 600 bytescontainer x 5

nGrinder agent

Page 21: Keep it simple web development stack

D E M O - C A S E 1 : S A M P L E A P P$ cat settings.py INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'shopping' ) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'shopping_db', 'USER': 'root', 'PASSWORD': 'hellopython', 'HOST': 'db', 'PORT': 3306, } }

Page 22: Keep it simple web development stack

S A M P L E A P Pmodels.py from django.db import models

class Shopping(models.Model): product_code = models.TextField() product_title = models.CharField(max_length=100, verbose_name = "Product name") product_price = models.IntegerField(default='0', verbose_name = "Product price")

class Meta: verbose_name = "Product list" verbose_name_plural = "Favorite lists"

Page 23: Keep it simple web development stack

S A M P L E A P P

// views.py def shopping_list(request): """ List all code shoppinglists, or create a new shopping. """ if request.method == 'GET': shoppinglists = Shopping.objects.all() serializer = ShoppingSerializer(shoppinglists, many=True) return JSONResponse(serializer.data)

// serializers.py from rest_framework import serializers from shopping.models import Shopping

class ShoppingSerializer(serializers.ModelSerializer): class Meta: model = Shopping fields = ('product_code', 'product_title', 'product_price')

urls.py urlpatterns = [ url(r'^shopping/$', views.shopping_list) ]

Page 24: Keep it simple web development stack

S A M P L E A P P

$ cat docker-compose.yml db: image: mysql environment: - MYSQL_ROOT_PASSWORD=hellopython - MYSQL_DATABASE=shopping_db ports: - "3306:3306" web: build: ./web_api/ command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/web_api ports: - "8000:8000" links: - db:db

Page 25: Keep it simple web development stack

demo : case1

Page 26: Keep it simple web development stack

P E R F O R M A N C E : C A S E 1

P Y T H O N R E S T A P I

M Y S Q LL O A D T O O L

Page 27: Keep it simple web development stack

D E M O : C A S E 2

views.py def shopping_list(request): """ List all code shoppinglists, or create a new shopping. """ if request.method == 'GET': return JSONResponse({“product_code":"1005", "product_title":"BILLIE GOES TO TOWN SHOPPER","product_price":28})

Page 28: Keep it simple web development stack

P E R F O R M A N C E : C A S E 2

P Y T H O N R E S T A P IL O A D T O O L

Page 29: Keep it simple web development stack

N G I N X - G U N I C O R N$ cat dockdr-compose.yml nginx: restart: always build: ./nginx/ ports: - "80:80" volumes: - /www/static volumes_from: - web links: - web:web web: restart: always build: ./web expose: - "8000" volumes: - /usr/src/app/static env_file: .env command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000

N G I N X+ G U N I C O R N

P Y T H O N R E S T A P I

L O A D T O O L

Page 30: Keep it simple web development stack

N G I N X - G U N I C O R N

$ cat nginx.conf

server { listen 80; server_name example.org; charset utf-8; location /static { alias /usr/src/app/static; } location / { proxy_pass http://web:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }

Page 31: Keep it simple web development stack

N G I N X - G U N I C O R Ngunicorn docker_django.wsgi:application -w 2

Page 32: Keep it simple web development stack

gunicorn docker_django.wsgi:application -w 12

Page 33: Keep it simple web development stack

D E M O : C A S E 3

$ cat settings.py

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'shopping_db', 'USER': 'postgres', 'PASSWORD': 'hellopython', 'HOST': 'db', 'PORT': 5432, } }

Page 34: Keep it simple web development stack

$ cat docker-compose.ml web: build: ./web_api/ command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/web_api ports: - "8000:8000" links: - db:db db: image: postgres ports: - "5432:5432" environment: - DB_USER=postgres - DB_PASS=hellopython - DB_NAME=shopping_db

D E M O : C A S E 3

Page 35: Keep it simple web development stack

P E R F O R M A N C E : C A S E 3

Page 36: Keep it simple web development stack

D E M O : C A S E 4settings.py CACHE = { 'default':{ 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': 'memcached:11211' } } views.py

def shopping_list(request): """ List all code shoppinglists, or create a new shopping. """ if request.method == 'GET': data = cache.get('shoppinglists') if data is None: shoppinglists = Shopping.objects.all() serializer = ShoppingSerializer(shoppinglists, many=True) data = serializer.data cache.set('shoppinglists', data, 60) # seconds return JSONResponse(data)

Page 37: Keep it simple web development stack

$ cat docker-compose.yml db: image: mysql environment: - MYSQL_ROOT_PASSWORD=hellopython - MYSQL_DATABASE=shopping_db ports: - "3306:3306"

memcached: image: memcached:1.4 ports: - "11211:11211"

D E M O : C A S E 4

web: build: ./web_api/ command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/web_api ports: - "8000:8000" links: - db:db - memcached:memcached

Page 38: Keep it simple web development stack

P E R F O R M A N C E : C A S E 4

P Y T H O N R E S T A P I

M Y S Q LL O A D T O O L

M E M C A C H E D

Page 39: Keep it simple web development stack

D E M O A R C H I T E C T U R E

P Y T H O N R E S T A P I

M Y S Q L

M E M C A C H E D

W E B PA G E

H A P R O X Y

W E B PA G E

W E B PA G E

H A P R O X YP Y T H O N R E S T A P I

P Y T H O N R E S T A P I

Page 40: Keep it simple web development stack

demo-composer.yml - haproxy - mysql - memcached - python django restframeowork

Page 41: Keep it simple web development stack

web: restart: always build: ./web_api/ command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/web_api expose: - "8000" links: - db - memcached

weblb: restart: always image: tutum/haproxy links: - web ports: - "80:80" environment: - BACKEND_PORT=8000

$ docker-compose build . $ docker-compose scale web=10 $ docker-compose up -d —no-recreate

db: image: mysql environment: - MYSQL_ROOT_PASSWORD=hellopython - MYSQL_DATABASE=shopping_db ports: - "3306"

memcached: image: memcached:1.4 ports: - "11211"

Page 42: Keep it simple web development stack

P E R F O R M A N C E : D E M O

Page 43: Keep it simple web development stack

DEMO

Page 44: Keep it simple web development stack

Conclusion

Python Django djangorestframawork ORM MySQL, Postgresql memcached Docker

Today reviewed :

flask redis memcached(memory-based) other rest framework gunicorn vs uwsgi test environment best practice

Next time:

Page 45: Keep it simple web development stack

Q&A