2020年3月29日 星期日

Reactive Programming(三):Project Reactor

本系列的文章為 Modern Java in Action / Project Reactor 的讀書筆記,因此內容可能會有點跳躍。

2020年3月18日 星期三

在 Spock Framework 測試包含 parallel stream 的標的時卡住

紀錄一下最近解了幾天的問題,程式碼大體上類似 [1] 裡面的 MyRecordProcessor 和 MyRecordProcessorTest 那樣。因為本來是要建置環境比較簡單的測試來重現問題,而原本的問題是發生在開發 Kinesis 的 RecordProcessor 中遇到的,因此 [1] 的範例也沿用了這個關係。不過實際上最後發現的原因跟 Kinesis 沒有關係就是了。

問題的徵兆是,當要測試的標的內部改寫成有 parallel 的狀況時,Spock 這邊執行測試就可能會出現測試整個卡在某個地方的狀況。卡住時會完全沒有回應,但也沒有拋出錯誤或者停止執行。這個問題好像遇到的人並不是那麼多,所以可以找到的資料也非常少。不過主要參考了 [2-3],最後確認的原因是因為測試時用了 Spy。Spy 好像存在某些限制(在 [3] 的回答中有提到,雖然他沒提到到底是什麼限制),實際上似乎導致在 parallel 的狀況時,Spy 的 dynamic proxy 似乎有時會生效、但有時會無效。所以最後解決方法就是~不要用 Spy。

參考資料
  1. spock-parallel-test
  2. Spock unit test is stuck when parallel stream is used
  3. Using thread pools in a Spock Spy'd class hangs during unit tests

2020年3月1日 星期日

Vespa 入門(一):在本機建立 containerized Vespa

因為在公司持續地在用 Vespa,所以打算寫個系列文章慢慢紀錄 Vespa 的一些使用、調校經驗。(雖然說過去寫的系列文章大多…寫到第二或第三篇就………。)

本篇會紀錄在本機啟動 Vespa 的 container 的方法,通常這麼做可以在開發階段用來測試 Vespa 的語法。可以參考 Vespa 官方文件 [1]。

環境準備

依照 [1] 的描述,Docker 環境最重要的就是需要有至少 6GB 的記憶體。而在我的環境中,我是在 Windows 10 上跑 Docker 的,因此至少要是個有支援 Hyper-V 的 Windows 版本,才能夠執行 Docker。

取得 Vespa 範例

首先,Vespa 有提供一些簡單的範例 Application,可以從以下的 Github 取得。裡面有很多資料夾,包含了數種在 Vespa 官方文件中會講到的例子。

git clone https://github.com/vespa-engine/sample-apps.git

這裡假設我把這個 repository 放在 G:\git 裡。

建立並啟動 Vespa container

要啟動 Vespa 之前,我們需要執行兩個動作。第一個是先啟動一個 Vespa 的 container,這個步驟只會準備好 Vespa 需要的執行環境而已。接著第二個是部署 Vespa Application,這個動作就像是在 RDBMS 裡執行 CREATE DATABASE 一樣,是讓 Vespa 準備好 schema 並且真的啟動伺服器。

docker run --detach --name sample-vespa --hostname vespa-container --privileged --volume g:\git\vespa-sample-apps:/vespa-sample-apps --publish 8080:8080 vespaengine/vespa
docker exec sample-vespa bash -c 'curl -s --head http://localhost:19071/ApplicationStatus'

首先如前所說,我們先以 vespaengine/vespa 的 image 啟動一個 Vespa container,這裡我們把這個 container 命名為 sample-vespa,並且把資料夾 g:\git\vespa-sample-apps 掛到 container 的 /vespa-sample-apps 路徑上,方便之後我們在這個 container 中部署與啟動 Vespa。

container 開好以後,可以透過第二行指令來確認 Vespa 的狀態。不過因為 container 雖然綁了 port,但卻還沒有啟動任何服務,因此我們要確認狀態只能利用在 container 裡執行 curl 指令來確認。如果正常的話會獲得類似這樣的回覆:

HTTP/1.1 200 OK
Date: Sun, 01 Mar 2020 11:31:41 GMT
Content-Type: application/json
Content-Length: 9232

接著就是要在裡面部署和啟動指定的 Vespa Application 了。

docker exec sample-vespa bash -c '/opt/vespa/bin/vespa-deploy prepare /vespa-sample-apps/album-recommendation-selfhosted/src/main/application/ && /opt/vespa/bin/vespa-deploy activate'
curl -s --head http://localhost:8080/ApplicationStatus

這邊我們先部署 album-recommentation-selfhosted 這個 Vespa Application。因為 Vespa 的 Search Definition 是放在 src/main/application 裡的,因此在部署的時候要指定路徑是這個資料夾。第一個指令會獲得類似這樣的反應,表示已經順利地啟用 Vespa Application。

Uploading application '/vespa-sample-apps/album-recommendation-selfhosted/src/main/application/' using http://localhost:19071/application/v2/tenant/default/session
Session 3 for tenant 'default' created.
Preparing session 3 using http://localhost:19071/application/v2/tenant/default/session/3/prepared
WARNING: Host named 'vespa-container' may not receive any config since it is not a canonical hostname. Disregard this warning when testing in a Docker container.
Session 3 for tenant 'default' prepared.
Activating session 3 using http://localhost:19071/application/v2/tenant/default/session/3/active
Session 3 for tenant 'default' activated.
Checksum:   71cf99ec40a0a08c8edbd1aa3cee03ed
Timestamp:  1583062394458
Generation: 3

再使用第二個指令確認 Application 狀態時,可以獲得:

HTTP/1.1 200 OK
Date: Sun, 01 Mar 2020 11:34:39 GMT
Content-Type: application/json
Transfer-Encoding: chunked
參考資料
  1. Vespa: Quick Start