2017年12月28日 星期四

在 AWS Lambda 的 Python 程式匯入額外的套件

AWS Lambda 的執行環境有預設匯入的套件
如果使用了其他的套件,Python 程式就會拋出找不到套件的錯誤。

從 AWS 的官方文件 [1] 中,可以看出關於這個問題的解決方法
就是事先把套件裝進程式裡,當成是程式自身的一部分,一起打包送進 AWS Lambda。

具體來說,也就是假設我的 Python 程式的資料夾是放在 D:\python\my_project
則可以使用以下的指令,把套件指定安裝到專案資料夾中。

pip install requests -t D:\python\my_project

而做完後,就會看到專案資料夾跑出一大堆資料夾和檔案
之後要上傳到 AWS Lambda 時,把整個資料夾(也就是 D:\python\mu_project\* )壓縮成 zip
一起上傳到 AWS Lambda 即可。

參考資料
  1. Creating a Deployment Package (Python)

2017年12月21日 星期四

AWS SDK v2 疑似是 BUG 的 exclusiveStartKey?

這只是快速先紀錄一下目前遇到的狀況,但還沒有嚴謹地確認是不是其他邏輯造成的…..。

2017年12月19日 星期二

SLF4J 與其他 logging framework 實作綁定與橋接的關聯

使用 SLF4J 的時候,同時使用很多開源函式庫,會很容易導致各種 log 跑不出來或者 dependency 衝突的問題
本質上是因為不同開源函式庫,各自使用了不同的 logging framework
因而導致了 log 被輸出到沒有被設定的實作,或者相同的實作被重複綁定等等。

2017年12月13日 星期三

AWS DynamoDB SDK v2 基礎使用(二):基礎開發環境建置

因為今年 AWS 推出了第二版的 AWS SDK [1],所以就來紀錄 AWS SDK v2 吧。

在用過第一版的 SDK 以後,其實覺得第二版的 SDK 寫得比較易用,而且還支援 Java Stream API。
不過實務上 AWS SDK v2 的文件 [2-3] 目前相當地不完整,而且網路上也沒太多資料
所以有很多情況是必須依靠第一版的經驗、Javadoc 跟 IDE 的提示來猜測使用方法…。

2017年12月12日 星期二

Jersey Test Framework 在 JUnit 5 的暫時解法

本來 Jersey Test Framework 是對應 JUnit 4 使用的 Jersey 測試環境
如果開發環境升級到 JUnit 5 的話,就會出現像下述這樣的 NullPointerException 的狀況。

java.lang.NullPointerException
     at org.glassfish.jersey.test.JerseyTest.target(JerseyTest.java:564)
     at org.glassfish.jersey.test.JerseyTest.target(JerseyTest.java:578)

2017年12月6日 星期三

DynamoDB 更新

更新 List/Set 裡的內容

首先需要注意 List 跟 Set 主要的不同點:

  1. List 可以包含重複的 Element,而更新時基本上也不會對重複的 Element 做什麼處理;而 Set 會自動合併相同的 Element,例如 String Set 在寫入重複的字串時,不會再出現第二個相同的 Element(也不會噴 Exception)。
  2. List 的內容更新,需要使用 SET 指令;但是 Set 內容的更新,則是使用 ADD 指令。
Attribute Value 不要直接寫在 Expression 裡
key 不存在時,list_append() 會失敗

可參考 [6],AWS 的 SDK 在嘗試附加內容到一個 list 裡時,如果這個 list 本身就不存在,會出現的錯誤其實不太能解釋狀況
出現的錯誤訊息會是:

software.amazon.awssdk.services.dynamodb.model.DynamoDBException: The provided expression refers to an attribute that does not exist in the item
參考資料
  1. Update Expression
  2. Working with Items: Java
  3. aws-doc-sdk-examples
  4. AWS SDK for Java 2.0 – Developer Preview
  5. How do I Append a string to a list using dynamodb sdk? (Java)
  6. Is it possible to combine if_not_exists and list_append in update_item

2017年11月30日 星期四

AWS CloudWatch Filter

CloudWatch 的 Filter 功能,主要的目的好像是用來觀察指定的事件在某個時間區段中的發生狀況
所以總歸來說,適用在想要把結果劃成折線圖那種的狀況。

例如 AWS 官網給的範例 [2],都是屬於建立 Filter 去偵測某個特定樣式的 log 是否出現
出現的話,在 Metric 上會反應出「事件出現次數 +1」
然後最後在 CloudWatch 的 Metrics 那邊,就能夠以折線圖的形式,看到例如每分鐘這個事件的發生狀況。

參考資料
  1. 淺談系統監控與 AWS CloudWatch 的應用
  2. Creating Metric Filters

2017年11月27日 星期一

在 Java 中把 AWS DynamoDB 的紀錄轉成 JSON

DynamoDB 上的紀錄,都會有像是 {“S”: “XXX”} 之類的格式,用以表示它在 DynamoDB 裡的型態
不過程式在處理時,這樣很麻煩~。

實務上,AWS SDK 裡提供了一些方法,可以幫我們去掉那些多餘的東西。
具體來說,例如以下的程式碼:

ScanRequest scan = new ScanRequest();
ScanResult result = dynamodbClient.scan(scan);

Gson gson = new GsonBuilder().build();

for (Map item : result.getItems()) {
    JsonElement json = gson.toJsonTree(InternalUtils.toSimpleMapValue(item));
}

上述的程式碼,是假設對一個 DynamoDB 的表格做 scan 操作
操作完以後,要把 scan 出來的結果,用 GSON 轉成 JsonElement 的型態。
這裡透過 com.amazonaws.services.dynamodbv2.document.internal.InternalUtils 這個套件
就能夠去掉欄位型態這個東西,讓結果成為單純的 JSON。

參考資料
  1. DynamoDB - Object to AttributeValue

2017年11月24日 星期五

AWS Lambda 呼叫另一個 AWS Lambda

一般來說,Lambda 都是透過中介服務去觸發的
例如透過 DynamoDB Stream、SNS、Kinesis、S3 等等的
當這些服務發生變更時,發送訊息觸發 Lambda。

不過實務上,Lambda 本身只要具備 Invoke 權限,就能夠直接透過 AWS 的 Lambda API 去觸發另一個 Lambda。

2017年11月22日 星期三

AWS SNS 的 Delivery Policy

在使用 SNS 時,需要考慮如果接收端處理 message 失敗了該怎麼辦?
如果沒有做特殊的設定,預設 SNS 是會直接走 Backoff Phase,重試三次、每次延遲 20 秒。

不過如果想要更多一點的重試,或者想設定比較複雜的行為,就需要稍微了解一下 SNS 的 Delivery Policy。

2017年11月16日 星期四

在 Elasticsearch 上安裝 X-Pack

因為想要監控 Elasticsearch,所以就試著安裝了 X-Pack。
X-Pack 安裝流程請直接參考官方文件 [1] XD
因為只有幾個動作而已,這裡就省略了。

yum 鎖定軟體版本

以我的狀況來說,因為我的 Elasticsearch 有使用一些有限定版本的擴充套件
因此要避免 yum 不小心幫我把 Elasticsearch 升級。
要作到這個效果,可以使用 versionlock 這個工具
例如以下這樣,可以把 elasticsearch 和 kibana 套件鎖在目前安裝的版本上。

yum install yum-plugin-versionlock
yum versionlock elasticsearch-*
yum versionlock kibana-*
參考資料
  1. How do I exclude kernel or other packages from getting updated in Red Hat Enterprise Linux while updating system via yum?

2017年11月12日 星期日

從 Jupyter 讀取 Windows 磁碟中的鐵達尼號資料

在書上的範例中,提到用鐵達尼號的資料做分析
不過書上範例所指的資料位址已經無法存取了。
稍微搜尋了一下,發現 Kaggle 也有提供這個資料 [1],而且是免費的。

從 [1] 下載資料下來之後,假設是放在 D:\test\data\titanic 這個資料夾裡,訓練用的資料命名為 train.csv

import pandas

training_data_path = "D:\\test\\data\\titanic\\train.csv"

# Read training data.
training_data = pandas.read_csv(training_data_path)
print(training_data)

路徑要記得跳脫,才能正確找到檔案。

參考資料
  1. Kaggle - Titanic: Machine Learning from Disaster
  2. Read a .csv into pandas from F: drive on Windows 7

2017年11月7日 星期二

透過 Anaconda 安裝 Tensorflow 與 Keras

  1. 下載並安裝 Anaconda
  2. 執行以下的指令建立 Python 虛擬環境
    conda create --name tensorflow python=3.5 anaconda
  3. 啟用虛擬環境
    activate tensorflow
  4. 安裝 Tensorflow
    pip install tensorflow
  5. 此時想再使用 pip 會出錯 [1],要先以下述指令強制重新安裝 html5lib
    conda install --force html5lib
  6. 安裝 keras
    pip install keras
參考資料
  1. pip throws TypeError: parse() got an unexpected keyword argument 'transport_encoding' when trying to install new packages

2017年9月21日 星期四

Elasticsearch 去除重複資料

最近一直在處理 Elasticsearch 資料重複的問題
程式當中想要在插入資料之前,先搜尋有沒有重複的資料
如果有的話就先把重複的資料砍到剩下一筆,然後針對那一筆做資料更新。
不過實務上,程式跑起來有些會成功完成 deduplication,但有些則依然重複。

2017年9月13日 星期三

透過 AWS Lambda 開發 Serverless Framework(三):使 Lambda 函式擁有 Internet 存取權

Lambda 函式在部署的時候,預設是不會帶有任何網路設定的
因此我們沒辦法知道 Lambda 實際的 IP 位址等等的資訊。
在一些單純的程式中,這可能沒什麼
但如果是在系統的 pipeline 裡,Lambda 需要去存取其他非公開服務時,可能就會有問題了。

2017年8月17日 星期四

透過 AWS Lambda 開發 Serverless Framework(二):開發 RESTful API

從前一篇文章中,可以看出 Lambda 是一種以事件來觸發的架構
理論上因為 RESTful API 也是以事件觸發的,所以應該也有機會變成 Lambda
不過 JAX-RS 的結構又跟 Lambda 的結構不太一樣,所以到底行不行呢?

2017年8月16日 星期三

eclipse 在 Windows 10 發生使用 git 就無回應的問題

最近突然 eclipse 發生了只要使用任何 git 功能,eclipse 就會陷入無回應的狀況
困擾了一段時間,在經過有點努力的搜尋後,終於找到問題的原因和解法了!(歡呼貌)

2017年8月2日 星期三

透過 AWS Lambda 開發 Serverless Framework(一):接收 Kinesis 訊息

AWS Lambda 是 AWS 發表並大力主打的 Serverless 服務之一。
在談怎麼使用 Lambda 之前,也許可以先談談為何要使用 Lambda?

2017年7月27日 星期四

無法在 GoDaddy 設定 @ 的 CNAME

因為網站是用 WordPress 架在 AWS 上,所以網域應該要用 CNAME 導去 AWS 的位址
本來很單純想說網域(假設是 example.com)想要自動轉去 https://www.example.com
設定上就是加上 @ 的 CNAME
但結果在 GoDaddy 上就是無法設定,它一直顯示紀錄已存在。

花了一些時間查詢以後,雖然細節有點看不太懂,不過總之原因好像是因為 CNAME 其實會跟其他像是 TXT、MX 之類的紀錄重疊 [1-2]
所以某個網域或者子網域如果要設定 CNAME 的話,這個網域或子網域應該要不存在任何除了 A 以外的紀錄
否則會導致紀錄之間衝突,因而產生像是 [3] 的結果,某些既存的其他服務會因為被 CNAME 覆蓋而無效了。

另外 [2] 的回覆也有提到,DNS 的規格文件 RFC 1034 的 3.6.2 小節中,有以下的具體描述。

A CNAME RR identifies its owner name as an alias, and specifies the corresponding canonical name in the RDATA section of the RR.  If a CNAME RR is present at a node, no other data should be present; this ensures that the data for a canonical name and its aliases cannot be different.  This rule also insures that a cached CNAME can be used without checking with an authoritative server for other RR types.

而這個問題要解決的話,以 GoDaddy 來說,可以去設定它免費提供的「網域轉址」
就可以把網域(example.com)自動導向到某個自行指定的網址了。
不過實際實驗時,好像網域轉址只對 HTTP 有效,HTTPS 似乎無效就是了。
也就是說,設定後 http://example.com 會有自動轉址的效果,但是 https://example.com 則沒有反應。

參考資料
  1. Configuring “@” CNAME record in GoDaddy control panel
  2. CNAME and TXT record for same subdomain not working
  3. Why it's a bad idea to put a CNAME record on your root domain
  4. RFC 1034

2017年7月23日 星期日

使用 Django 建立網站(二):建立第一個自定義的頁面

在前一篇當中,我們已經產生了一個叫做 myweb 的專案,接著要建立一個應用程式(App)。
這部份基本上也可以參考 Django 官方的教學文件 [1]。

2017年7月16日 星期日

在 Eclipse 使用 Python 虛擬環境開發 Python

最近再度開始學習 Python,然後看到不少 Python 套件的官方文件提到虛擬環境
因此來紀錄一下,以 Java 開發者的角度來看 Python 虛擬環境相關的基本知識。

2017年7月15日 星期六

在 Ubuntu 14.04 安裝 venv

在 Ubuntu 14.04 上,想要用下述指令建立虛擬環境時,出現沒有安裝 venv 的錯誤訊息

root@default:/# python3 -m venv myvenv
The virtual environment was not created successfully because ensurepip is not
available.  On Debian/Ubuntu systems, you need to install the python3-venv
package using the following command.

    apt-get install python3-venv

You may need to use sudo with that command.  After installing the python3-venv
package, recreate your virtual environment.

但依照訊息的描述去安裝 python3-venv 時,又出現找不到這個 package 的錯誤。
參考 [1] 的作法,實際上好像應該安裝的套件是 python3.4-venv

apt-get install python3.4-venv
參考資料
  1. Python3-venv not installed ubuntu 14.04

2017年7月6日 星期四

使用 ssmtp 連接郵件伺服器時的驗證問題

同事在使用 ssmtp 連接 Office365 時,Office365 的郵件伺服器一直回覆下述的訊息

535 5.7.3 Authentication unsuccessful

花了一段時間研究後,發現問題其實是在於登入的密碼包含像是 # 這種特殊符號
導致 ssmtp 並沒有送出正確的密碼,因而造成驗證錯誤。

由於目前這仍然是個 open issue,因此也只能紀錄一下,然後去改密碼了 XD。

參考資料
  1. Special characters in ssmtp password

2017年7月5日 星期三

使用 Django 建立網站(一):安裝 Django

其實只是需要用 Python 做 RESTful 的網站,然後隨便搜尋一下就看到 Django,於是就試著用看看。

2017年7月4日 星期二

使用 Java 存取 FTP 伺服器

要存取 FTP 伺服器,簡單地搜尋了五秒,大概就會看到 Apache Commons Net 這個函式庫吧 XD。
包山包海地實作了包括 FTP、NTP、SMTP、Whois 等等的一堆基礎網路相關的協定。
而這篇的目的是為了簡單地紀錄 FTP 的使用方法。(其實真的蠻簡單的 XD)

2017年6月27日 星期二

變更 Privoxy 預設行為

Privoxy 是個 Proxy 伺服器軟體,預設狀況下會做不少擋廣告之類的行為
不過也許在某些網站會遇到這些阻擋行為導致網站無法正常瀏覽。

2017年6月16日 星期五

在部落格使用 SyntaxHighlighter 4

部落格要放程式碼的時候,需要一些套件幫忙換顏色什麼的,讓程式碼更容易閱讀些
我的部落格很久以前就在用 SyntaxHighlighter 3
不過今天突然發現本來用的網域服務要收掉了,必須要把 SyntaxHighlighter 的 JavaScript 換地方放
此外同時也發現 SyntaxHighlighter 4 出現在 Github [1] 上,所以就順便嘗試了升級。

2017年5月26日 星期五

在 Java 設定 Command Line 參數:Apache Commons CLI 簡易使用(未完)

寫程式時,寫完的程式總是要被執行的。不過要怎麼被使用者執行呢?
現代來說,容易想到的就是做個 GUI 介面~
但實務上,很多小程式其實可能做 GUI 介面得花費的開發時間,甚至遠高於程式本身
而且 GUI 做出來有可能也只有兩三個按鈕,顯得挺不划算~。
因此,其實有相當多的程式,最後都還是會選擇最簡易的方式:以 Command Line 的形式讓使用者執行。

在 Java 中,main() 進入點都會有個 String[] args 的參數
這個陣列就是使用者在執行程式時,同時夾帶的 Command Line 參數。
當然我們可以自己去解析陣列的內容,但挺浪費時間。更好一些的作法,是使用已經有的現成函式厙。
而這裡要紀錄的,就是 Apache Commons CLI [1]。

2017年5月4日 星期四

在 Java 傳送訊息給 Amazon SQS

Amazon SQS 是 Amazon 的其中一個訊息服務
感覺上其實有點像是劣化版的 Kinesis。
Anyway,總之就是一種用來傳送訊息的方法,所以這篇要來簡要紀錄一下怎麼從 Java 控制它。

2017年4月18日 星期二

Java 字串與位元組的編碼

簡單小記,字串(String)因為任何理由要轉換成位元組(byte array)時,最好要指定編碼
否則在 Java 中,預設會以系統編碼來處理,就容易產生中文亂碼的問題。

String s = "some text here";
byte[] b = s.getBytes(CharSet.forName("UTF-8"));

s = new String(b, CharSet.forName("UTF-8"));

在 Amazon Linux AMI 上使用 Java 8

簡單的小問題~AMI 預設好像內建 Java 1.7,要更新成 1.8 的話,可以用以下的 YUM 指令。

sudo yum install java-1.8.0
sudo yum remove java-1.7.0-openjdk

其中要特別把 1.7 移除掉,是因為單純安裝 1.8 的話,預設 java 指令還是會呼叫 1.7。

參考資料
  1. How can I upgrade to Java 1.8 on an Amazon Linux Server?

2017年3月20日 星期一

在 Gitlab 上設定使用 AWS SES 作為郵件伺服器

其實試了一段時間之後,發現也不用特別紀錄什麼,因為官方有完整的設定範例 [1] 了 XD
唯一需要稍微注意的地方是….設定完以後要用 reconfigure 指令讓 Gitlab 重讀,不要用 restart
但這其實也寫在官方文件 [1] 上了。

參考資料
  1. SMTP Setting – AWS SES
  2. SSL certification error

2017年3月8日 星期三

如何維持軟體專案的可維護性?

最近半年,有時常在猶豫一些問題,最常遇到的,就是前些時候寫好的一段程式碼,現在必須在上頭追加一些新的功能,然後就感覺到「唔,當初沒有計畫要追加這個功能,所以結構不太適合這麼做」,或者是「當初時程有點趕,寫起來有點凌亂」等等,可能有著各種原因讓自己覺得之前寫好的程式碼有點髒。但現在新功能的時程也不是很長,如果去動了舊的程式碼,時程可能變得很緊湊,那該怎麼辦呢?

2017年2月15日 星期三

StartingSequenceNumber 49537979178794861780081237450294896636708704732336619521 used in GetShardIterator on shard shardId-000000000000 in stream primaryManifestStream under account xxxxxxxxxxx is invalid because it did not come from this stream

先簡要紀錄,收到這種一大串說 “it did not come from this stream” 的錯誤訊息
根本原因在於,使用 Kinesis 的 Consumer 時
設定 group ID 後 Consumer 會去 DynamoDB 建立一張 table,table 名稱會完全跟 group ID 一樣
因此如果有兩個在監聽不同 Stream 的 Consumer 用了相同的 group ID,晚建立的那個 Consumer 就會噴出標題的錯誤。

參考資料

  1. GetShardIterator... invalid because it did not come from this stream

2017年2月8日 星期三

Maven 部署專案時,附上 javadoc 或原始碼

一般在 pom 檔沒有特別設定時,使用 mvn deploy 指令只會把函式庫打包後的 jar 送上 Maven Repository Server
但這樣會造成其他使用者在使用這個函式庫時,沒有 javadoc 可以即時查閱。
因此改成以下的指令 [1],讓 Maven 打包時順便一起把 javadoc 打包起來會比較好些。

2017年1月23日 星期一

在 Jersey Test Framework 中測試 Multipart Form Post 的環境設定

在 Jersey 上要使用 Multipart,需要額外做一點事情,包括引用 Multipart 的函式庫,並且設定要 Jersey 載入
不過當要使用 Jersey Test Framework 時,這個問題又稍微更麻煩了一點
因為 Jersey Test Framework 也是使用 Jersey,然後因此在 Client 端也額外需要做設定
除了 Jersey Test Framework 啟動的 Web Server 上需要動態註冊 Multipart 以外
還有 Jersey Test Framework 的 Client 也需要註冊 Multipart。(好麻煩 XD)