takeda_san’s blog

JavaFXと機械学習を頑張る方向。

GCPでもJavaがしたい その4

作業予定

  1. GCPアカウント作成
  2. Webサーバをたててみる
  3. JREをいれて何か動かしてみる
  4. RMIで通信してみる
  5. Dockerイメージをつくってみる ←今回はここ
  6. コンテナを動かしてみる ←今回はここ
  7. クラスタ環境をつくってみる
  8. RMIで通信してみる(コンテナ編)

先月のGCPの請求が届いたんだけど49円で、300ドルを使いつくす気配がないたけだです。
DockerもGCPでコンテナ管理も、よくわかってないけどやっていくぞ!

Dockerイメージをつくろう

まずは、ローカルでコンテナを作ってRMIのサーバ側だけを動かしてみようという方針。
GCPコンソールからCloud Shellを起動して、vi DockerfileでDockerfileを作る。 このDockerfileでコンテナの中身をつくるらしい。

というわけで、以下を記載して保存。
うん、どっかのサイトからコピペしてきたんだ。

で、この最後のCOPY RmiServer.jar .ってところで、jarファイルをコンテナへコピーしております。
というわけでRmiServer.jarをアップロードしておく。 右上のほうのボタンからファイルをアップロードでできます。
f:id:takeda_san:20171203210853p:plain 便利すぎる…

コンテナを動かしてみる

よし、コンテナをうごかすぞ!
のまえに、さっき作ったDockerfileをビルドしないといけないようです。
docker buildってコマンドでできるらしい。

docker build -t gcr.io/[プロジェクトID]/gcp-rmi:v1 .

プロジェクトIDはダッシュボードのところに書いてあった。
なんか、わやわやーっと出力されて、どうやらコンテナイメージができたようです。

Successfully built hogehoge
Successfully tagged gcr.io/[プロジェクトID]/gcp-rmi:v1

うし、さっそく起動してみよう。
docker runってコマンドでできるらしい。

docker run -it -p 1099:1099 gcr.io/[プロジェクトID]/gcp-rmi:v1

-itってオプションを付けると起動したコンテナ内でいろいろコマンドが打てる。
つけないと、すぐ終了しちゃうみたい。
一応ポートフォワーディングしてるけど、今回は使わない。

で、まずはjarファイルがちゃんとコピーできてるか確認。

# ls
RmiServer.jar  bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

素晴らしい。
あとは、いつも通り起動。
ちなみに、ポートを起動時に指定できるようにしました。
あと、ログをちょっと出すようにしました。

# export CLASSPATH=./RmiServer.jar
# rmiregistry &
# java -jar ./RmiServer.jar 1099
server start
port:1099
server init finish

うん、ちゃんと起動したみたい。

おかたづけ

試行錯誤で作ったコンテナの残骸とか、起動しっぱなしのコンテナをおかたづけします。
docker stop CONTAINER IDdocker rm CONTAINER IDでいちいち止めるのめんどくさいよね。

qiita.com

docker stop $(docker ps -aq)
docker rm $(docker ps -aq)

実行結果。

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

うん、スッキリ。

JavaからKotlinにクリック一つで変換できるって本当ですか?

Kotlinスタートブック -新しいAndroidプログラミングを読んで、Kotlinをやっていく気持ちが高まった。
けど、いざ自分でいろいろ作ってみようって時にどう書いたものかと、ひとり悩んでいたんですが、IntelliJJava→Kotlin変換できるらしいですね。
おー、とりあえず変換してみてどんなもんか見てみよう。

というわけで、前に書いたRMIのプログラムを変換してみよう。
変換はツールバー->Code->Convert Java File to Kotlinからできるぞい。

サーバとインタフェースを変換してみた。

サーバー

Java

Kotlin

インタフェース

Java

Kotlin

かんそう

特にエラーとかなく、すいすい変換できた。
今回は簡単なプログラムだから、あんまり見た目が変わらんかったけど、
もうちょっと大きいクラスをいかにKotlinらしく書き直していけるかが、Kotlin力ということか…
Kotlin道の歩み方が少しわかった。

JJUG CCC 2017 Fallにいってきましました

イベント参加の感想を書くとポエム感でるのでどうなのよ。と、いらんことで悶々と悩むこと二日間。
書きたいものは書く。発信だいじ。

年齢も経験も関係ない!ステップアップするためのJavaコミュニティ活用術

朝から行ってきました。
前回もJJUG CCCには来ていたのですが、コミュニティへの参加というよりはJava界隈のナウいモノを探しに来ていたので
なんとなくJava day Tokyoみたいなカンファレンス的な気分でした。
でもなんか、コミュニティって発表者との距離も近いし、懇親会もあったりで違うよなぁ。何が違うんだろうか…
と、ぼんやり考えていたので是非とも聞きたい!な内容でした。

内容的には、発表者の方のJJUGとの出会い、かかわり方を実例に、コミュニティではどんなことができて、どんなことをするのがオススメなのかというのものでした。
前向きな言葉と具体的な行動例で、ちょっと登壇なりその他発信活動がんばってみようかな、という気持ちになりました。

10年前のレガシーシステムをサーバーサイドKotlinでフルリニューアルしている話

赤べこのKotlin本を注文していた私にはタイムリーな内容。
単に開発の話だけではなく、技術選定の苦労や経営陣の説得というところまで内容に含まれていたので、かなり勉強になりました。
こういうエンジニアになれたらカッコイイよねぇ。あこがれる。
また、Rubyの開発者にとって親しみやすいというのは意外でした。
ScalaとかJavaの比較はよくあるけど、そいういうもんなのね。
Kotlinやっていく気持ちが高まりました。私もはやく、ことりん(^ω^)ペロペロしたい。

あとは、Spring BootとDomaってよく聞くけどなんじゃろなって。

Spring Bootの本当の理解ポイント

というわけで、さっそく聞きに行くやつ。
Springってなんだよ。Spring MVCとかSpring FrameworkとかSpring Bootとか何なんだよ。オイ、Java EEとどう違うんじゃ。
という感じの理解度なので。
最初のSpringって何という内容はありがたくて、ありがたくてしょうがなかった。
ここだけで来てよかった感がすごい。

各種機能を聞くにあたって、過去にオレオレフレームワークとして泣きながら作った機能が、洗練された形で入ってて無知ってアカンな…と。
集約されているとはいえ、アノテーション多くて覚えるの大変そうだけど、いくつかパターン覚えればやっていけるやつなんかな。
実際使って、どんなもんなのか試してみたい。
(会社で研修受けさせてくれないかな…)

帰宅

このセッションまでで『なんか、ご飯食べたら眠くなった』というアレな理由で帰宅しました。
夜中に目を覚ましてTwitterを眺めていたら、懇親会参加しとけばよかったなぁと少し後悔。
お酒飲みながらLTを見るなんて、すごく楽しそう。
次回、懇親会参加へと決意をするJJUG CCC 2017 Fallでした。

GCPでもJavaがしたい その3

作業記録的なやつです。

作業予定

  1. GCPアカウント作成
  2. Webサーバをたててみる
  3. JREをいれて何か動かしてみる
  4. RMIで通信してみる ←今回はここ
  5. Dockerイメージをつくってみる
  6. クラスタ環境をつくってみる
  7. コンテナを動かしてみる
  8. RMIで通信してみる(コンテナ編)

…ちょっとやる内容変わってるけど気にしない。 JavaFXでクライアント作るのが、ちょっとめんどくさかっただけ。

なぜRMIなのか

Javaでサーバ通信で簡単なやつ…と考えたときにJavaSEだしコンソールで簡単にできそうという理由。
あとポート開けたり、セキュリティの設定で躓く姿が今から想像できてワクワクするから。

コード

クライアントから送った文字列にちょっと付け足して送り返すだけのやつ。
見づらいので記事にコードを書かないでgithubに上げたのを貼り付ける。
ナウイ。

インタフェース

サーバ

クライアント

ローカルで動作確認してみる

なれないIntelliJでやったので、これだけで3時間ぐらいかかったのは秘密。

モジュールの配置の仕方

このコードをサーバ側用とクライアント用に分けてjarファイルとして出力する。
RmiServer.jar→サーバ用
RmiClient.jar→クライアント用

rmiregistry起動編

クラスパスを指定する方法で起動します。
例えばworkってディレクトリにjarを入れてあるって前提。
あと無駄にJava 9でやる。

set CLASSPATH=C:\work\RmiServer.jar
"C:\Program Files\Java\jre-9\bin\rmiregistry.exe"

もちろん、パス通してればrmiregistry.exeで大丈夫。

サーバ起動編

普通にjar実行。

java -jar C:\work\RmiServer.jar

クライアント起動編

起動時引数に接続先のホスト名を入れるようになっているので、localhostと指定してjar実行。

java -jar C:\work\RmiClient.jar localhost

実行結果

from server:こんにちは!!

インスタンスと通信をしてみよう

まずはファイルをアップロード

まず、インスタンスを生成して、jdk入れる。
そしてファイルのアップデートなんだけれど…どうやるんだ?ドキュメントを見に行こうか。
なんとコマンドでファイルがアップロードできるらしい。

gcloud compute copy-files [LOCAL_FILE_PATH] [INSTANCE_NAME]:~/
gcloud compute copy-files` is deprecated.  Please use `gcloud compute scp` instead

えぇ、非推奨なの…?
多分日本語のヘルプが古いんだね。
英語勉強しなさいってことだね。

というわけで、よくわからんのでWinSCPをインストールしてアップロードにします。
設定はここに書いてある通り。

インスタンスへのファイルの転送  |  Compute Engine ドキュメント  |  Google Cloud Platform

んで、WinSCPで使用するために秘密鍵と公開鍵が必要なんだけど、自分で生成して登録してあげなきゃならないみたい。
基本的には下の通りなんだけど、公開鍵をSSH認証鍵として登録するときにちょっとフォーマットを変えてあげなきゃいけないみたい。

GCEにPuttyから簡単接続する|apps-gcp.com|G Suite(旧:Google Apps) やGoogle Cloud Platform サービスについて紹介します

無効な鍵です。次の形式にする必要があります: <protocol> <key-blob> <username@example.com> または <protocol> <key-blob> google-ssh {"userName":"<username@example.com>","expireOn":"<date>"}

なので、ssh-rsa 公開鍵 hogehoge@gmail.comみたいな感じに書き換えて登録しておく。
そして、接続成功。
RmiServer.jarファイルをささっとアップロード。

いざ実行

まずはサーバ側の準備
クラスパスの設定~rmiサーバの起動
(jarは、とりあえずrootにおいてみた)

export CLASSPATH=/root/RmiServer.jar
rmiregistry &
java -jar ./RmiServer.jar 

そして、クライアントを起動してみる。

java.rmi.ConnectException: Connection refused to host: 10.142.xxx.xxx; nested exception is: 
    java.net.ConnectException: Connection timed out: connect

あっ…ですよねー。
接続失敗してるIPが内部IPに変わってるのが、気になるが先にファイアウォールの設定かな…
GCPのダッシュボードの検索窓からファイアウォールで出てきたVPCネットワークファイアウォールルール ってところから設定するっぽい。
これを参考にしながらTCPのポート1099を開ける。

dev.classmethod.jp

もう一度、実行。

java.rmi.ConnectException: Connection refused to host: 10.142.xxx.xxx; nested exception is: 
    java.net.ConnectException: Connection timed out: connect

う、うーん。
やっぱり、内部IPに変わってるのが気になるので調べてみる。

netbuffalo.doorblog.jp

あっ、これっすね。
サーバの起動時の引数に-Djava.rmi.server.hostname=[外部IPアドレス]を加えてあげる
なんか初回はサーバが立ち上がるまで、1分ぐらいかかった。
んで、どうやら1099ともうひとつ別のポートを開かなきゃいけないみたいなんだけど匿名ポートから任意のポートに変える方法が今いちわからなかった…
なので、tcp全空け。

dstn.appresso.com

ここのサイトに書いてある通りだと思うんだけど、濃すぎるキャラクターのせいで理解を阻害された感ある。
うん、いいわけ。
そして、リトライ。

java -jar -Djava.rmi.server.hostname=104.196.xxx.xxx ./RmiServer.jar
from server:こんにちは!!

GCPとは別なところでハマったけど、RMIの勉強になったからいいか。

まとめ

情報がとっちらかってるので、RMIしたいけどクライアントとサーバが別な時にやることまとめ。

クライアント編

とくになし。
いつも通りに起動しましょう。

サーバ編

  • ファイアウォールを設定しましょう rmiregistryで使うデフォルトポート1099とリモートメソッド呼び出し時につなぎに行くポート(匿名ポート)をTCPで開ける。

  • リモートメソッド呼び出し時につなぎに行く先の指定 -Djava.rmi.server.hostname=[外部IPアドレス]でつなぎに行く先を指定してあげる。
    ほかにも方法はある模様。

Java RMI ConnectException: Connection refused to host: 127.0.0.1 エラーの正しい理解と対策

あー、なんか疲れた。

GCPでもJavaがしたい その2

作業記録的なやつです。

作業予定

  1. GCPアカウント作成
  2. Webサーバをたててみる ←今回はここ
  3. JREをいれて何か動かしてみる ←今回はここ
  4. JavaFXのクライアントアプリケーションと通信してみる(たぶんRMIで)
  5. Dockerイメージをつくってみる
  6. クラスタ環境をつくってみる
  7. コンテナを動かしてみる
  8. JavaFXのクライアントアプリケーションと通信してみる(コンテナ編)

Webサーバをたててみる

インスタンスを作る

はい、サクッとWebサーバ作ります。
GCPのダッシュボードからインスタンスの作成を選択してインスタンスを新規作成。
今回のOSは、Linuxで、ファイヤーウォールのところでHTTPトラフィックを許可するにチェックを入れておきます。

NGINXを入れる

今回はNGINXを入れてヘローワールドします。
(これエンジンエックスって読むんだね)
おじさん知ってるよ、Apacheより最近はNGINXの方がナウいんでしょ。

というわけで、インスタンスの右端のSSHからインスタンスに接続。
いちいちターミナル起動しなくてよいのが素敵。
f:id:takeda_san:20171105215100p:plain

パッケージのインデックスを更新して、NGINXをインストール。
今までインデックスの更新なんて気にしてなかった…
Linux使うなら当たり前の作業っぽいよねコレ。不勉強ぶりよ…

apt-get update
apt-get install nginx -y

確認してみる

外部IPのところのリンクをクリックして、Welcomeページを表示する。
f:id:takeda_san:20171105215703p:plain

f:id:takeda_san:20171105215830p:plain

ほい。

Java環境を入れてみる

Open JDKのインストール

apt-get install openjdk-8-jdk

あれ、9もいけるんかなと思って

apt-get install openjdk-9-jdk

あ、いけた。

root@web-server:~# java --version
openjdk 9-Debian
OpenJDK Runtime Environment (build 9-Debian+0-9b181-4bpo91)
OpenJDK 64-Bit Server VM (build 9-Debian+0-9b181-4bpo91, mixed mode)

徐々にGCPJavaの影が忍び寄る。
次回、Javaのアプリを動かすぞ。

Gradleでビルドがしたい

作業メモ。

JavaのアプリケーションのビルドをMaven、Antで書いてJenkinsで実行みたいなことを今までやってきたのですが、
XMLの設定ファイルをいじったり、プロパティファイルを書いたりが、あまりにも精神力をすり減らす作業なので別のやり方無いかなぁ。
(XMLを人力で書くのが、人類には早すぎると思う)

jenkinsのパイプラインをGroovyで書いてて、ビルドもコードで書けたらいいのになぁと思ってたところ Gradleがそれっぽい?とうわけでGradleやっていきます。
さっそく、ホームページへ。

gradle.org

ご丁寧にOSごとに環境構築方法が書いてありますね。
Windows愛用者の私もニッコリ。

環境構築編

調達

へぇ、SDKMAN!ってやつでインストールするのがナウいのね。
ですが、今回は手動ダウンロード、アンド解凍。
ドキュメント入りのほうがよさそう、ということでComplete, with docs and sourcesって方にしました。

ファイルの配置

ドライブ直下にC:\Gradleって感じで、Gradleフォルダを新規作成。
そのなかに解凍したgradle-4.2.1フォルダを丸ごと入れる。

環境変数に追加

いつもの環境設定画面を開いて
ctrl+e -> 左側のPCで右クリック -> プロパティ -> システムの詳細設定 -> 環境設定
PathにさっきのパスC:\Gradle\gradle-4.2.1\binを追加。
環境変数、いつの間にか、一覧で表示されて編集できるようになってて感動した。
f:id:takeda_san:20171030225827p:plain

動作確認

コマンドプロンプトgradle -v f:id:takeda_san:20171030230007p:plain

すげー、一度も躓かずに動作確認できた。

とりあえずHello world

さっそく、Getting Startedをやっていく。
(なんだか動画の講座もあるっぽいぞ…。至れり尽くせり)

gradle.org

このなかでも、Creating New Gradle Buildsってのが初心者チュートリアルなんかな。

https://guides.gradle.org/creating-new-gradle-builds/

このチュートリアルの各種手順はUnixLinuxのコマンドで書いてあるみたいです。
前に紹介したcmderでやるか同じWindowsのコマンドに読み替えてやる必要がありそう。

takeda-san.hatenablog.com

build.gradleとは

build.gradleというファイルで、依存関係の解決やタスクと呼ばれる作業単位を定義するらしい。
タスクはjenkinsでもあったな。
つまりはスクリプトをこのファイルに書き込むことで、ビルド手順とするということだろうか。
build.xmlとかpom.xmlみたいなもんかね。
XMLを書かなくてよいのは良い。

Gradle wrapperとは

このビルド作業をほかの端末でやる場合に、同じ環境を作らねばならないのですが、このGradle wrapperを使うとコマンド一発で環境構築ができますよということらしい。

確かにgradle wrapperでできたgradlew.batを実行するとgradleのインストールと環境変数の設定をやってくれた。 (ダウンロードに少し時間がかかった)
もうひとつ新しく生成されていたgradlewUnixLinux用のシェルスクリプトファイルらしい。

properties

よくあるproperties形式のパラメータ指定もできるぜ。とのこと
設定値はgradlew propertiesで確認できるとのこと。
リリースバージョンとか、各種ディレクトリパスの定義はここでやればよさそうね。

コアタスク

よく使うような機能はコアタスクとしてあらかじめ定義されていて、すぐ使えるようになっているらしい。
このへんなんかAntっぽい。

タスクの定義と実行

こんな感じのcopyタスクを定義する。
(build.gradleファイルに書き込んでおく)

task copy(type: Copy) {
    from 'src'
    into 'dest'
}

んで、gradlew copyで実行。
どんなタスクが実行可能かはgradlew tasks --allで確認できる。
おー、見事にコピーされてる。

プラグイン

このコアタイプはプラグインという形で配布されている。
プラグイン構文で導入できるらしい。
ちなみにこのplugin構文はファイルの先頭に書かないと怒られるっぽい。
(taskの前なのかな)

ねんがんのHello World

task内でprintln 'Hello, World!'と書くことで、ねんがんのHello, Worldができる。
このチュートリアル内で使っているdoLastみたいな、Gradle内だけで使える文法(こういうのDSLっていうのね)は 別のチュートリアルに入っているので興味のある人は見てねってことらしい。

思ったこと

  • ビルドをスクリプトで書けるのはすごく良い、最高
  • wrapperで環境構築が簡単にできるのがよい
  • コアタスクがあるので、基本的な処理は自分で書かなくて済みそう
  • wrapperとかインターネット経由でファイルの取得ができない環境の場合はどうするんだろうか(Mavenだとお勝手リポジトリで代替できたが、どうやるんだろ)

GCPでもJavaがしたい その1

作業記録的なやつです。

作業予定

  1. GCPアカウント作成 ←今回はここ
  2. Webサーバをたててみる
  3. JREをいれて何か動かしてみる
  4. JavaFXのクライアントアプリケーションと通信してみる(たぶんRMIで)
  5. Dockerイメージをつくってみる
  6. クラスタ環境をつくってみる
  7. コンテナを動かしてみる
  8. JavaFXのクライアントアプリケーションと通信してみる(コンテナ編)

作業記録

なぜAWSではなく、GCP

QwikLabsでAWSGCPの入門クエストみたいなのをそれぞれやってみたんだけども
GCPのほうがUIがスッキリしてて、ヘルプも充実してるような気がしたので。
あと、Kubernatesを使ってみたい。

$300分無料らしい

これを書いている時点では$300分無料で使えるらしい。
ドキュメントをもうちょっと読んでみると$300使い切った後はアカウントが一時停止状態になるらしい。
これには、クラウド破産に震える私にも安心。

レッツ登録

既にあるgoogleのアカウントでクレカと住所情報を入れて無料トライアル開始。
しばらくして登録が終わると、QwikLabsで見慣れたGoogle Cloud Consoleがこんにちは。
これ、もうインスタンス作れるのでは?ということでやってみよう。

記念インスタンス

というわけで、自分のアカウントでは初インスタンス
今回はGUIからポチポチつくってみる。
左のメニューから[Compute Engine]をクリックして、準備完了までしばらく待つ。
VMインスタンスの青い[作成]ボタンを押す。

リージョンとゾーン

せっかくなので、東京のリージョンにしてみる。

リージョン…地域を示す ゾーン…インスタンスとディスクが共有できる単位(インスタンスとディスクは同じゾーンじゃないと共有できない) で、リージョンには1つ以上のゾーンが含まれる

ってことかな。
↓のめっちゃ詳しいヘルプ読んだほうが早いかも。

https://cloud.google.com/compute/docs/regions-zones/regions-zones?hl=ja

リクエストを投げる側と地理的に近いほどレスポンスが早いものらしい。
(FPSで海外サーバに入ると瞬間移動がつかえる現象を思い出す)
なので、日本人向けのサービスなら東京リージョンが良いってことなのかな。

いざ作成

リモートデスクトップで実際につないで動作確認をしたいのでWindows Server 2016をOSにして、一番したの[作成]ボタンをクリック。
(当たり前だけど、ちょっとライセンス使用料で月額が高くなるのね)

f:id:takeda_san:20171024224742p:plain

インスタンスの一覧に画面が変わって、さっき作ったインスタンスが立ち上がるのを待つ。
立ち上がったらインスタンス名をクリックして、VMインスタンスの詳細ページを開く。
リモートアクセスから[Windowsパスワードを設定]でログイン用のパスワードを設定する。
そのあとに隣の[RDP]ボタンからリモートデスクトップ接続用の.rdpファイルをダウンロード。
(クロームだとそのままブラウザで繋げるっぽいな)
さっそくつないでみる。

f:id:takeda_san:20171024225512p:plain

こいつはスゲェぜ。

あとかたづけ

使いもしないインスタンスを放置しておくと無料枠がどんどん減っていくようなので、あとかたづけ。
VMインスタンスの詳細ページから[停止]を押す。
(あとで気が付いたんだけど、これって、ちゃんとマシン終了してからのほうがよかったなぁ)
停止したらもう使わないので、[削除]を押す。
スッキリ。

請求額

ここまでやった後に、請求額を見てみたんだけど$0.00のままだった。
無料枠内は表示されないのか、リアルタイム反映じゃないのか。
毎日更新って書いてあるから、1日一回反映なんかな。