Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JavaでやってみるThe 12 Factor App

Yu Watanabe
November 11, 2014

JavaでやってみるThe 12 Factor App

Japan Java Users Group Cross Community Conferrence 2014 Fall

Yu Watanabe

November 11, 2014
Tweet

More Decks by Yu Watanabe

Other Decks in Technology

Transcript

  1. Javaでやってみる   The  Twelve  Factor  App JJUG-­‐CCC  2014  Fall  

    R1-­‐5   ベルサール西新宿   2014-­‐11-­‐15(Sat)
  2. 自己紹介 •  渡辺  祐   •  (株)ビズリーチ   •  @nabedge

      •  hCp://mixer2.org   •  hCp://nabedge.blogspot.jp   2
  3. 注意 •  12-­‐Factorの主張の是非はここでは議論しない。   •  1要素  ⇔  1ツール/ライブラリで解決ということはない。   • 

    12要素全部やらないとダメってことでもない。   •  12-­‐factorに書いてある通りにやるわけでもない   (臨機応変に解釈してアレンジ) 5
  4. 主に使う道具 •  Java7  or  higher   •  Spring  Framework  4.x

      •  Spring  Boot   •  Tomcat-­‐embed  7  or  higher   •  maven  (gradle)   •  Sonatype  NEXUS   •  Jenkins 6
  5. 話の順序 VII  ポートバインディング   IX    廃棄容易性   XI  

     ログ   III    設定   V    ビルド、リリース、実行の分離   II    依存関係の明示的な宣言   VI    ステートレスなプロセス   最後に番外編 7
  6. 結論を先に •  [CATALINA_HOME]/webapp  に   foobar.warを置いてTomcatを   起動する    

    •  開発したアプリの中で、その   いち依存ライブラリたるTomcatが   ポートを開いてリクエストを待つ。 11
  7. そのまま使おうとすると public  stadc  void  main(String[]  args)  {    Tomcat  tomcat

     =  new  Tomcat();    tomcat.setPort(8080);    tomcat.addWebapp("/”,      new  File(“/var/webAppDir)        .getAbsolutePath());    tomcat.start();    tomcat.getServer().await();   } 13
  8. SpringのBeanとしてTomcatを定義 @Configuradon   public  class  WebMvcConfig  extends  WebMvcConfigurerAdapter  {  

     @Bean    public  EmbeddedServletContainerFactory   embeddedServletContainerFactory()  {      TomcatEmbeddedServletContainerFactory  factory          =  new  TomcatEmbeddedServletContainerFactory();      factory.setPort(8080);      factory.setUriEncoding(“UTF-­‐8”);      factory.setContextPath("");   } 15
  9. MainメソッドでSpringを起動 public  stadc  void  main(String[]  args)  {    SpringApplicadonBuilder  builder

           =  new  SpringApplicadonBuilder();    builder.sources(WebMvcConfig.class);    ConfigurableApplicadonContext  context        =  builder.run(args);    context.registerShutdownHook();   16
  10. Tomcatのバージョンアップもお手軽 <dependency>    <groupId>org.apache.tomcat.embed</groupId>            

     <ardfactId>tomcat-­‐embed-­‐core</ardfactId>              <version>7.0.56</version>   </dependency>   <dependency>    <groupId>org.apache.tomcat.embed</groupId>              <ardfactId>tomcat-­‐embed-­‐logging-­‐log4j</ardfactId>              <version>7.0.56</version>   </dependency> 19
  11. 高速な起動? あきらめよう •  理想: 一ケタ秒   •  現実:  20秒〜30秒  

    – サンプルアプリ程度なら10秒以内   •  Web•ogicよりは速かろう...   22
  12. @PreDestroy   public  void  lazyUpdate()  {    //  例:DB操作を遅延実行するメソッド  

    }     @Bean(destroyMethod=“close”)   public  DataSource  dataSource()  {    //  例:DBのデータソース生成メソッド   } 24
  13. public  stadc  void  main(String[]  args)  {    SpringApplicadonBuilder  builder  

         =  new  SpringApplicadonBuilder();    builder.sources(WebMvcCfg.class);    ConfigurableApplicadonContext  context        =  builder.run(args);  //  ここで起動    context.registerShutdownHook();   } 25 Springならメソッド1個呼ぶだけ
  14. アプリはどこで動く? •  Windows7  +  Eclipse   •  OracleVirtualBox  +  CentOS

      •  Dockerコンテナ   •  AWSのEC2   •  Heroku   •  オンプレミス   30
  15. ※  SYSLOGに中継したい場合 •  Logback(Log4jも)のSyslogAppenderはUDPを 使うのでログのロストが怖い   •  Java  Service  Wrapper提供のラッパーのログ

    中継機能が便利   – Linux,Win,MacOS用の各バイナリあり   – 詳しくは  hCp://wrapper.tanukisowware.com/ 33
  16. •  Spring  Framework    commons-­‐logging   •  Tomcat    log4j

     または java.udl.logging   •  他のライブラリ    slf4j、commons-­‐logging、log4j   •  自分のライブラリ    slf4j 35
  17. Slf4jのブリッジライブラリで集約 36 log4j log4j-­‐over-­‐slf4j commons   -­‐logging jcl-­‐over-­‐slf4j Slf4j-­‐api logback

    ConsoleAppender 従来型ライブラリは   すべて依存関係から除 外(exclusion)しておく!
  18. logbackの設定 •  すべてConsoleAppender   •  以下二つは変数化して外部から調整可能に しておく。   – ログのレベル(DEBUG  /

     INFO)   – タイムスタンプの有無   •  例:ローカル環境で開発中はタイムスタンプ有り   •  例:本番環境では、ログ集約システムの側で   タイムスタンプを付加する 38
  19. ところで、GCログどうする? •  フォーマットが独特すぎて   他のログと混ぜると….   •  どうしようもないかもしれない。   ログの先頭に任意の固定プレフィクスでも

      付けられればいいんですが…   •  -­‐Xloggc:/var/log/gc.log..  とかはもうやめて、 JMX経由でGC状況をモニタリング?   39
  20. だから「OS環境変数」 1.  LinuxでもWindowsでも   OS環境変数の設定方法はほとんど同じ。   2.  気の利いたライブラリの多くはOS環境変 数からの設定値読み込みに対応してい る。

      3.  対応していなくても起動時のコマンドライ ン引数にOS環境変数をあてるとか。   4.  どうせ ansible/chef/puppet  で自動設定 するし。 43
  21.  <logger  name=”com.example.myapp"      level="${AP_LOG_LEVEL:-­‐DEBUG}"  /> 44 上の“$AP_LOG_LEVEL”  変数の優先順位  

    1.   logback.xml上のproperty値   2.   Javaシステムプロパティ        -­‐DAP_LOG_LEVEL=INFO   3.   OS環境変数        export  AP_LOG_LEVEL=INFO   4.   上記のどこにも無い場合にはDEBUG  
  22. SpringBoot流 設定値の埋め込み方 @Component   public  class  Foo  {    

     @Value(“foo.bar”)    private  String  bar  =  “hoge”;  //  default値       } 46
  23. さっきのfoo.barの値の変え方 1.  コマンドライン引数   java  –cp  …  -­‐-­‐foo.bar=xxxxx  //ハイフン2個  

    2.  OS環境変数   3.  コマンドラインで指定した位置にある   ”applicadon.properdes”   4.  クラスパス直下のapplicadon.properdes   5.  ソースコード上の値   47 実際はもう少し細かいので詳細は   hCp://docs.spring.io/spring-­‐boot/docs/1.1.7.RELEASE/reference/html/boot-­‐features-­‐external-­‐config.html
  24. 一方、これもある意味NGらしい •  「サーバにリリースだ!」   1.  ソースをチェックアウト   2.  設定ファイル差し替え  

    3.  mvn  compile  package   4.  app.warの完成   5.  scpして   6.  sshでAPサーバ再起動 53
  25. ビルドという作業 55 VCS checkout mvn        compile  

       package jar mvn        deploy   パッケージ   リポジトリ GOAL
  26. ポイント •  「ビルド」の結果はjar(war)という   バイナリ   •  バイナリは   パッケージリポジトリサーバ

      (以下PKGリポジトリ)にdeploy(格納)   しておくものである   •  MavenもGradleもバイナリ間の依存性 解決にはPKGリポジトリの存在が必須 56
  27. PKGリポジトリを構築しておく •  Sonatype  NEXUS   •  Ardfactory   – Bintray?  

    •  Apache  +  mod_webdav   (おすすめできない) 57
  28. ビルドという作業(再掲) 58 VCS checkout mvn        compile  

       package jar mvn        deploy   パッケージ   リポジトリ GOAL
  29. リリースという作業 59 PKGリポジトリ 1.  mvn  copy-­‐dependencies   2.  zip  

    3.  scp   サーバ上でunzip •  自分が開発したアプリjar   •  依存ライブラリjar GOAL
  30. 実行という作業 60 $  java  \    –cp  “jar群の展開dir/*”  \  

     com.example.MyAppMainClass ※設定値はOS上に環境変数として保存済み “*”(ワイルドカー ド指定)でおk   (java6以降)
  31. 63 II      依存関係の管理   III    設定  

    V      ビルド、リリース、実行の分離 Javaアプリでは、下の4つ全てが絡み合って   3要素が成立   1.   ビルドツール   2.   PKGリポジトリ   3.   OS環境変数(chef/puppet/ansible)   4.   CIツール  
  32. いろいろ難しいので •  Sdckyセッション +  ELB  でいいのでは。   •  Tomcatのセッションストアプラグイン (keyValue,

     RDBMS)は   serialize/deserialize  がらみでいろいろトラブル   •  今回は、いくつかのプランの紹介のみ 69
  33. プランB:  Memcached •  memcached-­‐session-­‐manager   – Tomcatのvalveとして使うプラグイン   – SpringFrameworkとは無関係に動かせる   • 

    あくまで個人的な検証結果:   – SpringMVC  +  SpringSecurity  +  FlashScope変数を 組み合わせるとserialize失敗の例外が出やすい 71
  34. *.war,  web.xml,  JSP禁止 •  Servlet3.xでGO   •  src/main/webapp  すら無しの方向で  

    •  ビューはThymeleafかMixer2で。   – src/main/resources/templates  に配置   •  こうすると、もうwarに固める必要なし。   •  *.jar群をクラスパスに入れてjavaコマンドで 起動(単純!)   –  SpringBootの独自one-­‐jar形式は、、、 74 あくまでも個人的な意見です