Hank Lin

A new blog

AWS SDK for Java

| Comments

好消息, 好消息, AWS 推出了完整的Java SDK. 優點是AWS的服務都有support!. 像是EC2, S3, Auto Scaling, CloudWatch, Elastic Load Balancing, Virtual Private Cloud, SimpleDB, SQS, RDS, Elastic MapReduce. 以前都是得自己一個服務一個服務去找library, 現在不用再一個一個找了. 而且Amazon很好心的包成一個jar, 不用再管理200個jar files了.(哪有200個啊!) javadoc也有寫內容, 不是空洞的. 還有sample code. 不過我還沒真正試用看看, 等我試用好了再來報告. 至於AWS toolkit for Eclipse 是很久以前就有了啦. 不過因為我都是用command line的tool 比較多, 所以就懶得裝了. 而且我不想裝太多plugin 到Eclipse咩!

用terracotta達成tomcat Session Replication

| Comments

不設定session replication 的tomcat cluster

Tomcat是最常用的java servlet container了, 經過調教也有很多網站在使用. 如果要達成high scalability的話, clustering 是最常用的手段. 這一篇老文章: Under the Hood of J2EE Clustering, 把一些application server 怎麼做clustering的方法寫得很清楚. 在這邊我要介紹不用tomcat的cluster 機制去做到session replication. 我先複製了兩份tomcat 6.0 的目錄, 分別放在 /opt/server1 和/opt/server2 , 然後分別listen 8080, 8081 port. 然後jvmRoute 分別設成jvm1, jvm2以資區別. (以上如果不知道要怎麼做的話…ㄟㄟ…請看tomcat document) 用port的好處就是可以不用switch, 就把browser 裡的cookie 帶到servers, 因為cookie是只看domain和path的. 而且我還可以用port 控制我要request到哪一台, 可以說是development 測試最方便的作法了.

tomcats 好了之後, 在eclipse 裡開個新web project, 我把他叫tc (名字我都喜歡短的). 就做一個簡單的計數器, 每request 一次就把request過的次數加1, 然後印到畫面上:

CountServlet.java

package com.hanklin;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class CountServlet extends HttpServlet {
    private static final long serialVersionUID = -4951220189098528823L;

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        HttpSession session = req.getSession();
        AtomicInteger count = (AtomicInteger) session.getAttribute("count");
        if (count == null) {
            count = new AtomicInteger();
            session.setAttribute("count", count);
        }
        resp.getWriter().write("

" + count.addAndGet(1) + "

"); } }

好吧, 這在使用者第一次request時, 如果同時發很多requests可能會錯, 不過那不是這裡的重點, 所以不管他. 接下來是web.xml, 也很簡單的.

web.xml



  tc
  
    count
    com.hanklin.CountServlet
  
  
    count
    /count
  

然後可以輸出成tc.war檔了, 把tc.war 丟到兩個tomcat 的webapps目錄下面, 然後開server.

$ sudo /opt/server1/startup.sh
$ sudo /opt/server2/startup.sh

依次開兩個chrome來看看:

http://localhost:8080/tc/count http://localhost:8081/tc/count

好的, 你沒見過我, 我也不認識你. 現在該terracotta 大軍 登場了.

terracotta 簡介

Terracotta, 說是簡介可是實在不知道如何”簡”起啊! 以前terracotta網站自己介紹是”Network-attached memory”, 就是要你把他想成NAS(Network-attached storage). 還用很多flash動畫說明, 看起來就像很多java processes 可以合在一起, 形成一個超大的java process. 在這個超大java process 裡面, 被shared的objects 可以被不同的小java processes 存取, 而且會符合Java language的規範, 像是==, hashCode() 會有正確的行為. 而且也會符合Java Memory Model的行為, 如synchronized. 在The Definitive Guide to Terracotta 一書裡面, 是這樣定義Terracotta: “a transparent clustering service for Java applications”. (內心OS: 這本書快出第二版了, 要記得去買) 所以terracotta的架構就是要有一台terracotta server(技術文件叫L2), 管理這些shared objects, 然後有許多的terracotta clients(技術文件叫L1), 也就是你的java applications, 連到terracotta server. 當你的一個java application 寫入一個shared objects時, 另一個java application 可以讀到更新後的值. 感覺起來和一些caching solution很像, 可是如果你有注意到我前面說的, 像是 synchronized 也可以正常運作的話, 就可以知道這並不只是單純的caching objects, 還包含協調行為, 而且Java 的code 是可以不用改的. 不過有一些classes是不能shared, terracotta 把它叫作Non-Portable Classes, 要注意啊. 我最早開始在EC2上弄tomcat clustering 的時候, 發現到在EC2的環境是不支援multicast的. 這樣的話tomcat內建的clustering 機制就無法運作, 只能在load balancer上動手腳, 讓同一個client 始終都導到同一台tomcat上. 這當然不是非常好的辦法, 還好在那時候有找到一篇文章, 說的就是怎麼用terracotta在EC2上架tomcat cluster. 在那之前我就有聽過terracotta, 但是沒有用過, 只覺得terracotta似乎是很有趣. 正好這是個不可多得的好機會來試試terracotta, 雖然terracotta的網站說的比扯鈴還扯, ㄟㄟ…是比傑克還神奇, 什麼true linear scalability, transparent clustering, 但是沒有實際使用過怎麼知道呢? 好的, 以下我們就一步一步, 用terracotta建立tomcat cluster吧!

建立terracotta大軍

萬事起頭難, 先下載Terracotta咩! Terracotta滿討厭的一點就是下載點不公開, 一定要網頁點點點, 它才給你一個很快就失效的URL (其實是放在S3上面, 這個技巧我以後來介紹一下). 而且terracotta的網站改了好多次, 產品名字也換來換去, 連結也換來換去, 搞得我好亂啊! 目前這個下載頁面, 是可以用的啦. 安裝terracotta, 有installer和tar兩種, 我都是用tar 解壓的, 因為只要解壓就裝好了咩. 所以我選”terracotta-3.2.1.tar.gz” 那個下載連結. 下載好以後, 就是安裝步驟:

$ sudo tar zxf terracotta-3.2.1.tar.gz

我是把他丟在/opt 下面, 然後做一個link 叫tc, 所以我的terracotta的安裝目錄就是/opt/tc.

$ sudo ln -s /opt/terracotta-3.2.1 tc

然後要做一個叫作boot jar 的東西:

$ cd tc/bin
$ sudo ./make-boot-jar.sh

2010-03-12 12:13:54,961 INFO - Configuration loaded from the Java resource at '/com/tc/config/schema/setup/default-config.xml', relative to class com.tc.config.schema.setup.StandardXMLFileConfigurationCreator.
2010-03-12 12:14:03,960 INFO - Creating boot JAR at '/opt/terracotta-3.2.1/bin/../lib/dso-boot/dso-boot-hotspot_linux_150_16.jar'...
2010-03-12 12:14:04,360 INFO - Successfully created boot JAR file at '/opt/terracotta-3.2.1/lib/dso-boot/dso-boot-hotspot_linux_160_18.jar'.

要記得這個boot jar 的位置, 等一下會用到. 現在來設定tomcat servers. terracotta在 3.0版本以後有別的方法可以設定, 我還是用以前的作法, 直接在java process 給system properties. 先來編輯$TOMCAT/bin/startup.sh, 修改JAVA_OPTS:

export JAVA_OPTS="-Xbootclasspath/p:/opt/tc/lib/dso-boot/dso-boot-hotspot_linux_160_18.jar -Dtc.install-root=/opt/tc -Dtc.config=localhost:9510 $JAVA_OPTS"

-Xbootclasspath/p: 後面跟的就是boot jar的位置. tc.install-root 就是terracotta的安裝目錄, tc.config是terracotta的設定檔位置, 可以用file path, 但是建議要用ip:port的寫法, 讓每個terracotta client 去找terracotta server 要設定檔.

然後是一些煩人的東西. 如果你有用G1GC, (我就是其中之一…(汗)), 很抱歉, terracotta還不支援G1GC! 移掉這個! -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

如果你是用 java 1.6.0_18, (我還是其中之一…(大汗)), 要再加上:

-XX:+MustCallLoadClassInternal

這是什麼東西我也不知道, 反正terracotta和java 1.6.0_18 氾沖就對了. 然後就是terracotta的重頭戲了, terracotta的設定檔, 我把他取名tc-config.xml, 放在/opt/tc 下面:

tc-config.xml




  
    
      %(user.home)/terracotta/server-data
      %(user.home)/terracotta/server-logs
    
  

  
    %(user.home)/terracotta/client-logs
    
      
    
  

  
    
      
        tc
      
    
  

主要是分成3塊: , , . 重點是加 tc. 因為我把web application取名tc, 所以要填入tc. 然後因為我用tomcat 6.0, 所以要寫說要用tomat 6.0 的TIM(Terracotta Integration Module). 寫好了之後就下載tim.

$ cd /opt/tc
$ sudo bin/tim-get.sh install-for tc-config.xml

Terracotta 3.2.1, as of 20100302-130324 (Revision 14673 by cruise@su10mo5 from 3.2)

Parsing module: tim-tomcat-6.0:latest
Installing tim-tomcat-6.0 2.1.1 and dependencies...
INSTALLED: tim-tomcat-6.0 2.1.1 - Ok
INSTALLED: tim-tomcat-5.5 2.1.1 - Ok
INSTALLED: tim-tomcat-common 2.1.1 - Ok
SKIPPED: tim-session-common 2.1.1 - Already installed
SKIPPED: tim-distributed-cache 1.3.1 - Already installed
SKIPPED: tim-concurrent-collections 1.3.1 - Already installed

Done.

都OK了, 就可以開terracotta server了!

$ sudo bin/start-tc-server.sh -f /opt/tc/tc-config.xml
2010-03-12 12:53:05,308 INFO - Terracotta 3.2.1, as of 20100302-130324 (Revision 14673 by cruise@su10mo5 from 3.2)
2010-03-12 12:53:06,066 INFO - Configuration loaded from the file at '/opt/tc/tc-config.xml'.
2010-03-12 12:53:06,416 INFO - Log file: '/root/terracotta/server-logs/terracotta-server.log'.
2010-03-12 12:53:09,073 INFO - Available Max Runtime Memory: 496MB
2010-03-12 12:53:16,431 INFO - JMX Server started. Available at URL[service:jmx:jmxmp://0.0.0.0:9520]
2010-03-12 12:53:17,517 INFO - Terracotta Server instance has started up as ACTIVE node on 0:0:0:0:0:0:0:0:9510 successfully, and is now ready for work.

我是每次都用-f去指定設定檔的位置, 以免搞錯. 然後看一下log裡面的configuration file是不是讀到對的. 然後看到ready for work就是開好了. 現在可以開tomcat servers了.

$ sudo /opt/server1/startup.sh
$ sudo /opt/server2/startup.sh

2010-03-12 12:54:20,998 INFO - Terracotta 3.2.1, as of 20100302-130324 (Revision 14673 by cruise@su10mo5 from 3.2)
2010-03-12 12:54:22,306 INFO - Configuration loaded from the server at 'localhost:9510'.
2010-03-12 12:54:23,013 INFO - Log file: '/root/terracotta/client-logs/terracotta-client.log'.
2010-03-12 12:54:30,986 INFO - Connection successfully established to server at 127.0.0.1:9510

可以發現tomcat的開機訊息多了terracotta的東西! 看一下configuration 是不是去terracotta server 讀設定檔. 現在終於到了重要的一刻了, 來試試咩!

一樣, 依次開兩個chrome來看看!

http://localhost:8080/tc/count http://localhost:8081/tc/count

感動! 現在這兩台tomcat 已經合為一體了! (我發誓! 我絕對不是refresh 按兩下去抓圖的!)

開始的結束

用Java 的好處是有很多免費的東西可以用. 有時候太多也是很麻煩, 不知道要用哪一個. 最有名的例子應該就是Java servlet用的MVC framework吧! 我記得至少有40種可以用… 搞到最後大概還是回去用struts, 一方面也是大家用最久最習慣, 一方面也是資源比較多. 後來有一陣Ajax的旋風, 那些MVC framework又馬上就過時了, 因為programming model都不太合. 所以累的地方就是要一直學新的東西咩! 這樣也好啦, 多充實一下自己才不會一下就被人幹掉了. 剛剛我很快的用terracotta, 弄完一個最簡單的tomcat cluster, 但是scalability, HA, performance這些議題是沒完沒了的. 以後我再慢慢把一些經驗寫出來.

Resources

用EC2作一朵雲

| Comments

AWS的中心: EC2

Amazon Elastic Computing Cloud (EC2), 和S3同樣是AWS裡面最早的成員, 它的複雜性和功能性都是最高的. 從EC2推出以來, 功能一直不斷更新, 變強大. 現在更是cloud computing界的領導者. EC2是一種Infrastructure as a service(IaaS), 提供你on-demand computing power. 當我需要10台機器時, 我只需要透過EC2的API去啟動, 沒多久(現在大多小於30 sec), 我就有10台機器可以用了. 當我只需要3台機器時, 我可以把其它7台關掉, 就不用付這7台的錢. EC2可以說是AWS的核心功能了, 直接依附在EC2上的AWS其它服務就有 Amazon Elastic Block Store(EBS), Amazon CloudWatch, Amazon Auto Scaling, Amazon Elastic Load Balancing, Amazon Elastic MapReduce, Amazon Virtual Private Cloud(VPC). 其它的Amazon Simple Storage Service(S3), Amazon Simple Queue Service(SQS), Amazon Relational Database Service(RDS), Amazon SimpleDB, 也是圍繞在EC2週圍, 和EC2高度合作. EC2現在支援Linux與Windows, 也有許多付費軟體可以使用, 還有多種 instance types, 及regions. 功能真多啊! 還在一直更新, 文件看都看不完! 好吧, 工程師是不會被幻覺嚇倒的, 現在來看看怎麼用EC2實現雲端運算.

人造雲的工具

EC2也使用REST, SOAP界面, 所以也是有很多API和GUI咩! 照例我來介紹一些工具.

  • Amazon EC2 API Tools 是Amazon出的, 可以在命令列下指令, 每當EC2有新功能時, 這個tool也會同步更新. 是我最常用的.
  • Amazon EC2 AMI Tools 是Amazon出的, 這是用來建立Amazon Machine Image(AMI)的. AMI是啟動新instances時的範本, 你可以把他想像成是整個系統備份出來的影像檔, 開instances時就是把AMI還原回去, 就是一台機器了.
  • AWS Management Console 是Amazon出的web application. 不用安裝東西就可以操作EC2, 幾乎所有操作都可以完成. 是不愛打字的人的福音啊!
  • Elasticfox 是Firefox plugin, 大概從AWS Management Console出了之後就沒用過了. 如果要填secret key還是填給Amazon比較沒問題您說是吧! (前一陣子Firefox才發佈說有幾個plugin是惡意的說, 愛注意啊!)
  • jclouds 前一篇有提過的jclouds, 一樣也是再等他文件多一點再用.

等一下我還是用EC2 API Tools來說明(沒錯!! 我還是懶得抓圖!! 本blog以圖少著稱!!). AWS的強項就是所有功能都有API, 在AWS Management Console按一按就能把機器開好, 多沒成就感! 這樣怎麼能顯得出工程師的厲害咧? 所以我們還是用command工具吧!

安裝EC2 API Tools

許多EC2工具都要用private key 和certificate, EC2 API Tools也是一樣. 你可以按照以下的步驟取得它們. 先到http://aws.amazon.com/, 先點選”Account”那個tab, 再點選”Security Credentials”. 如果你還沒有AWS帳號, 就先看這一篇建立一個. 在”Access Credentials” 那一區, 點選”X.509 Certificates”那個tab, 勇敢的按下”Create a New Certificate”按鈕吧! 分別按”Download Private Key File” 及”Download X.509 Certificate”按鈕, 下載這兩個檔案, 下載好就可以按”close”. 兩個檔案名稱會長得像這樣: cert-AZO6NISCCNOM3FQLCJAJADEYC7HLLWH5.pem
pk-AZO6NISCCNOM3FQLCJAJADEYC7HLLWH5.pem

其中private key(pk-*.pem)那個檔案, 如果不下載就沒機會再下載了(嚇! 這是一生一次的機會啊!), 只能再產生新的啦. 這兩個檔案也是要保存好.

現在可以下載EC2 API Tools了. 因為這是java的library, 所以裝之前要先有java哦.

$ wget http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip
$ unzip ec2-api-tools.zip

解壓好出現一個目錄: ec2-api-tools-1.3-46266, 1.3-46266 是ec2-api-tools的 version/release numbers, 你的可能會不一樣.

$ cd ec2-api-tools-1.3-46266

有幾個環境變數要設:

JAVA_HOME=$java-dir
EC2_HOME=$ec2-api-tools-dir
PATH=$PATH:$ec2-api-tools-dir/bin
EC2_PRIVATE_KEY=~/.ec2/pk-AZO6NISCCNOM3FQLCJAJADEYC7HLLWH5.pem
EC2_CERT=~/.ec2/cert-AZO6NISCCNOM3FQLCJAJADEYC7HLLWH5.pem

設好了之後, 試試看有沒有動靜

$ ec2-version
1.3-46266 2009-11-30

EC2 instances的位置由regions與availability zones來分層. regions是由地理位置分隔, 如US, EU. availability zones是在region之內的小分區, 不會被同region內的其它availability zones失效而影嚮到. 你可以把他想成是機房代號. 同一region內的instances在network latency比較低. 現在來看看EC2有哪些regions:

$ ec2-describe-regions
REGION  eu-west-1       ec2.eu-west-1.amazonaws.com
REGION  us-east-1       ec2.us-east-1.amazonaws.com
REGION  us-west-1       ec2.us-west-1.amazonaws.com

可以看到有3個regions的名字, 以及它們的service endpoints. 那來看看有哪些availability zones:

$ ec2-describe-availability-zones
AVAILABILITYZONE        us-east-1a      available       us-east-1
AVAILABILITYZONE        us-east-1b      available       us-east-1
AVAILABILITYZONE        us-east-1c      available       us-east-1
AVAILABILITYZONE        us-east-1d      available       us-east-1

可以看到us-east-1 下面有4個availability zones, 那我想要看看eu-west-1有哪些availability zones:

$ ec2-describe-availability-zones -U https://eu-west-1.ec2.amazonaws.com
AVAILABILITYZONE        eu-west-1a      available       eu-west-1
AVAILABILITYZONE        eu-west-1b      available       eu-west-1

目前eu-west-1 下面有2個availability zones. 如果我都是一直在eu-west-1工作, 那我可以設一個環境變數

EC2_URL=https://eu-west-1.ec2.amazonaws.com

這個service endpoint URL 的規則就是https://$REGION_NAME.ec2.amazonaws.com 另外, EC2_PRIVATE_KEY, EC2_CERT, EC2_URL這三個環境變數如果不設, 也可以每次下指令時用參數去指定.

-K, --private-key
-C, --cert CERT
-U, --url URL

還有一個特別的參數 --region , 它會override -U 和 EC2_URL 環境變數. 給的方法就是:

--region $REGION_NAME

看看有開了幾個instances(當然是還沒有半個)

$ ec2-describe-instances

天邊的一朵雲

想要生一朵雲出來, 得先有一份可以用的AMI. 說到這個AMI啊, 也是一門藝術了(哈哈! 難的東西我都先說是藝術), 以後再提怎麼作自己的AMI啦. 我用早期的ec2-ami-tools有一些問題, 在作AMI的過程中常常會失敗(也有可能是我技術太差!@#), 現在就比較好用了. AMI有分public和private的, 還有分免費和付費的. 我就先用別人作好的AMI來造第一朵雲啦. Amazon Developer Resources上有很多免費的public AMIs. 我選了Fedora Core 8, 32-bit, 有先裝 Apache的AMI, 它的AMI id是ami-60da3d09, 先把它記下來. 因為現在是第一朵雲, 為了等一下用ssh連進去, 我們要先產生ssh用的key file.

$ ec2-add-keypair mykeypair
KEYPAIR mykeypair   f3:10:0b:98:3c:6b:89:b1:11:51:fc:de:0f:b6:52:7c:cc:1d:53:8a
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAmdp6bIiTdZRYfB6rBx6vXYeAyNPZnZcZVGoA/zoa53cQ/G92pl4zEWzVlvyR
.
略...
.
Ot+c8poWUu7Lxvrgx9RiCtJZN1UzaCWJQqno/0ufvMUmENZXHiNWtqD4bnAV+bZN4eI=
-----END RSA PRIVATE KEY-----

把—–BEGIN 到 —–END 那幾行存成mykeypair.pem

經過重重難關, 終於可以生一朵雲了!

$ ec2-run-instances ami-60da3d09 -k mykeypair -g default -z us-east-1a -t m1.small
RESERVATION     r-7430c31d      924417782495    default
INSTANCE        i-ae0bf0c7      ami-60da3d09 pending mykeypair   0    m1.small    2008-03-21T16:19:25+0000        us-east-1a

-k 這個選項是指定要用哪個keypair, 建議一定要給啊! 等一下就可以用key file登入這台機器. -g 這個選項是指定instances所在的security groups, 可以不給, 但是這個選項對管理instances很重要, 建議每次一定要給. 你可以把它想成是iptables. 這個選項可以指定多次, 讓這些instances 屬於多個security groups. 這也是一生一次的機會, 指定就不能改了. 一開始會有一個security group 叫default, 所以先用它咩. -z 是指定availability zone, 也是可以不給, 但是建議每次一定要給. 如果不給的話EC2會在region內自動選一個availability zone. -t 是指定instance type, 不給就是最小的機器(m1.small), 也是建議每次寫清楚. 如果你有看EC2的文件的話, 他的示範指令是一次開20個instances, 真是豪氣啊!! 再加上用High-Memory Quadruple Extra Large, 錢就燒得很快了.

$ ec2-run-instances ami-60da3d09 -k mykeypair -g default -z us-east-1a -n 20 -t m2.4xlarge

好,看一下剛剛EC2傳回的資訊: 可以看到instance-id(i-ae0bf0c7), 所用的AMI (ami-60da3d09), status (pending), key pair (mykeypair), 序號(0) 如果一次開多個instances, 序號就會遞增下去, instance type (m1.small), 開的時間, 還有所在的availability zone (us-east-1a). 現在來查看這個instance 開好了沒:

$ ec2-describe-instances i-ae0bf0c7
RESERVATION     r-7430c31d      924417782495    default
INSTANCE        i-ae0bf0c7      ami-60da3d09 ec2-67-202-7-236.compute-1.amazonaws.com        ip-10-251-31-162.ec2.internal   running mykeypair     0               m1.small        2010-02-10T16:19:25+0000  us-east-1a

好了, 狀態是running 了, 而且多了domain name的資訊. ec2-67-202-7-236.compute-1.amazonaws.com 拿去查DNS的話就是67.202.7.236 (很沒創意但是很方便), ip-10-251-31-162.ec2.internal 則是只能在EC2內查, 會得到private IP. 目前新開的instances都會有一個動態public IP, 如果要固定IP, 要用 Elastic IP 來解決, 這類管理的問題後以再提咩. 關於得到新開的instances的資訊(如public IP)還有別的方法, 也是可以由API得到, 也是以後再說咩.

胡搞瞎搞

EC2 instances開好了, 也開始扣錢了, 可是怎麼證明我有一台機器咧? 現在要開始設定security groups了. 把port 80 和世界接軌吧!

$ ec2-authorize default -p 80 -s 0.0.0.0/0

看看目前的security group設定: (這個命令沒有s, 害我常打錯! 厚~真煩)

$ ec2-describe-group
GROUP   102200112200    default default group
PERMISSION      102200112200    default ALLOWS  tcp     80      80      FROM    CIDR    0.0.0.0/0
PERMISSION      102200112200    default ALLOWS  all                     FROM    USER    102200112200    GRPNAME default

好的, 打開chrome(Firefox也行, IE6的話…我只能說您的耐心真好啊!), 打入你的instance的IP, 應該會看到apache 的 It works! 咩. 好啦, 光明正大的從大門進去怎麼能滿足宅男工程師呢, 當然要試試走後門啦!

$ ec2-authorize default -p 22 -s $your-public-ip-address/32
$ ssh root@67.202.7.236 -i mykeypair.pem

$your-public-ip-address 是你的public IP不是instance的IP, 別搞錯了.

看看instance storage容量:

$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1             8.0G  610M  7.0G   8% /
varrun                854M   48K  854M   1% /var/run
varlock               854M     0  854M   0% /var/lock
udev                  854M   20K  854M   1% /dev
devshm                854M     0  854M   0% /dev/shm
/dev/sda2             147G   28G  112G  21% /mnt

instance storage 以前叫ephemeral store, 因為instances 一關掉, 資料就消失在空氣中了. 關於storage還有很多花樣, 也是後以再提咩.

如果你很有四海一家的精神, 願意把錢花在 找外星人, 幫忙算算蛋白質, 或是計算地球氣候變化. 那你就可以把你的instances加入他們的grid了! 我沒有那麼崇高的理想咩, 因為我現在主要是作網站架構, 所以我的目標就是把系統設計成可以像他們一樣的有彈性, 這樣可以依工作量來調配系統資源. EC2給了我這個可能性! 好了! 離題了. 最後記得砍掉啊!

$ ec2-terminate-instances i-ae0bf0c7

每個人心中都有一朵雲

cloud computing是最近最熱門的話題, 連報紙都可以看到”台灣雲端元年”這個詞, 但這對既有的系統架構是全然不同的概念. 把現有系統搬到EC2上面是很簡單, 這看起來就像是本來是用實體機器, 現在改成用virtual machine來跑. 但是這並不代表現有系統不用作任何改變, 在雲端的系統應該有適合的系統架構. 以前被視為可靠(事實上, 一掛就死得很慘)的intranet, storage, 現在在cloud computing上都變成了internet, ephemeral storage. 設計這樣的系統是一大挑戰, 但是能讓你的系統更有彈性, 不怕任何一台機器掛掉, 還可以快速的, 動態的調配資源. (哈哈, 這是最高目標啦!)

開始用S3

| Comments

S3是什麼?

Amazon Simple Storage Service(S3) 是Amazon Web Service (AWS) 裡最早開始的服務之一. 雖然名字裡有一個Simple, 但是S3卻是一點也不簡單的服務! S3讓你任意的從internet上儲存, 讀取資料, 不用擔心硬碟爆掉, 還有server掛掉的問題. 簡單介紹完, 馬上來看看怎麼開始用S3.

申請AWS 帳號

因為這是有關AWS的第一篇文章, 所以我先走一次申請AWS的流程囉. 先到 http://aws.amazon.com/ , 點選 “Sign up for a free Amazon Web Services Account”. 你應該已經有Amazon的帳號了吧? 蝦米? 還沒有? 趕快建立一個吧! 如果是公司要用的就建立一個公司的帳號吧! 有Amazon帳號就打密碼, 再按”Sign in using our secure server”. 現在可以到 http://aws.amazon.com/s3 的網頁了, 再點選 “Sign Up For Amazon S3”, 這一頁就是要你填信用卡資料而已啦,  我知道你也是個無怨無悔為公司奉獻的員工, 但是也不要填入你的卡號啊! 公司應該有信用卡吧, 沒有的話趕快去生一張咩!

取得Keys

使用S3需要Access Key ID 及 Secret Access Key. 連到http://aws.amazon.com/, 選”Account”, 再選”Security Credentials”, 在”Access Key” 的tab那邊, 就可以看到你的這兩個key啦! secret access key 一定要安全的保管, access key id 則是用來辦別你是用哪一個secret access key的, 所以比較沒有關係.

選擇client

因為是在雲端裡, AWS的服務都有提供SOAP和REST兩種界面. 所以S3的client真是百百種啊! 好用不好用真的參差不齊, 以下是我的經驗囉!

  • S3fox 是firefox plugin, 有firefox就可以用, 方便你用GUI去操作, 最快上手.
  • jets3 用java寫的. 有API 也有GUI. 有完整實作S3的功能, 可是我嫌它有點肥, 好像java的library常常會這樣吼.
  • s3sync 用ruby寫的. 是我最常用的啦! 因為在shell 裡有時要傳個檔案還是懶得開GUI, 直接打指令就可以了, 好像很久沒更新了, 不過好用就好.
  • jclouds 也是用java寫的. 這套API是我覺得寫得最棒的! 但是這個project還很新, 很多文件都沒有, 所以我還在密切注意中!

至於我在開發的時候, 是用自己寫的library去使用S3 REST的界面啦, 因為我覺得java 的S3 library都不是很好用吔. 也許以後jclouds更成熟, 我就會改用他囉! 以下我就用最常用的s3sync來示範啦(其實是我懶得抓圖啦!). 先下載s3sync:

$ wget http://s3.amazonaws.com/ServEdge_pub/s3sync/s3sync.tar.gz
$ tar zxf s3sync.tar.gz
$ cd s3sync
$ mv s3config.yml.example s3config.yml

編輯s3config.yml

$ vim s3config.yml

把前兩個改成你的access key 和secret access key囉, 第3個砍掉就可以了!

aws_access_key_id: 11111111111111111111111
aws_secret_access_key: 222222222222222222222
ssl_cert_dir: /home/user/s3sync/certs

然後看一下README.txt 囉! 主要是告訴s3sync去哪裡找到設定, 我都是用:

$ export S3CONF=$我的s3sync安裝目錄

當然要有ruby啦! 沒有的話就裝一下咩!

$ sudo apt-get install ruby ruby1.8 libruby1.8 libopenssl-ruby libopenssl-ruby1.8

操作buckets

S3的兩個組成就是bucket和object. bucket就是S3裡面的最上層分類, 所有的objects 都是放在bucket裡, 一個bucket 可以放無限個objects, bucket name 在S3裡是唯一的. 一個帳號可以建立100個buckets, 不過相信我, 你不需要那麼多, 多了反而難管理. 一般來說就是以每一個application/domain 開一個bucket就夠了. bucket name 的限制是:

  • 3 ~ 255 個字, 可包含英文字母, 數字, periods(.), dashes(-), underscores(_)
  • 要數字或字母開頭
  • 不可長得像IP (192.168.1.1)

但是為了virtual hosting 的功能, 最好是符合以下的額外條件:

  • 3 ~ 63 個字, 可包含小寫字母,數字, periods(.), dashes(-)
  • 不可dashes(-)結尾, eg: test-
  • 不可兩個periods(.)相連, eg: test..test
  • 不可periods(.)和橫線(-)相連, eg: test-.test , test.-test

virtual hosting可以很方便的access你的object, 例如我有一個bucket叫mysecret, 裡面有一個object 叫good.avi, 那這個object的URL就是

http://mysecret.s3.amazonaws.com/good.avi

或是用SSL的

https://mysecret.s3.amazonaws.com/good.avi

如果bucket name 不符合virtual hosting 的要求就只能用下面這種URL囉!

http://s3.amazonaws.com/my(秘)/good.avi

如果你很有分享的精神的話, 把good.avi設成public read, 那我可以在browser 直接打上面的URL去讀取到, 很方便的. 和bucket有關的還有location, access control, DNS caching, redirection等議題, 以後再討論囉! 現在來建立bucket了:

$ ./s3cmd.rb createbucket mysecret

如果你得到409 Conflict, 那就是這個bucket name已被別人用囉, 再想一個吧!

看看自己有哪些buckets:

$ ./s3cmd.rb listbuckets

看看mysecret裡有什麼objects?

$ ./s3cmd.rb list mysecret

關於listing objects 這個也是可以搞得很複雜啊! 以後再討論囉!

操作objects

object是用key 去識別的. object key在bucket裡不重覆就可以了, object key就不像bucket name有那麼多限制了, 可以是1 ~ 1024個UTF-8字元, 但是為了管理和使用上的方便, 取名就是一門藝術了, 這個議題也先擱著. object value就是你存的東西, 大小限制是 5 GB. (不錯吧! 剛好可以讓你放一整張DVD). 和object有關的還有key listing, metadata, 和access control等議題, 也是以後再討論囉. 現在該傳些好的東西和好朋友分享了.

$ ./s3cmd.rb put mysecret:good.avi /pathto/good.avi Content-Type:video/avi x-amz-acl:public-read

因為bucket和object 預設都是private 所以要特別說我要public read, 而為了日後自己的方便, Content-Type最好自己加上去, Content-Length則是s3sync會幫你加, 這在你只想偷窺(peek)一下這個物件是什麼的時候很好用, 而不用整個拿下來.

現在, 可以打開你最愛的browser, 打入網址:

http://mysecret.s3.amazonaws.com/good.avi

登登! 可以看到了! 但是怕被人發現, 還是砍掉吧!

$ ./s3cmd.rb delete mysecret:good.avi

bucket也一並砍掉重綀了, 反正只是先玩玩. bucket裡面有object的話要先砍光, 否則會失敗哦!

$ ./s3cmd.rb deletebucket mysecret

結語

你可能會說S3有什麼了不起? 有很多on-line storage services啊! 是沒錯, 但是跟其他付費的on-line storage比較的話:

  • S3有SLA, 比較可靠.
  • S3的下載速度還不錯. 如果從EC2讀取又更快了, 數據以後再整理上來.
  • 一個object 大小可以到5GB
  • 有unique URL可以直接access! 打死一堆storage services. 而且這URL還可以自定的.
  • 可以用Cloud Front 加快client下載的速度.
  • 有開放低階的REST, SOAP, 也有許多程式語言的API, GUI可用
  • 有支援BT下載, 但我沒試過

當然也不是沒有缺點啦, 最大的當然就是要花$囉! S3適合放靜態檔案, 像是圖檔, 影片檔(怎麼都是宅男的最愛), js/css/html也是不錯, 但是要處理版本的問題. 大的檔案, 文件等等都適合. 一些常改的資料就不要放在S3了, 一直讀讀寫寫效率是很差的. 善用S3的話可以解決很多資料存取的問題.