루비가 얼랭에 빠진 날
DESCRIPTION
2008.5 제5회 루비세미나 발표TRANSCRIPT
Concurrency-oriented Programming
3
How Erlang programs work?
• 많은 프로세스들로 구성– 운영체제 독립적인 경량 (light-weight) 프로세스– 유일한 식별자 (Pid)– 많은 프로세스를 동시 처리 (100,000 개 이상 )
• 프로세스들 간에 서로 메시지를 주고 받음– 비동기적 메시지 전달 메커니즘
• 프로세스는 서로 연결 (link) 될 수 있음– 연결된 프로세스가 죽으면 다른 프로세스가 통보받음– 수퍼바이저 / 워커 모델 구성
4
A Stateless Server Process-module(demo2).-compile(export_all).
run() -> Pid = spawn(fun echo/0), Pid ! {self(), hello, 42}, receive {Pid, reply, 42} ->
Pid ! stop end.
echo() -> receive {From, hello, Val} ->
From ! {self(), reply, Val},echo(); % loop!
stop ->io:format("Done!~n", []),ok
end.
P1
P2
{P1, hello, 42}
{P2, reply, 42}
Client
Server
stop
5
Benefits of COP
• 성능 (Performance)– 분산 병렬 처리– Multi-core Support
• 가용성 (Reliability)– 무정지 (fault-tolerent)– Hot code swapping
• 확장성 (Scalability)
6
generic_server
OTP gen_server 비헤비어
7
Apache vs. Yaws
* http://www.sics.se/~joe/apachevsyaws.html
REpresentational State Transfer
9
RESTful URL (Rails)
• GET /posts index• GET /posts/1 show• GET /posts/new new• GET /posts/1/edit edit• POST /posts create• PUT /posts/1 update• DELETE /posts/1 destroy
10
respond_to :wow!
# POST /posts # POST /posts.xml def create @post = Post.new(params[:post])
respond_to do |format| if @post.save flash[:notice] = 'Post was successfully created.' format.html { redirect_to(@post) } format.xml { render :xml => @post, :status => :created, :location => @post } else format.html { render :action => "new" } format.xml { render :xml => @post.errors, :status => :unprocessable_entity } end end end
11
GoogleTrends “ruby on rails”
1.0 1.2 2.0
resource 도입 from MVC to REST
12
The RADAR Architecture
* RESTful Application, Dumb-Ass Recipient (http://pragdave.pragprog.com/pragdave/2007/03/the_radar_archi.html)
Time to Relax…
14
CouchDB
문서 (document) 기반 데이터베이스 서버 .
Aaccessible via a RESTful JSON API Views (incremental map/reduce) Schema-Free Distributed, robust architecture Written in Erlang Apache Incubating (alpha 0.8 release)
15
SQL vs. CouchDB
SQL CouchDB
Predefined, explicit schema Dynamic, implicit schema
Uniform tables of data Collection of named documents with varying structure
Normalized. Objects spread across tables. Duplication reduced.
Denormalized. Docs usually self contained. Data often duplicated.
Must know schema to read/write a complete object Must know only document name
Dynamic queries of static schemas Static queries of dynamic schemas
* http://www.zefhemel.com/archives/2008/03/11/sittin-on-the-couchdb
16
Document = JSON Object
{
"_id":"discussion_tables",
"_rev":"D1C946B7",
"Subject":"I like Planktion",
"Author":"Rusty",
"PostedDate":"2006-08-15T17:30:12-04:00",
"Tags":["plankton", "baseball", "decisions"],
"Body":"I decided today that I don't like baseball. I like plankton."
}
17
Some CouchDB REST APIs• Dababase API
– GET /_all_dbs 모든 DB– PUT /database/ 새 DB 생성– DELETE /database/
• Document API– GET /database/doc_id– POST /database/ 또는 PUT /database/doc_id– PUT /database/doc_id (with ‘_rev’ property) – DELETE /database/dic_id?rev=xxx
• View API– GET /database/_view/view_name/func_name
18
Accessing CouchDB with Ruby
• 범용– ActiveResource– REST Client
• CouchDB 전용– CouchObject– Ruby-CouchDB– ActiveCouch– Couchrest
DEMO
20
Admin Interface
21
Ruby View
22
Extending AResclass CouchResource < ActiveResource::Base class << self def element_path(id, prefix_options = {}, query_options = nil) "#{prefix(prefix_options)}#{collection_name}/#{id}#{query_string(query_options)}"
def collection_path(prefix_options = {}, query_options = nil) "#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
def instantiate_collection(collection, prefix_options = {}) collection = collection.fetch("rows") if collection.kind_of? Hash
def instantiate_record(record, prefix_options = {}) record = record.fetch("value") if record.has_key? "value“ def find_view(view_name, func_name) find(:all, :from => "/#{element_name}/_view/#{view_name}/#{func_name}") end
23
Mywiki Resource
class Mywiki < CouchResource self.site = "http://localhost:5984" self.format = :json self.collection_name = 'mywiki' # used as a database name self.primary_key = '_id'end
24
Console Result
25
Finish!!