2014年4月29日 星期二

AWS 筆記 - Amazon EC2 Auto Scaling 與 Elastic Load Balancing

整體流程:
  1. 建立 My AMI (www-service-auto-scaling-ami)
    • 順便準備一些會提升 CPU 使用率的程式
  2. 建立 ELB 規則 (www-service-auto-scaling-elb)
  3. 建立 Auto Scaling 規則
    • 建立 Launch 機器的規則 (www-service-auto-scaling-launch-conf)
    • 建立 Auto Scaling 規則 (www-service-auto-scaling-group)
      • 建立 新增機器 Alerm 規則 (CPU 平均高於 50%)
      • 建立 減少機器 Alerm 規則 (CPU 平均低於 30%)
首先,建立 My AMI 是因為開機器時要以自己的服務為主



建立 Elastic Load Balancing 規則,因為到時候打算對 ELB 新增機器,而非對 EC2,此外,這時建立 ELB 時,可以不用套用在任何機器上



點選建立 Auto Scaling 規則,但在這之前需要設定 launch 機器規則,例如要挑哪個 AMI 等:












設定 launch 規則後,正式進入 Auto Scaling 規則,這邊主要需設定新增機器、降低使用機器的條件,也可以設定 email notification 通報機器增減訊息等。












當 Auto Scaling Group 設定完後,將會立即依照設定開啟機器(同理刪除 Auto scaling group 也就會把機器都關掉),例如設定為最少2台,那就會馬上開2台出來。接著,可以在 ELB 或 Auto Scaling 頁面觀察機器狀態,其中在後者還能更新開關機器的條件,並且把上執行等。











 

至於如何測試自否自動 Scaling 的部分,此例我是搭配 ELB 測試,對指定網址瀏覽時,除了顯示 /etc/hostname 資訊來測試是否有不同外,還透過 CGI 執行一隻背景程式來讓 CPU 使用率衝到 100% ,透過這樣的做法,即可以觀察 Auto scaling 是否正常運行,亦可翻閱 Auto scaling history 查看更動。

<?php
shell_exec( 'echo "<?php while(1) ; " | php > /dev/null 2>&1 &' );

@date_default_timezone_set("Asia/Taipei");
$current_datetime = @date('Y-m-d H:i:s', @time());
echo "Service @ $current_datetime:".file_get_contents('/etc/hostname')."\n";

AWS 筆記 - 使用 Amazon Elastic Load Balancing 與 SSL/HTTPS (GoDaddy) 設定



首先,先開一台 EC2 機器,架設一下 HTTP/HTTPS,設定完就建一個 AMI 保存起來,再從 My AMI 再多開一檯出來(記得要擺在同一個 Availablility Zone才行),變成有兩檯 EC2 機器正在運行。此外,若 SSL 憑證有第三方簽證,而對於 EC2 上的機器,其 SSL 憑證可以不必用第三方簽證,只要在 Elastic Load Balancer (ELB) 上頭是第三方簽證的就夠用了!讓管理方便許多。

接著設定 ELB 吧,比較需要留意是 SSL 的設定,其中 DNS 跟 SSL 憑證是委託 GoDaddy 維護的,所以先從 GoDaddy 取得 SSL 憑證吧,大概會有三個檔案:
  • xxxxxx.crt
  • gd_bundle-xxxx.crt
  • xxxxxx.key



此時在填寫資料時,在 Public Key Certificate 就是 xxxx.crt ,而 Certificate Chain 就是 gd_bundle-xxxx.crt ,比較麻煩一點的是 Private key 那塊,需要稍微轉換 xxxxx.key

$ openssl rsa -text -in *.key

再把 -----BEGIN RSA PRIVATE KEY----- 到 -----END RSA PRIVATE KEY----- 裡的資料貼上即可。如此一來即可完成 SSL 設定。其他的步驟就沒什麼難的。



設定要用來監控判斷機器狀況的檔案:





挑兩檯機器以上吧:






設定好後就會得到一個網址可以連,此網址就會動態調整 requests 到數檯機器上:



此外,若有機器 out of service 時,也能觀測或動態刪減,十分方便:



其他筆記:
  • 關於 SSL / HTTPS 的部分,記得去申請個 CNAME Record 來對應到 ELB 的網址,如此一來,使用者逛網頁時就不會彈跳出不會彈跳出憑證問題
  • 關於如何測試 ELB 到底有沒有動態調整 requests 的部分,建議可以寫一隻 PHP 讀 /etc/hostname 出來,接著就可以透過 ELB 網址瀏覽,觀察讀出來的 hostname 是否有在變化

    $ cat index.php
    <?php
    @date_default_timezone_set("Asia/Taipei");
    $current_datetime = @date('Y-m-d H:i:s', @time());
    echo "Service @ $current_datetime:".file_get_contents('/etc/hostname')."\n";

AWS 筆記 - 查詢 Amazon RDS Disk Space 硬碟空間使用情況


AWS Console -> RDS -> Instances -> choose an instance -> Show Monitoring -> Freeable Sapce (MB)

此例是建立 300GB RDS,還剩 284053 MB 可用。還可以查看兩星期內的空間使用變化。

2014年4月28日 星期一

AWS 筆記 - 使用 Amazon EC2 以及建立自己的 AMI

老實說,已經有 4 年沒摸 EC2 了 XD 上去逛了一下,整個界面都不一樣了,慶幸地使用流程跟 4 年前差不多,連建立 AMI 的部分也是如此。

建立 Ubuntu 14.04 機器一檯:

Step 1:



Step 2:



Step 3:



Step 4:



Step 5:



Step 6:



建立 AMI:

Step a:



Step b:



接著,開機器時,可以從自己的 AMI 開一檯機器出來:

[Linux] Apache/2.4.7 [authz_core:error] : client denied by server configuration @ Ubuntu 14.04

開始在 AWS 上試用 Ubuntu 14.04 了,結果安裝完碰到這問題 XD 說真的有好一陣子沒有用 apache web server ,為了方便 deploy 跟 server 管理,就又改用 apache 了

關鍵解法:
Require all granted
範例:

$ sudo apt-get install mysql-client php5 apache2
$ sudo mkdir -p /data/dev
$ sudo vim /etc/apache2/conf-available/dev.conf
Alias /dev /data/dev
<Directory /data/dev>
        Options FollowSymLinks
        DirectoryIndex index.php
        AllowOverride None

        Require all granted
</Directory>

$ sudo a2enconf service-dev
$ sudo service apache2 restart

2014年4月27日 星期日

使用 Graph API 得知指定 URL 在 Facebook 散播的情況

很久沒用都會忘記 Orz

透過 Open Graph:

$ curl https://graph.facebook.com/?ids=http://blog.changyy.org/ | python -mjson.tool
{
    "http://blog.changyy.org/": {
        "id": "http://blog.changyy.org/",
        "shares": 2
    }
}


透過 FQL: SELECT url,id,site FROM object_url WHERE url = 'http://blog.changyy.org'

$ curl http://graph.facebook.com/fql?q=SELECT%20url,id,site%20FROM%20object_url%20WHERE%20url%20=%20%27http://blog.changyy.org%27 | python -mjson.tool
{
    "data": [
        {
            "id": 597172713656917,
            "site": "blog.changyy.org",
            "url": "http://blog.changyy.org"
        }
    ]
}

2014年4月26日 星期六

iOS 開發筆記 - App Submission Feedback 抗戰成功的經驗


第一次跟說贏 App Reviewer ! 這種感覺真爽 XD 免得又要從來一次 Waiting For Review ... In Review... 週期...

簡言之,App Reviewer 也可能亂用 app ,雖然這也稱得上 UI/UX 設計不良,但為了避免延遲上架時間,有信心說贏就去解釋吧!

若是 app 操作讓 App Reviewer 認為是 bug 時,簡易做法:
  • 提供 Step by step 的操作步驟
  • 搭配 Screenshot (只能上傳最多四張)
如此一來,App Reviewer 發現這不是程式問題而是操作流程誤解時,就有機會翻盤了。當 Reviewer 認同之前的退件理由是個誤會時,整個 App status 流程就會從原本的 Reject 狀態 New App Submission Message -> Wait for review -> In Review 瞬間轉換,接著有幸的話就變成 Processing for App Store 啦!並且在 Resolution Center 中看不會保留此次被 Reject 的記錄。

iOS 開發筆記 - Facebook SDK 與 App Reviewer 無法登入 FB 問題的處理心得



經過幾番測試,發現有些 iOS App Reviewer 無法正常登入 Facebook ,因此,假使你的 app 一開始就需要登入 FB 的話,很有可能會莫名其妙地收到 App Submission Feedback 的信件通知 Orz 然後百般跟 Reviewer 說會不會是他自己無法連到也沒法解決,千篇一律地收到制式回應,最後為了降低等待時間,就是重新上傳 binary 等待下一個 App Reviewer 了

故最佳解就是先限制 app 可以使用的地區,例如美國等,以此避免某些 App Reviewer 所在的地區不能連 Facebook !

2014年4月23日 星期三

AWS - 使用 Amazon RDS - MySQL Replica 筆記



體驗 Amazon RDS 與 MySQL Replica 運作模式,有幾項心得:
  • Amazon RDS 當 Slave 時,必須改用 Amazon 自定 func 來啟動,如 mysql.rds_set_external_mastermysql.rds_reset_external_mastermysql.rds_start_replication (START SLAVE)、mysql.rds_stop_replication (STOP SLAVE) 和 mysql.rds_skip_repl_error 等
  • Amazon RDS 使用 UTC 時區,依照 MySQL Replication and Time Zones 文件所述,Master 跟 Slave 的時區須一致,因此,也調整 Master 情況,對於 Timestamp 的用法就要避免用 MySQL CURRENT_TIMESTAMP 等,建議避開透過 MySQL 管理時區,直接用程式設定 timestamp 數值。但這樣變動還滿大的。
  • 定期用 mysql> SHOW SLAVE STATUS \G 觀看,儘量不要用 SELECT count(*) FROM table 來觀看,因為會需要關注的情況通常是資料量已經很大了,而 AWS RDS $0.10 per 1 million I/O requests,一直用 count(*) 在資料量大的情況也會很可觀的。Seconds_Behind_Master 數值,可能短期不會降下來,用0.5~1天的時間間隔去觀察是否有下降即可
  • 機器要 reboot 前,記得要先用 mysql.rds_stop_replication (等同 STOP Slave) 指令,若 Seconds_Behind_Master 數值很大,通常要跑很久

    mysql> CALL mysql.rds_stop_replication;                                                                                          
    +---------------------------+
    | Message                   |
    +---------------------------+
    | Slave is down or disabled |
    +---------------------------+
    1 row in set (5 min 28.69 sec)
    
  • 假設 RDS 專門當 MySQL Replica Slave 的話,記得 Master 可以透過 binlog-ignore-db 濾掉 mysql 等 databases,不然當 Master 更動 mysql 時(例如 apt-get upgrade 有 mysql 時也會有機會碰到)也會把這些 log 記錄起來,到時後 RDS 收到就會噴錯誤訊息,而 RDS 的解法就是不斷地用 mysql.rds_skip_repl_error 略過這些更動(可以搭配 SHOW SLAVE STATUS \G 查看 Last_SQL_Error 資訊,例如:

    mysql> SHOW SLAVE STATUS \G
    ...
    Last_SQL_Error: Error 'Access denied for user ''@'' to database 'mysql'' on query. Default database: 'mysql'. Query: 'ALTER TABLE db
       MODIFY Host char(60) NOT NULL default '',
       MODIFY Db char(64) NOT NULL default '',
       MODIFY User char(16) NOT NULL default '',
       ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'
    
    mysql> CALL mysql.rds_skip_repl_error ;
    +-------------------------------------+
    | Message                             |
    +-------------------------------------+
    | Statement in error has been skipped |
    +-------------------------------------+
    1 row in set (0.05 sec)
    
    +-----------------------------------------------------------------------------------+
    | Message                                                                           |
    +-----------------------------------------------------------------------------------+
    | Slave has encountered a new error. Please use SHOW SLAVE STATUS to see the error. |
    +-----------------------------------------------------------------------------------+
    1 row in set (2.05 sec)
    
    Query OK, 0 rows affected (2.05 sec)
    
    ...
    
    mysql> CALL mysql.rds_skip_repl_error ;
    +---------------------------------------------------------+
    | Message                                                 |
    +---------------------------------------------------------+
    | Slave is running normally.  No errors detected to skip. |
    +---------------------------------------------------------+
    1 row in set (0.03 sec)
    
    
此外,對於 RDS 操作心得:
  • 開一個單位出來至少 15 分鐘起跳,從 create 到 backup 約 15 分鐘,其中 backup 是開台例行流程,以 18GB的 storage size 來說,約 3 分鐘,從 backup 換到 modifying 還要 2分鐘。
  • 從 snapshot restore 亦是如此,過程還必須重 load my.cnf 設定(因為預設不給挑 my.cnf),過程像是要再 reboot 一下,從 applying 到 pending-reboot 約 4 分鐘,當按下手動 reboot 時,兩分鐘內狀態從 pending-reboot 變成 in-sync,但 DB Instance Status 還是在 rebooting,從 rebooting 轉成 available 約 2 分鐘
  • 試過 db.t1.micro 跟 db.m1.small 做 MySQL Replica Slave 的角色,發現 DB server 資料增加量追不上?改用 db.m1.medium 了($0.115 per RDS Medium Instance hour ),穩穩地有看到 Seconds_Behind_Master 下降,但貴的不是開台的價錢,還可能是 I/O Requests 的價碼,資料要一直追,現況 12 小時約 0.5 million I/O requests ($0.10 per 1 million I/O requests)
所以從 snapshot 開一檯機器都可以用耗時約 27 分鐘,比我想像中慢了不少,測試起來真痛苦。

其他心得:
  • 別忘了確認 Master 跟 Slave 的 character,此例我是設定為 utf8,RDS 預設也是 latin1

    mysql> show variables like '%char%';
    +--------------------------+-------------------------------------------+
    | Variable_name            | Value                                     |
    +--------------------------+-------------------------------------------+
    | character_set_client     | utf8                                      |
    | character_set_connection | utf8                                      |
    | character_set_database   | utf8                                      |
    | character_set_filesystem | binary                                    |
    | character_set_results    | utf8                                      |
    | character_set_server     | utf8                                      |
    | character_set_system     | utf8                                      |
    | character_sets_dir       | /rdsdbbin/mysql-5.5.33.R1/share/charsets/ |
    +--------------------------+-------------------------------------------+
    
  • 如果未來打算把 RDS 當 Master 的話,可以留意 auto_increment_increment 跟 auto_increment_offset 的設定,可提供平順的轉換機制(可支援從 Read 變 Write)
    mysql> show variables like 'auto_inc%';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | auto_increment_increment | 10    |
    | auto_increment_offset    | 2     |
    +--------------------------+-------+
  • 建一台 RDS 個人常做設定 Parameter Groups:
    max_allowed_packet = 67108864
    sync_binlog = 1
    innodb_flush_log_at_trx_commit = 1
    auto_increment_offset = m
    auto_increment_increment = n
    collation_connection = utf8_unicode_ci
    character_set_results = utf8
    character_set_server = utf8
    character_set_connection = utf8
    character_set_database = utf8
    character_set_client = utf8
    character_set_filesystem = binary
    
  • 一般 MySQL Server Master my.cnf:
    [mysqld]
    # ...
    character-set-server=utf8
    collation-server=utf8_general_ci
    # ...
    default-time-zone       = '+00:00'
    server-id               = x 
    auto-increment-increment = y
    auto-increment-offset   = z 
    log_bin                 = /var/log/mysql/mysql-bin.log
    binlog-ignore-db = mysql
    binlog-ignore-db = performance_schema
    binlog-ignore-db = information_schema
    binlog-ignore-db = test
    innodb_flush_log_at_trx_commit = 1 
    sync_binlog = 1
    
  • 簡易 Slave 設定對應表:
    • 一般 MySQL Slave:
      mysql> CHANGE MASTER TO 
      MASTER_HOST='YourDBServerIP', 
      MASTER_USER='repl_account', 
      MASTER_PASSWORD='repl_password', 
      MASTER_LOG_FILE='mysql-bin.######', 
      MASTER_LOG_POS=#######;
      
      mysql> START SLAVE;
      
      mysql> STOP SLAVE;
      
      mysql> RESET SLAVE;
      
    • RDS Slave:
      mysql> CALL mysql.rds_set_external_master (
      'YourDBServerIP'
      , 3306
      , 'repl_account'
      , 'repl_password'
      , 'mysql-bin.######'
      , #######
      , 0
      );
      
      mysql> CALL mysql.rds_start_replication;
      
      mysql> CALL mysql.rds_stop_replication;
      
      mysql> CALL mysql.rds_reset_external_master;
      
      
  • 如果MySQL Replica Master 是 5.5.x 版,那依照 MySQL 文件在 RDS 開一台 5.6.x 當 MySQL Replica Slave 應該也行,文件出處:MySQL 5.6 Reference Manual :: 16 Replication :: 16.4 Replication Notes and Tips :: 16.4.3 Upgrading a Replication Setup When you upgrade servers that participate in a replication setup, the procedure for upgrading depends on the current server versions and the version to which you are upgrading.

    This section applies to upgrading replication from older versions of MySQL to MySQL 5.6. A 4.0 server should be 4.0.3 or newer.

    When you upgrade a master to 5.6 from an earlier MySQL release series, you should first ensure that all the slaves of this master are using the same 5.6.x release. If this is not the case, you should first upgrade the slaves. To upgrade each slave, shut it down, upgrade it to the appropriate 5.6.x version, restart it, and restart replication. Relay logs created by the slave after the upgrade are in 5.6 format.

    ...

2014年4月18日 星期五

[Linux] 修改 MySQL root 密碼 @ Ubuntu 12.04

最近開了太多檯機器,不斷地跳來跳去,就忘了兩個月前某一檯的 MySQL Root Password,找一下修改方式:

$ sudo service mysql stop
$ sudo mysqld_safe --user=mysql --skip-grant-tables --skip-networking &

$ mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD('NewPassword') where USER='root';
mysql> FLUSH PRIVILEGES;
mysql> quit;

$ sudo killall mysqld_safe
$ sudo service mysql start

[Linux] 修改 System Timezone @ Ubuntu 12.04

$ sudo dpkg-reconfigure tzdata

記得要把相關服務重開,如 cron 、 MySQL server 等,或乾脆重開機也行

$ sudo service cron stop
$ sudo service cron start

Linode - A pending free upgrade is available



2014/04/17 時,Linode 公告方案升級(所有方案升一級,最低方案剩 Linode 2G),並且提供 SSD 服務,跟朋友討論時,要點一下 Dashboard 右下角的 Upgrade,也因此試了一下。



以原先方案 Linode 4G 的機器升級,實際測試耗時約 30 分鐘,在評估一下機器中斷服務的時間吧!

2014年4月17日 星期四

淘寶國際轉運心得



有些人都會佔賣家便宜,硬要說"國內運算",當然,賣家也不是省油的燈 XD 所以大部份都要先橋好運費才能往下走,而大部分從大陸寄東西過來的快遞大概耗費 30~36RMB 的價碼(需看商品重量)

上回在 PTT 跟團買烏克麗麗,第一次體驗淘寶購物,不過,煩擾的事是由主購者處理的,所以體驗上只有在收件時要額外付快遞錢。這次則是親自使用,就試試所謂的國際轉運。

國際轉運的特色是讓賣家把東西寄到國際轉運站,所以賣家上頭標記運費多少就是多少,不必去跟賣家討價還價,畢竟到國際轉運站就一定是國內運輸。等到東西到國際轉運站後,買家在上去網站支付所國際轉運站到自己家的運費。

整體貨品訂購跟運輸流程:
  1. 跟賣家下單,請賣家送到國際轉運站
  2. 追蹤貨品何時到國際轉運站
  3. 到國際轉運站進行支付到自家運費,此時可以選超商取貨或直接送到你家
最大的優點是處理多件商品,也就是跟多位賣家下單,統一在國際轉運站集貨,再一次支付國際運費。最大的缺點就是運輸時間拉長,原先賣家用快遞送到你家可能只要 5 天就能拿到貨,現在變成 3 天到國際轉運,再 3 天等待國際轉運簽收,再 3 天進行空運,時間可能拉長到一倍不等,在國際轉運站的 status 有不少 Orz,如"待入庫"、"已入庫"、"待出庫"等,而從國際轉運運輸時,又不少狀態 orz

未來思考這種用法可以著重在:
  • 是否向有多個賣家購買物品以及多項物品的急迫性,不急的話就用國際轉運
  • 若不急著收件且想要超商取貨,那就選國際轉運吧
  • 若不急著收件且賣家支付快遞的錢(例如 36RMB) > 賣家國內快遞(7RMB)+國際轉運運費(18RMB)

2014年4月16日 星期三

AWS - 初次使用 Amazon Relational Database Service (RDS) 筆記

時間差不多了,該幫公司引入 Amazon RDS 了!首先就是先請老闆拿出信用卡註冊一個帳號,接著邀請指定的管理者進駐使用,再透過 AWS Identity and Access Management (IAM) 給予權限,而這些管理者就不需要註冊 AWS 了,並且有專屬的 login 網址。此例會接觸到 EC2 跟 RDS 這兩塊,其中 EC2 是 Security Group 的部分,因為 Amazon RDS 的登入權限是吃 EC2 裡的 Security Group,例如不限 IP 來源(0.0.0.0/0) 等。

簡單地用圖記錄,此例先用預設值:

Step 1:使用 AWS RDS


Step 2:在此選擇 MySQL


Step 3:在此使用最簡單的方案


Step 4:設定 RDS 的規格,以及 RDS 代號,以及登入的帳密


Step 5:設定 MySQL 的環境,在此先用預設,之後還可以改。並且開一個 Database,此外 Security Group 則是在規範有誰可以連到這台 DB server,這可以晚點再切換到 EC2 去設定


Step 6:使用預設備份等


Step 7:接著就會確認 RDS 規格並進行啟動啦,可以準備回到 Dashboard 觀察目前的資訊


Steo 8:接著就可以查看目前 RDS 初始化的狀態


Step 9:初始化完在 EndPoint就會顯示登入位置:


Step 10:這步不見得需要,這是切換到 EC2 的 Security Group 設定,此例是允許任何位置的 IP 連入


最後,就跟用 command line 連進一台 MySQL DB 沒兩樣囉。

2014年4月15日 星期二

[Linux] 使用 Nagios 和 nagios-nrpe-server 定期偵測系統狀況



記得上個月也摸了一下 nagios ,但後來因忙碌而中斷的 Orz 這次就專心補齊了一下。簡單的說,若是在單機上安裝,則是自我檢測的方式,若透過 nagios-nrpe-server 則可以晉升為遠端監控。

僅需挑一檯機器當 Monitor,在上頭安裝 nagios3 環境 (nagios3 server),而在其他待監控的機上,安裝 nagios-nrpe-plugin 環境,並設置可以監控它的來源、要監控的指令。

待監控的 Servers:

由於有些資源還是要從 Server 自身監控,如 Disk space、 CPU Load 等,所以透過 nagios-nrpe-server 來提供遠端查詢方式

$ sudo apt-get install nagios-nrpe-server
$ sudo vim /etc/nagios/nrpe_local.cfg
allowed_hosts=127.0.0.1,MonitorServerIP
command[check_load]=/usr/lib/nagios/plugins/check_load -w 15,10,5 -c 30,25,20
command[check_all_disks]=/usr/lib/nagios/plugins/check_disk -w 15% -c 5%
$ sudo service nagios-nrpe-server restart
netstat -at |grep nrpe
tcp        0      0 *:nrpe                  *:*                     LISTEN
$ grep nrpe /etc/services
nrpe            5666/tcp                        # Nagios Remote Plugin Executor


自我連線測試,也可以在 Monitor Server 測試指定 Server IP :

$ telnet localhost 5666

Monitor Server:

$ sudo apt-get install nagios3 nagios-nrpe-plugin

別忘了帳密在 /etc/nagios3/htpasswd.users 設定。此外,在 /usr/lib/nagios/plugins/ 就有一堆可以用的 tools ,例如監控 Google 是否正常:

$ /usr/lib/nagios/plugins/check_http -H www.google.com
HTTP OK: HTTP/1.1 200 OK - 12316 bytes in 0.057 second response time |time=0.056623s;;;0.000000 size=12316B;;;0


接著,則是定義自己的服務跟機器:

$ sudo vim /etc/nagios3/conf.d/my-server.cfg

#define host

define host {
        host_name db
        alias db.xxxx.com
        address db.xxxx.com
        hostgroups ssh-servers,remote-servers,https-servers
        use generic-host
}

define host {
        host_name www
        alias www.xxxx.com
        address www.xxxx.com
        hostgroups ssh-servers,remote-servers,http-servers,https-servers
        use generic-host
}

# define hostgroup

define hostgroup {
        hostgroup_name          mysql-servers
        alias                   MySQL DB Service
        members                 db
}

define hostgroup {
        hostgroup_name          https-servers
        alias                   HTTPS Service
        members                 db
}

define hostgroup {
        hostgroup_name          remote-servers
        alias                   Remote Server
        members                 db
}

# define service checking

define service {
        hostgroup_name          https-servers
        service_description     HTTPS
        check_command           check-https!$HOSTADDRESS!443
        use                     generic-service
        notification_interval   0 ; set > 0 if you want to be renotified
}

define service {
        hostgroup_name          remote-servers
        service_description     Remote NRPE CPU Load
        check_command           check_nrpe_1arg!check_load
        use                     generic-service
        notification_interval   0
}

define service {
        hostgroup_name          remote-servers
        service_description     Remote NRPE Disk Space
        check_command           check_nrpe_1arg!check_all_disks
        use                     generic-service
        notification_interval   0
}

# define commands

define command{
        command_name    check-https
        command_line    /usr/lib/nagios/plugins/check_http -I $ARG1$ -p $ARG2$ -S
}


$ sudo service nagios3 restart

如此一來,到 http://MonitorServerIP/nagios3 登入後,就可以觀察現況啦。以上的偵測包括 http, https, ssh, cpu loading, disk space 等,如果想要加上 mysql db service 的情況,可以試試 check_mysql_health 這支,需要額外下載:

下載 check_mysql_health 和編譯:

$ cd /tmp
$ wget -qO- http://labs.consol.de/download/shinken-nagios-plugins/check_mysql_health-2.1.8.2.tar.gz | tar -xzvf -
$ cd check_mysql_health-2.1.8.2
$ ./configure
$ make
$ sudo cp /tmp/check_mysql_health-2.1.8.2/plugins-scripts/check_mysql_health /usr/lib/nagios/plugins/


接著,撰寫相關 mysql db service checking:

$ sudo vim /etc/nagios3/conf.d/my-server.cfg

define host {
host_name db
alias db.xxxx.com
address db.xxxx.com
hostgroups ssh-servers,mysql-servers
use generic-host
}

define hostgroup {
hostgroup_name mysql-servers
alias MySQL DB Service
members db
}

define service {
hostgroup_name mysql-servers
service_description MySQL Remote Connection
check_command check-mysql-db!$HOSTADDRESS
#check_command check_tcp!-H!$HOSTADDRESS$!-p!3306
use generic-service
notification_interval 0 ; set > 0 if you want to be renotified
}

define command{
command_name check-mysql-db
command_line /usr/lib/nagios/plugins/check_mysql_health --hostname $ARG1$ --username nagios --password nagiospassword --mode querycache-hitrate --warning 90 --critica 95
}


此外,別忘了建立帳號供 monitor server 連到 db server,在 db server 上建立 nagios 帳號:

mysql> GRANT usage ON *.* TO 'nagios'@'nagios_monitor_server' IDENTIFIED BY 'nagiospassword';

[Linux] High Availability MySQL 筆記:auto-increment-increment, auto-increment-offset, my.cnf @ Ubuntu 12.04

想起來很妙,在過去累積至今 2014 年初的工作經驗上,對於處理資料儲存方面,我並非使用 SQL DB 的,結果今年一口氣摸了不少 XD 不過原理都大同小異,就順便筆記一下。

以 High Availability MySQL (MySQL HA) 為例,通常為了降低系統複雜度又要提供 HA 時,可以考慮將 Read/Write 分離,讓 Write 在某一檯機器上,但 Read 可以有一批機器,只是開發上又要留意,如果 client 有更新資料時,必須讓 client 後續的動作也在 write 那檯機器,以免 MySQL Replication 的過程還未及時,這是讀比寫大量的使用情境。

如果寫也要做 HA 時,最常碰到的問題就是每檯 server 上的 primary key collision 的問題,以兩台某 table 的 int id 為例,讓其中一檯為 2N,另一台是 2N + 1,其中 N 是第幾筆資料,同理有 10 台,那就依序為 10N, 10N+1, 10N+2, ..., 10N+9。

達成這個效果,慶幸地只需要更改 my.cnf 或動態更新環境變數即可,共有兩個參數:

$ sudo vim /etc/mysql/my.cnf

[mysqld]
# ...
# http://dev.mysql.com/doc/refman/5.5/en/replication-options-master.html
auto-increment-increment = 10
auto-increment-offset = 1

$ sudo service mysql restart


如果不想要讓 mysql restart 的話,可以透過設定 global variable 的方式:

mysql> set global auto_increment_increment=10;
mysql> set global auto_increment_offset=1;


另外,也可以查詢目前情況:

mysql> show variables like '%auto_increment%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+

mysql> set global auto_increment_increment=10;

mysql> show session variables like '%auto_increment%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+

mysql> show global variables like '%auto_increment%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 10    |
| auto_increment_offset    | 1     |
+--------------------------+-------+


需留意 session variables 代表是此時 mysql connection 的狀態,若透過 set global 變數的方式,需要重連才會看到。

透過上述 primary 的分開後,除了可以做 write HA 外(如:Master-Master 架構),其實也可以用在移機過程,例如目前有 Server 1 跟 Server 2 且 Server 1 是目前的 DB server,想要把 db 從 Server 1 移到 Server 2 時,先透過 MySQL Replication 機制讓 Server 2 同步跟著 Server 1 資料,等到資料差不多時,可以把 target db connection 角色從 Server 1 移到 Server 2,但轉移的過程中總是有一些連線還在跟 Server 1 溝通,就會變成有新資料新增到 Server 2 上,而 Server 1 裡還未同步到 Server 2的資料,其 primary key id 很大的機會跟 Server 2 裡的一樣,導致 primary key collision 問題。

因此,為了解決這個問題,就可以透過 auto-increment-increment 和 auto-increment-offset 的設定,讓兩台的 auto-increment-offset 不一樣,就可以避免這種問題了。

Linode - 使用 Backup 服務處理事件: An issue affecting the physical hardware this Linode resides on has been detected.

下班前收到這個 event ,結果就是繼續加班 Orz 若下班前的會議沒 delay 的話,我應該是在回家的路上被狂 call XDD

An issue affecting the physical hardware this Linode resides on has been detected.

We are working to resolve the issue as quickly as possible and will update you as soon as we have more information.
Your Linode will return to its previous state once the issue is resolved. Thank you for your patience and understanding.

記得以前問過學弟,他說 Linode 也會有維護的情況,沒想到真的碰到了...直接把你的機器關掉,我跟老闆說,這就像我們租的機房碰到火災一樣 XD 沒轍。

至於解法也沒有啥好辦法,一種就是等他維護好,另一種則是另外建一台 backup server 出來用,由於我們的服務都有建 backup ,所以就來體驗一下。

切換到被關掉的那台機的 backup 區,可以看到有一些選項可用:


此例就選 daily backup 的 restore to 選項,接著選要去哪台機器:


由於我已經先開了新機器(最下面那台),不然可以點 Add a Linode,此例也意外發現只能 restore to 同一區 DataCenter 的機器。最後,那台新機器的情況就會顯示正在處理:

 

處理完後,就可以 Boot 啦 :P

註:還好 Linode 只花了 3 小時處理,接著就可以把新機器著手進行關閉了。

2014年4月14日 星期一

[Linux] 安裝 Glances - An eye on your system @ Ubuntu 12.04


Glances - An eye on your system

$ sudo apt-get install python-pip build-essential python-dev
$ sudo pip install Glances
$ glances


如此就可以看到美美的系統監控了 :D

其中 glances 來支援 server/client 模式,並支援 password 管控,可以把它當作可以遠端看 server 的狀態吧

Server:
$ glances -s -B 0.0.0.0 -p 12345 -P helloworld
Glances server is running on 0.0.0.0:12345


Client
$ glances -c ServerIP -p 12345 -P helloworld

2014年4月12日 星期六

[OSX] 透過 USB 線使用 Android 手機讓 Macbook Pro 上網(Android Wi-Fi sharing via USB connection)



對於新一點的 Android 手機,在網路分享那塊有三種模式:
  • 可攜式 Wi-Fi 無線基地台 (Wi-Fi 行動熱點)
  • 藍牙網路共用
  • USB 網路共用
比較常用的就是讓 Android 手機當作一個無線 AP ,讓其他終端設備透過 Android 手機連出去網路,這個模式通常是 Android 手機可以透過 2G/3G/4G 電信網路連出去的情況。

然而,參加一些 conference 時,自設 Wi-Fi 行動熱點容易與現場的 Wi-Fi AP 訊號產生干擾,導致別人用大會無線網路品質不佳,所以最佳的方式就是透過 USB 網路共用!


對 Mac OSX 而言,需要解決的就是讓 OSX 辨識 USB 網路共用裝置,簡言之就是需要安裝 driver 才行 XD 所幸網路上有熱心方案:HoRNDIS: USB tethering driver for Mac OS X,如此一來,只要將手機開啓 USB 網路共用,而 OSX 可以偵測到就行能上網啦

iOS 開發筆記 - Improper Advertising identifier [IDFA] Usage. Your app contains the Advertising Identifier [IDFA] API but you have not indicated its usage on the prepare for Upload page in iTunes Connect.



在 2014-04-10 上傳 ipa 發現這這問題:
Improper Advertising identifier [IDFA] Usage. Your app contains the Advertising Identifier [IDFA] API but you have not indicated its usage on the prepare for Upload page in iTunes Connect.
解法有兩種:
  • 將程式內有用到 UUID/UDID 的部分去掉(如 Google Analytics Library 等),再重新上傳
  • 設法先退可簽署 IDFA 條約的狀態,重新上傳
其中要退回到簽署 IDFA 的部分,可以做的方式有兩種:
  • 將 app 內有用到跟 UUID/UDID 相關的移掉,進行重新上傳到 iTunes Connect,再把 reject 它,重新填寫跟 IDFA 相關的條款,再重新上傳 iTunes Connect
  • 建立 empty project ,將 Bundle Identifier 設成跟 app 一樣,上傳到 iTunes Connect,再 reject 它,重新填寫跟 IDFA 相關的條款,再重新上傳 iTunes Connect
後來,我選擇不用改 code 的部分,當然也要先把狀態改回到可以簽署 IDFA 流程,就選擇建立 empty project 來處理(此外,可以從原先的 app project 把Images.xcassets複製來用)。只是一樣的程式碼幾個禮拜前沒問題,為何這幾天出事?真是令人不解。

今早 2014-04-12 測試時,一樣的 code 發現又沒 IDFA 問題了 Orz 但還是把碰到這怪現象的解法記錄一下。

註 UDID/UUID 相關:

#import <AdSupport/ASIdentifierManager.h>

if (NSClassFromString(@"ASIdentifierManager")) {
    NSLog(@"ID: %@", [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]);
} else {
    NSLog(@"ID: %@", [[UIDevice currentDevice] uniqueIdentifier]);
}


Updated @ 2014-05-02 : iOS 開發筆記 - 使用 AdMob 與 IDFA 的處理

2014年4月10日 星期四

iOS 開發筆記 - The Facebook server could not fulfill this access request: no stored remote_app_id for app


犯了一個小錯誤 XD 太久沒用 Facebook app 了,新版界面忘了新增 iOS Bundle ID 導致 Reviewer 無法登入 :P 但很妙的這個現象是在 iOS 使用內建系統 Facebook 帳號整合時,才會出現的。

至於新增 iOS app 的設定:
developers.facebook.com -> Your App -> 設定 -> 新增平台
預設沒有顯示出來,所以...不小心忽略了。

重簽 Godaddy SSL 憑證 (re-keying an SSL Certificate)

熱門議題 OpenSSL Security Advisory [07 Apr 2014] / CVE-2014-0160 的影響,要把所以 Web Server 用的 HTTPS 重新整理,由於使用 Godaddy 維護 SSL 憑證,所以,直接看 Godaddy 流程:Re-Keying an SSL Certificate

  1. Log in to your SSL Manager.
  2. Go to the Manage Certificates tab.
  3. In the Filters list, click Certificates.
  4. Select the certificate(s) you want to re-key, and then click Re-Key. The Re-Key Certificate page displays.
  5. If your domain name uses our shared hosting, and you want to switch to third-party hosting or one of our virtual private or dedicated servers: For What would you like to do?, select Un-install this certificate.
  6. In the CSR field, paste your new CSR, including ----BEGIN NEW CERTIFICATE REQUEST---- and ----END CERTIFICATE REQUEST----.
  7. Select a Signature algorithm and a Certificate issuing organization, and then click Re-Key. We'll send you an email message with instructions to validate and download your certificate.

NOTE: This operation removes your existing SSL certificate from your shared hosting account, causing temporary website downtime for up to 72 hours.

[Linux] 更新 OpenSSH Server Key @ Ubuntu 12.04

由於熱門議題 OpenSSL Security Advisory [07 Apr 2014] / CVE-2014-0160 的影響,只好重新處理一下 OpenSSH Server key 了:

$ lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 12.04.4 LTS
Release: 12.04
Codename: precise
$ sudo rm /etc/ssh/ssh_host_*
$ sudo dpkg-reconfigure openssh-server

2014年4月9日 星期三

拆錶蓋 換電池 修錶工具組



說真的...覬覦這東西很久了 XD 以前都是用類似鑷子的東西,盡可能把錶蓋轉開,後來這次找不到鑷子,又發現附近的雜貨店賣一隻都快百元了,所以,就等一整組的工具組吧!

其實火車站附近的光X文具店也有在服務,分開收電池跟服務費(印象中是50元),那換 2~3 次就可以買一組工具了,於是就嘗試找看看吧!


這整組是在網拍買的(含運約150元),用 "拆錶" 關鍵字去搜尋就可以找到了。妙的是我親自跑了附近的鐘錶批發,一樣的東西都喊400元起跳 Orz 或是單一隻拆錶後蓋的都 80 起跳,真的貴不少。

有興趣的就去網拍逛逛吧,直接跑店家買不見得可以便宜到,或許是因為非熱門玩物吧?

[Linux] Proftp Quota 筆記 @ Ubuntu 12.04

由於採用 Virtual FTP User 的關係,試用一下 Proftp Quota 的服務:

$ cd /etc/proftpd/
$ sudo ftpquota --create-table --type limit
$ sudo ftpquota --create-table --type tally
$ ls -la
ftpquota.limittab
ftpquota.tallytab


$ sudo vim /etc/proftpd/proftpdc.conf
#<IfModule mod_quotatab.c>
#QuotaEngine off
#</IfModule>
$ sudo vim /etc/proftpd/conf.d/QuotaUsage.conf
<IfModule mod_quotatab.c>
QuotaEngine on
QuotaLimitTable file:/etc/proftpd/ftpquota.limittab
QuotaTallyTable file:/etc/proftpd/ftpquota.tallytab
QuotaShowQuotas on
QuotaDisplayUnits Mb
QuotaOptions ScanOnLogin
</IfModule>

$ sudo service proftpd restart


測試:

$ ftp localhost 21
ftp> quote site quota
202 No quotas in effect


試看看限定所有人只能上傳 20GB:

$ sudo ftpquota --table-path /etc/proftpd/ftpquota.limittab --add-record --type limit --quota-type all --units Gb --bytes-upload 20
$ sudo service proftpd restart


$ ftp localhost 21
ftp> quote site quota
200-The current quota for this session are [current/limit]:
200-Name: username
200-Quota Type: User
200-Per Session: False
200-Limit Type: Hard
200-  Uploaded Mb:              0.00/20480.00
200-  Downloaded Mb:    unlimited
200-  Transferred Mb:   unlimited
200-  Uploaded files:   unlimited
200-  Downloaded files: unlimited
200-  Transferred files:        unlimited
200 Please contact root@server if these entries are inaccurate

Linode Resize 筆記



上回在研究 Linode Resize 時,發現他的過程是將機器關機、資料移轉、開機,因此最後沒有採用。這次有台偏 testing 的機器,服務性質上恰好可以承受 donwtime 時間,就來試試了!

過程如之前所料的,先關機再移機,以官方公佈的資訊為例,從 Linode 1G 移機 resize 需要耗時 36 分鐘,此時間會跟 Linode 上選的方案有關,因為每個方案的 Storage 大小不一樣。

整體上,所耗的時間主要就是在搬移資料,至於搬移的速度嘛,據觀察一開始每秒 18MB/s,但之後可飆到 66MB/s,所以原先 Linode 1G 方案有 48 GB 儲存空間,以 50MB/s 算一下就是 15~20 分鐘,而實際移轉過程也可以線上觀看 Host Job Queue,項目名稱:Migrate Filesystem。



別忘了,做完 Resize 後要自己重開機!此次從 Linode 1G 升到 Linode 4G 耗時約 15 分鐘。




註:Linode Resize 完,Disk 也要自己 Resize 才行 Orz 所以又關機了一次

2014年4月5日 星期六

iOS 開發筆記 - ALAssetsLibrary assetForURL defaultRepresentation fullResolutionImage - Terminated due to Memory Pressure

最近設計 app 時,開始把圖片存進內建得相本裡,而不使用 app sandbox 空間,然而要取出圖片時,就會碰到 Terminated due to Memory Pressure 的問題,追一下,大概是瞬間取太多張照片 :P 此為 ARC 模式。

解法:
  1. 降低瞬間取照片的數量
  2. 使用 @autoreleasepool{ } 處理記憶體管理
例如:

[self.library assetForURL:[NSURL URLWithString:@"assets-library://..."] resultBlock:^(ALAsset *asset) {
                                //NSLog(@"asset:%@",asset);
                                UIImage *image = nil;
                                @autoreleasepool {
                                    image = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
                                }
                            } failureBlock:^(NSError *error) {
                            }];


只是,這樣也沒有真的避免大量記憶體的使用 Orz 因為 [asset defaultRepresentation] fullResolutionImage] 真的吃滿大的記憶體,例如 5MB 大小的照片,處理一張照片時,記憶體會瞬間加了 30~50MB,所以瞬間處理 3~5 張時,記憶體還可能衝到 2xxMB ,直到 Terminated due to Memory Pressure。暫時想到的解法就只能透過降低處理照片的張數了。

實際例子是 app 初始化完大概 20MB 記憶體,跑上述 code 處理 3 張照片可以吃到 90MB,不曉得是不是 CGImage 的關係?改天有空再追一下。