Tomcat containerにwarをデプロイするDockerfile

tomcat上で動いているアプリをk8s上で稼働させるためにdocker nizeしました。面倒くさいかと思っていましたが、意外と簡単だったので共有します。 以下のようなDockerfileを書けばよいです。

FROM tomcat:9.0.16-jre8-alpine

RUN rm -rf /usr/local/tomcat/webapps/*

COPY tomcat/server.xml /usr/local/tomcat/conf/server.xml
COPY target/awesome.war /usr/local/tomcat/webapps/awesome.war
EXPOSE 8080

CMD ["catalina.sh", "run"]

server.xmlについては、そのままデプロイするとwar名のcontext pathが設定されてしまうため、context pathがルートとなるように以下の設定を追記したserver.xmlで上書きしています。

<Host name="localhost"  appBase="webapps"
      unpackWARs="true" autoDeploy="true">

  <Context path="/" docBase="/usr/local/tomcat/webapps/awesome.war" reloadable="true" />
  <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
         prefix="localhost_access_log" suffix=".txt"
         pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>

簡単ですが、こんな感じでした

推測するな計測せよ

https://ja.wikipedia.org/wiki/UNIX%E5%93%B2%E5%AD%A6

UNIX哲学として知られている(直接にはUNIX哲学ではない、らしいです)格言です。

当社の某サービスには2000件程度(現時点では。どんどん増える見込み)のデータを取得している画面があるのですが、2秒ほどデータの取得に時間がかかっているためパフォーマンスチューニングを考えていました。

複雑な検索SQLが実行されているため、そこがボトルネックになっているだろうといろいろと調べてみたのですが、ふと「本当にここがボトルネックか?」と気になってプレゼン層からデータアクセス層までの各呼び出しで呼び出し時間を計測してみました。 その結果、実際にはSQLは0.5秒以内とそこそこ高速に実行されている事実がわかりました。

結局、本当に時間がかかっている箇所はアプリケーション層からプレゼン層に帰るときのドメインオブジェクトからDTOへの詰替えで、その処理の中でThread Safeにもかかわらずコストの掛かるインスタンス生成処理を繰り返していることが原因と突き止めました。

このように、パフォーマンスチューニングを行う場合は推測よりもまず本当にそこがボトルネックなのか計測をすることが肝心だな、と紹介した格言通りの経験をしたというポエムです。

なお、パフォーマンスチューニングをしようにもスパゲティだと難しくなります。 どこがボトルネックか探そうにもビジネスロジックが散在しているため、効果的に対策が可能な箇所が特定できないためです。

コーディング中、パフォーマンスの事を考えてアルゴリズムを工夫することがあるかと思いますが、 それよりもまずは可読性とメンテナンス性を重要視しましょう。 まず、ほとんどの場所ではパフォーマンスの問題はおきません。

そして問題が起きたとしても、可読性とメンテナンス性が高いコードであれば、パフォーマンスチューニングをすべき箇所はすぐに見つけられ、最適化も容易に行えるはずです。

以上、ポエムでした。

Spring Boot 1.5x -> 2.1.xへのマイグレーションで得られた知見

学習目的でちまちま検証してみました。 公式にマイグレーション手順のページはありますが、実際にやってみたところ多少独自の知見が得られたので超簡単ですが共有しておきます。

実際にやってみてハマったところ

JUnit4対応

  • Spring 5からはJUnit5サポートしていますが、素のままではJUnit4に対応していないので追加ライブラリを入れる必要があります。
  • そのライブラリを入れるだけでは動かず、TestConfigurationでDIコンテナに登録しているBeanの名前が衝突してJUnitの起動に失敗しました。
  • TestConfigurationなクラスにComponentScanをつけて欲しいBeanが存在するパッケージを指定して適当にDIへ登録していたのを、適当にScanしていたがゆえにTestConfiguration自身もScan対象になってしまっていたので、DIへ登録したいクラスをピンポイントでImportすることで解決しました。

Spring BootからSPAをホストする関連の設定の見直し

  • Spring Boot 1.5.xと2.1.xではホストする際に必要な設定に微妙な違いがあるのですが、それを失念しておりログイン直後にエラー画面に遷移する謎現象に悩まされました。
  • Qiitaで以前に投稿した自分の記事に助けられました。

Spring Securityのpropertiesが削除されている

  • 以前はproperties経由でSpring Securityのデフォルト設定の一部を変更できたのですが、それができなくなっていました。
  • 自分で設定キーを追加し、自分でその設定を読み出し、JavaConfigurationで設定を変更するといった追加対応が必要でした。

Spring SecurityのWebSecurityConfigurerAdapterがabstractからinterfaceに変更されているのでその対応

まとめ

やってみての感想は、「案外簡単」です。
そのため、アップグレードを検討している案件では事前調査に時間をかけるよりもとりあえず1日か2日程度かけてトライしてみたほうが良さそうだと思いました。
アップグレード後に起動すると親切なことにログにマイグレーションに必要な対応かそのヒントが表示されるので、それに従って設定なりコードなりを変更するだけで対応できそうです。
もちろん、テストはしっかりやる必要はありますが。

以上。

Clean Architectureを読みました

この本を読みましたので簡単なご紹介です

https://www.amazon.co.jp/dp/4048930656

構造化プログラミング、オブジェクト指向プログラミング、関数型プログラミングパラダイムの説明の説明から入り、SOLID原則を持ち出してOOPらしくコードの必要性とその概要を説き、 いわゆるアーキテクチャと言われるものがどういったことを関心事としているのかを説明し、それをClean Architectureとして体系化したものを紹介し、実現・構成するために各要素について何をどう考慮するのか解説すると言ったような流れの書籍でした(たぶん)。

いわゆる「アーキテクチャ」にまつわるエトセトラをとてもよくまとめてある良い本だと思います。

ただし、IDDD本のようなソースコードによる具体例がないため、いまいち、パッケージ(≒namespace)設計にはどう落とし込めばいいのかはわかりませんでした。

上記の2点から、アーキテクトを目指し始めた人や目指そうとしている人にとっての、最初の一歩を踏み出すためのガイドライン的な書籍として私は位置づけました。

具体的なコード例がないため、同じClean Architectureを採用していると主張しているアプリだったとしても、人によって解釈が異なり、パッケージ設計は様々になりそうです。

例えば私は、P200の図を素直にパッケージに落とし込むと、層構造を表現するため以下のようになると思います。

.
├entities
├outer ※名前がついてないので私独自のネーミングです
│├controller
│├gateway
│└presenter
└usecase

しかし、トランザクションスクリプトになれた人たちには、フラットに展開した以下のような構造のほうがわかりやすい傾向があるため、以下のようにする場合もありえそうです。

.
├controller
├entities
├gateway
├presenter
└usecase

SOLID原則についてピンポイントで指摘を入れておくと、これを読んでわかった気になるのは危険で、アジャイルソフトウェア開発の奥義などでより詳しく学ぶべきだと思いました。

https://www.amazon.co.jp/dp/4797347783

Let's Swagger

Let's Swagger

社内勉強会で使用した資料をはてな用にアレンジしたものです。

Goals

  • Swaggerって何か聞かれて答えられる程度の知識をみにつける
  • 具体的に何ができるのか、HowとWhatを知る

つゆばらい

  • 序盤英語です
    • 翻訳が面倒でした。ごめんなさい
    • 英語見ると蕁麻疹出ちゃう人はよそ見しててください
      • でも、英語できないとエンジニア人生かなり辛いです
  • Swaggerを使う準備として調べてみたことを発表しています

  • ってことは、私自身の実績はないですありませんでした

    • でも、参画中のプロジェクトでは使われています使ってると言える程度に関わるようになりました
  • 自分自身のために勉強したことを発表用に仕立て直してます

    • そのため、興味の対象が偏ってるかもしれません

What's Swagger ?

Ansower quoted from official Site

The World's most popular Api tooling.

Swagger is the world’s largest framework of API developer tools for the OpenAPI Specification(OAS), enabling development across the entire API lifecycle, from design and documentation, to test and deployment.

  • 要約すると(RESTful)APIの設計、文書化、テスト、開発を網羅した世界最大のフレームワークって書いてある
構成要素
  • DESIGN : Swagger Editor
  • BUILD : Swagger Codegen
  • DOCUMENT : Swagger UI

DESIGN (with Swagger Editor)

Design new APIs, or edit existing ones, in a powerful editor which visually renders your OAS/Swagger definition with concise, real time feedback and error handling.

  • 要はAPIの設計をエディター上でパワフルにやれるって書いてある

demo -> https://editor.swagger.io

BUILD (with Swagger Codegen)

Quickly build APIs by turning your OAS/Swagger definition into code, generating server stubs and client libraries in over 40 different languages, allowing for development and prototyping.

  • 要約すると定義ファイルからコード生成できるよって書いてある
# demo
$ swagger-codegen generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l nodejs-server \
-o ./ist-swagger-demo
$ cd ist-swagger-demo
$ tree .
.
├── README.md
├── api
│   └── swagger.yaml
├── controllers
│   ├── Pet.js
│   ├── Store.js
│   └── User.js
├── index.js
├── package.json
├── service
│   ├── PetService.js
│   ├── StoreService.js
│   └── UserService.js
└── utils
    └── writer.js
$ npm install
$ node .

DOCUMENT (with Swagger UI)

Visualize your API's resources from its OAS/Swagger definition and generate beautiful, interactive documentation that can be hosted in any environment, allowing your end consumers to easily get started with your API.

  • 要約すると定義ファイルから綺麗な仕様書生成するよって書いてある
# Continuing the previous, execute followings
$ npm install
$ node .
# then, go to http://localhost:8080/docs/

なぜSwaggerを使うのか

その1:API仕様書を元にコード化できるから

  • YAML/JSONで仕様書が書ける
  • API定義ファイルから
    • 多数の言語のクライアントコードなどが生成できる
    • サーバもさくっと作れる
      • mockとして使うもよし、ベースに使ってもよし
  • トップダウン形式というらしい

その2:コードからでもAPI仕様書の自動生成ができるから

その3:デファクタスタンダードだから

  • まだなってない気がするけど、たぶんなる、たぶん…。
  • フォーマットについて、一度学習すれば他の現場他の案件でも同じ
  • そのフォーマットを見慣れることになるので、見落としが減る

今回はボトムアップ形式について見てみましょう

  • サンプルアプリを作ってみた
    • SpringFoxを適用して、Swagger Spec自動生成
    • からのSwagger-UIで仕様書の出来栄えを見ていく

デモ用サンプルアプリ

git clone https://github.com/kogayushi/swagger-demo.git

どんなアプリか

Identity Manager

  • ID認証して認証情報を返すだけの簡単なお仕事

Framework

  • Spring Boot

Protocol

とりあえず、完成したSwagger-UIを見てください

$ cd swagger-demo
$ ./gradlew bootRun
# go to http://localhost:8080/swagger-ui.html

git commit logを追います

Swagger用アノテーションなしのプレーンな状態からアノテーションを張っていくごとに徐々に育っていく様子にご注目ください

https://github.com/kogayushi/swagger-demo

Step 1

  • Apply Spring Fox for swagger
変更点

f:id:kogayushi:20180413233949p:plain

Swagger UI

f:id:kogayushi:20180413234008p:plain

ダメなところ
  1. リクエストパラメーターがわかりにくい
  2. レスポンスパラメーターがわかりにくい
  3. formパラメーターでは具体的に何を送るべきかわからない 4.サンプル値がない 5.model見ると全部optionalってありえない 6.定義してない4XX Http Statusがならんでる
  4. 401/403は使ってない
  5. 5XX Http Statusがない
    • ありえない
  6. 少なくとも予期せぬエラーで500は絶対に返すことある

Step 2

  • Declare input variable as to be independen from form data
  • 独立した項目として入力値を定義する
変更点

f:id:kogayushi:20180413234026p:plain

Swagger UI

f:id:kogayushi:20180413234039p:plain

Step 3

  • Disable default response definition
  • デフォルトレスポンスの定義を消す
変更点

f:id:kogayushi:20180413234050p:plain

Swagger UI

f:id:kogayushi:20180413234102p:plain

Step 4

  • Declare proper response http status
  • 返す可能性のあるHttp Statusを正しく定義する
変更点

f:id:kogayushi:20180413234112p:plain

Swagger UI

f:id:kogayushi:20180413234147p:plain

Step 5

変更点

f:id:kogayushi:20180413234202p:plain f:id:kogayushi:20180413234209p:plain

Swagger UI

f:id:kogayushi:20180413234225p:plain f:id:kogayushi:20180413234231p:plain f:id:kogayushi:20180413234238p:plain

Step 6

  • Add descriptive annotation of Swagger into Error response DTO classes.
  • Swaggerの記述用アノテーションをエラーレスポンスのDTOクラスに付与する
変更点

f:id:kogayushi:20180413234309p:plain f:id:kogayushi:20180413234315p:plain

Swagger UI

f:id:kogayushi:20180413234325p:plain

課題

  • エラーレスポンスの例が全てのHttp Statusでおなじになってしまっている
  • エラーレスポンスの定義を全てのコントローラーで定義しなければならなさそう

終わりに

このようにアノテーションを張っていくだけで仕様書が出来上がってしまうというすぐれものです。 みなさんも、ぜひご活用ください。

キャリアアップに必要な物量(勉強時間)について真剣に考えてみた

キャリアアップに必要な物量(勉強時間)について真剣に考えてみた

社内ブログの記事を個人ブログ用に修正したものです。


私の経歴

  • 2009/4に医療系のSIerに新卒入社
  • 2014/7に人材派遣業の会社に転職し、派遣されて某大手ECサイトの会社へ。Webエンジニアへのキャリアチェンジ。
  • 2017/1に今の会社に入社

キャリアチェンジ時に考えていたこと

Web業界は初めてで現時点では実力も実績もない この業界でキャリアアップするためには、ひたすら努力(勉強)することしか思いつかない それ以外に能力を上げる方法があるとも思えないし… と思って勉強命で頑張ってきました


転職したあとから思った

でも、、、 いったいどれくらい勉強すればいいんだろうね?

そんなの人それぞれだと思うけど、 なんか定量的で納得感のある数字が欲しい


みなさんは一ヶ月にどれくらい勉強してるのでしょう?

  • 0時間(一切してない)
  • 5時間~
  • 10時間~
  • 20時間~
  • もっと(20時間以上)

平均は?

Paizaが行ったアンケートによると 週に5時間以上(月20時間以上)らしいです

じゃあ、その人達の先を行こうと思ったら、 何時間勉強すればいいんでしょう?


少し話がそれます


ランチェスター法則(戦略)ってご存知ですか?

Wikiより

ランチェスターの法則ランチェスターのほうそく、英:Lanchester‘s laws)とは1914年にフレデリック・ランチェスターによって発表されたオペレーションズ・リサーチにおける戦闘の数理モデルである。


第一法則

※読まなくていいです

ランチェスターの第1法則はいくつかの前提に基づいた場合にだけ適合する一次方程式の戦闘モデルである。ランチェスターの理論でその前提は次のように整理される。 1.両軍は相互に射撃を行うが、互いに相手の部隊の全てを有効な射程に収めている。 2.両軍の部隊の戦力は兵員と武器の性能によって同様に決まっているが、両軍の部隊が発揮できる戦闘効果は異なっている。 3.両軍とも相手が展開している地点の情報を持たない。したがって、射撃の効果がどれほど得られるか不明なまま戦場の全体に対して射撃を行なう。 4.両軍とも戦闘において残存する両軍の部隊は展開しているが、その部隊の配置は決して形式的に定まることはない。 このような前提を踏まえれば、狭隘な地形において対峙している一対一の戦闘部隊による戦闘をモデル化したものと見做すこともできる。このモデルはいくつかの要因を含んだ次のような方程式として示すことができる。


第二法則

※これも読まなくていいです

ランチェスターの第2法則は二次方程式を用いた戦闘モデルを示したものであり、ランチェスターは既に述べた第1法則の前提のうち1と2については同じように導入しながらも二つの異なる前提を設けて理論を構築している。 1.戦闘において残存している部隊は互いにあらゆる時点で相手の部隊が配置されている地点についての情報を持つ。 2.戦闘における両軍の部隊の射撃は相互に相手の残存する部隊に均等に分配する。 省略した2つの前提を含む第2法則の4つの諸前提は各部隊が敵情について正確に把握し、かつ相手に対して無駄のない適切な射撃が可能であることを示している。この戦闘モデルを調べると、第1法則で示された戦果に対して興味深い相違点が認められる。


(゚Д゚)ワケワカラン…

きっとみなさん、今こんな顔


小難しいことは置いといて…

要するに弱者が強者に勝つ、あるいは強者よりも優位に立つ(差別化する)ための戦略のことを指すらしい これ、勝ちに行きたい(稼ぎたい)ITエンジニアにも当てはめることできるんじゃなかろうか

よし、じゃあ具体的に当てはめて考えよう そして、他を蹴落として優秀なエンジニアになって高収入になってウハウハしよう! と、私は考えました


と思って具体的に考えてみた

ランチェスター法則には 攻撃力=(兵力)^2×(武器性能) という計算式があるらしい

これを経営に置き換えると 経営(人生)=素質×(時間)^2+過去の実績 となるらしい


さっきの勉強時間に当てはめると式はこうなるんじゃね?

エンジニアだと 能力(単価)=素質×(勉強時間)^2+過去の実績 こうなる(たぶんね)


おk,能力値の求め方はわかった

能力(単価)=素質×勉強時間^2+過去の実績 の式だと、素質と実績は定数 となると、変えることができるのは勉強時間だけ

さて、、、 人と同じかそれ以上の能力(単価)にするには何時間勉強すればいいのか、まだわかんないんだけど…?


また別の頭の良い人はこうもいいました

コロンビア大学のバーナード・O・コープマンが他の人よりどれくらい働けば成果が出せるのかシミュレーションしたそうです その結果によると才能が並か劣った人でも…

  • 人の2倍で他の人と同等の成果がだせるようになり
  • 人の3倍で大体勝てるようになり
  • 人の4倍で圧勝できるレベルになる

なるほど

  • 人の2倍勉強したら並
  • 人の3倍勉強したら優秀(単価100万とか?)
  • 人の4倍勉強したら神(単価130万とか?)

ってことか( ゚д゚ )クワッ!!


必要な勉強時間はどうなった?

能力=素質×勉強時間2+過去の実績 で、『勉強時間』は乗数だから 人の2倍とは√2で1.414倍 人の3倍とは√3で1.732倍 人の4倍とは√4で2倍 すればいいってことになる


つまり

人の2倍=20h × 1.414 = 約28h 人の3倍=20h × 1.732 = 約35h 人の4倍=20h × 2 = 40h


結論

人より劣っていると思うなら とりあえず月に28時間勉強してみましょう 人より秀でたいと思うなら 月に35時間勉強しましょう 単価130万もらってウハウハになりたいなら 月に40時間勉強しましょう


ただ、体感的には…

そんなに周りの人勉強してない気がする アンケートはpaizaなので勉強家ばかりのデータ 業界全体で平均とると、10時間未満とかな気がする 人の2倍=10h × 1.414 = 約14h 人の3倍=10h × 1.732 = 約17h 人の4倍=10h × 2 = 20h じゃないかなぁ。 誰か業界全体で平均とってみてほしい。


続きがありまして…

バーナード・O・コープマン氏によると

成功するにはこれを10-15年続ければいいそうです

コツコツ頑張りましょう!


ちなみに私の勉強時間は?

f:id:kogayushi:20180317141716p:plain 記録をつけ始めた(勉強本気になった)のは2015/1/1からです。 2017/03/31時点での総計勉強時間は984時間のようですね。

984/((12*2)+2)=約37h

圧勝する(単価130万以上)になるにはこのペースのままで あと最低でも8年頑張る必要がありそうです ※2017/3/31時点の話

コツコツ頑張ります。

オブジェクト指向プログラミングを学ぶのに適切な書籍と私がおすすめする読む順番

オブジェクト指向プログラミングを学ぶのに適切な書籍と私がおすすめする読む順番

何故かいたか

同僚Aが緑のデザパタ本読んでたり、同僚Bが他の人が読んでる本が気になるっていってたり、後輩Cが会うたびにおすすめの本を聞いてくるので、それらにちなんで、オブジェクト指向プログラミングを習得するためにこの順番でこの本を読むと良いのではないかということを伝えるために、私的な案を考えてみました。

短くまとめてはいますが真剣に考えています。

真剣に考えてみた結果、彼らに伝えて終わりにするのがもったいなくなってしまったのでブログに書いておくことにしました。

オブジェクト指向プログラミングが学べる書籍たち

私が読了済みの本の中から選んでいます。スムーズに理解が進むと思われる順番に並べています。

前提言語はJavaで言語構文にも十分詳しいことが大前提です。

  1. 現場で役立つシステム設計の原則
    • OOPらしさの雰囲気がわかります
    • 入り口に最適です。OOPがどう良くて嬉しいのか、平易でわかりやすく書かれています。
  2. テスト駆動開発
    • OOPらしいコードにたどり着く道筋がなんとなく見えます
    • そういう用途にも使えるというだけで、主題はテストコードです。
  3. リファクタリング
    • 手続き型からOOPらしいコードへ導く道筋のカタログです(リファクタリングが主題の本ですもんね)
    • リファレンスとして手元においておくとよいでしょう。
  4. パターン指向リファクタリング(絶版だが頑張ればまだ手に入る…)
    • さらにもう一歩踏み込んで、落とし所となるデザインパターンへ導く手法を主題にしています。
    • (3)と同じくカタログ化されています。リファレンスとして手元においておくとよいでしょう。
  5. Java言語で学ぶデザインパターン入門
    • (1)から(4)である程度OOPデザインパターンに対する理解が深まっているはずなので、このタイミングでやっとアカデミックにアプローチします。
    • 断片化しているデザインパターンの知識をここで体系的に纏めます。
  6. ドメイン駆動設計
    • ここからOOPを離れていきます
    • OOPをベースに、価値あるソフトウェアを戦術的に・戦略的に構築していく方法論が学べます。
    • いわゆる鈍器です。高いです。しかも抽象的で難解です。覚悟をもって読んで下さい。
  7. 実践ドメイン駆動設計
    • (6)の10年後に出た書籍です。DDDを具体的にコードに落とし込むとどうなるかにフォーカスしています。
    • 相変わらず、鈍器です。高いです。
    • CQRSやイベントソーシングなど技術的な観点が強めに入ってきます。
    • 実装例が出てきますが正解例ではないです。参考にするのはいいですが利用する場合は状況やプロジェクトの嗜好に合わせてアレンジしましょう。
    • これ読んだらもう一度#6読み直したほうが良いです。

その他のおすすめ(未読)

以下の書籍は私もまだ読んでいませんが、レビューなどを見る限りではなかなか良さそうです。これから読みます。

以上。