Ch3 : Play command & build & deploy
[Introduce]
Play本身的建置是用sbt工具來建置環境,sbt的設定檔build.sbt,可以對自身的專案做版本的控管,也可以協助你,引用其他專案相關的library。在Play的環境下的建置,我們使用的是activator關鍵字再加上指令.來讓我們去建置專案。以下就來介紹Play建置部署與常用指令。
Learning a new technical. you must be practice , practice , and more practice.
[build.sbt]
build.sbt本身可以用來定義該專案的名稱與版本,當我們使用Play去建置時,會產出相關的jar檔可以使用,也可以使用其他專案或別人的library(jar)來幫助自己的專案開發與使用。下面是簡單的範例,可以參考與使用。
name := "myFirstApp" <-專案名稱
version := "1.0.0-SNAPSHOT" <-專案版本
libraryDependencies ++= Seq( <-這個意思是,我們專案所需要相依性的library,會依照下面的順序,依據尋找
// javaJdbc,
// javaEbean,
cache, <-play的/repository/cache目錄,裡面存放play相關的lib
filters, <-play內建的filters,可以支援gzip的網站回覆資訊
"com.typesafe.play" % "play-json_2.11" % "2.3.4", <-這邊是範例,我們可以自定義要使用的lib來使用
)
play.Project.playJavaSettings <-這個宣告定義很重要,主要讓我們play專案所引用的基本lib是以java為基準
resolvers ++= Seq( <-這個意思是,當相關lib找不到時,會再依序照你定義的目錄或網址,抓取相關的lib
"Local Maven Repository" at "file:C:\.m2", <-如果你有mvn專案,可以設定路徑可以使用
"Spy Repository" at "http://files.couchbase.com/maven2" <-線上mvn的lib下載
)
// 這是sbt的註解寫法
// play支援轉換專成Maven repository的lib格式,以下兩個寫法是要把專案推播到哪個Maven repository網站上
publishTo := Some(
"My resolver" at "https://mycompany.com/repo"
)
// 稍微不太一樣是, 後面可以設定該 mvn Repo 網站的帳號與密碼
credentials += Credentials(
"Repo", "https://mycompany.com/repo", "admin", "admin123"
)
)
[play command]
指令部分,大部份是sbt內建的指令,少部分play新增的。我只介紹基本常使用的指令,若想要瞭解更多,而sbt官方有更完整的介紹。當我們要建置環境時,首先要切到專案的目錄之後,才可以下相關的指令,記得前面的關鍵字需要用activator
。
ex command : activator compile
- clean
刪除專案target目錄產出的編譯檔案。偶爾Play專案會發生compile錯誤,而本身專案設定卻沒有錯誤時,可以藉由這指令,清除target產出的資料,再重新compile一次,減少問題發生。
- update
下載這個專案所設定需要的library,是根據build.sbt來設定所下載的。update下來的library通常會放在play Framework的目錄下。
ex path : c:/playFramework/xxxxxx/repository/cache/
- compile
編譯Play專案,產出專案需要的檔案,通常會在專案下的target目錄。
- eclipse
eclipse的指令用處,可以讓eclipse IDE 所匯入專案,與辨認Play的程式碼,在使用eclipse指令之前,請記得要先compile才能使用,直接使用,若直接輸入eclipse指令,會導致eclipse失敗。
- run
啟動Play專案成為一個網站服務,後面可以雙引號設定要啟動服務的port。ex : activator "run 8888"。快捷鍵ctrl + D,可中斷Play的網頁服務執行。
- publish
產生專案本身,可呼叫與使用的jar檔,可以放到設定好的遠端函式庫。若在build.sbt有設定的話,可以把專案編譯成MVN格式的library後,放到設定好的Maven repository網站上。
- publish-local
產生專案本身,可呼叫與使用的jar檔,放到本機play的repository/local目錄下。
ex path : c:/playFramework/xxxxxx/repository/local
- stage
這個指令是把專案建置成可部署Play的服務檔案,建置後會放在以下路徑裡。
ex path : [project]/target/universal/stage/bin/myFirstApp
Play指令的使用時機,可以按照以下的說明,選擇自己需要執行的指令。
-會先清除專案產生出來的target資料,之後會下載專案要使用的library,最後編譯Play專案。
activator clean update compile
-編譯整個專案,以及讓專案可以使Eclipse匯入。
activator clean update compile eclipse
-讓play專案能成為一個可服務的網站。
activator "run 8888"
-編譯整個專案,並且把編譯過的jar檔放到相關的Repository網站或目錄。
activator clean update compile publish (publish-local)
-編譯整個專案,以及建置可部署Play的檔案。
activator clean update compile stage
[Play deploy and build]
Play本身主打就是各種形式的網站服務,這一小節,來介紹怎樣部署我們的Play專案以及可以設定的地方。如果你機器上有多個服務的時候,可以使用nginx或Apache來管理我們的Http server,最後我會是以常見的nginx與Apache來說明,Play的Http server應該要怎樣設定。
當我們使用下指令後。
activator clean update compile stage
會把可執行的Play檔案放在以下路徑。當你想要在一個全新的環境裡想要啟用Play服務時,最低的執行需求是最少要安裝Java8的編譯程式(JDK)。
path : target/universal/stage/bin/[project-name]
ex path : target/universal/stage/bin/myFirstApp
而Play啟動網站服務時可以增加參數化指令可以讓Play的服務更符合我們所期望的結果。
設定檔/conf
Play專案使用設定檔時,有時候需要分測試環境與正式環境的設定檔,我們也可以自定義設定檔,做其他用途。設定檔會放在專案的conf目錄下。test.conf通常意指測試的設定檔,prod.conf意指正式環境的設定檔。
-這樣設定會吃到play專案本身自己的conf檔,設定檔通常建議會是放在專案的conf/目錄下。
/path/to/bin/<project-name> -Dconfig.resource=prod.conf
-當然我們也可以使用專案外部的設定檔案。
/path/to/bin/<project-name> -Dconfig.file=c:/playFramework/playConf/prod.conf
Http Server
Play網站服務啟動時,我們可以特別去定義我們要使用的url的ip address跟想要使用port。
/path/to/bin/<project-name> -Dhttp.port=1234 -Dhttp.address=127.0.0.1
PID
Play服務啟動是有自己的PID(prcess ID),我們可以設定在想要的地方,方便之後需要砍掉服務時,可以到設定的目錄直接刪除它,這邊範例是以Linux or MacOS作業系統為主。
console(命令與提示字元/終端機) : ``Play server process ID is 2534```
-Pid設定
/path/to/bin/<project-name> -Dpidfile.path=/var/run/play.pid
-如果要砍掉服務時可以使用該指令去砍掉服務(ps:只能使用在Linux or MacOSX 等環境)
kill $(cat /var/run/play.pid)
-如果你想要讓Play自己自動產生自己的pid號碼,你可以在application.conf所設定。
pidfile.path = "/dev/null"
Log設定檔路徑
專案建立之後,會有一個log設定檔的參考範本可以看,路徑是在conf/logBack.xml。當Play執行時,可以根據指令,來去指定對應的logFile。
- 這是讀取專案內的log設定檔
/path/to/bin/<project-name> -Dlogger.resource=conf/prod-logger.xml
- 這是讀取專案外部的log設定檔
/path/to/bin/<project-name> -Dlogger.file=c:/playFramework/playConf/prod-logger.xml
- 這是讀取專案的網站log設定檔
/path/to/bin/<project-name> -Dlogger.url=http://conf.mycompany.com/logger.xml
Log設定檔
專案建立之後,會有一個log設定檔的參考範本可以看,路徑在conf/logBack.xml。Log檔可以說是檢查服務跟找問題的好幫手。主要是它可以監控Play,我們可以自行印出Play程式的輸入輸出結果。如果一些出問題或出錯時時,還可以額外設定,該寄出錯誤訊息給相關者,方便開發者去尋找程式問題。
在專案內的log設定檔,以下是官方設定檔的參考範本。
<!-- https://www.playframework.com/documentation/latest/SettingsLogger -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<!-- 這邊預設寫入專案內的logs目錄下的application.log檔案-->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${application.home:-.}/logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="STDOUT" />
</appender>
<!--play相關程式,info等級以上-->
<logger name="play" level="INFO" />
<logger name="application" level="DEBUG" />
<!-- Off these ones as they are annoying, and anyway we manage configuration ourselves -->
<logger name="com.avaje.ebean.config.PropertyMapLoader" level="OFF" />
<logger name="com.avaje.ebeaninternal.server.core.XmlConfigLoader" level="OFF" />
<logger name="com.avaje.ebeaninternal.server.lib.BackgroundThread" level="OFF" />
<logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF" />
<!--root這邊表示是全域等級的,只要發生Warn等級以上訊息,都會寫入log記錄檔-->
<root level="WARN">
<appender-ref ref="ASYNCFILE" /> <!-- 會根據ref指定log設定名稱,去記錄相關記錄-->
<appender-ref ref="ASYNCSTDOUT" />
</root>
</configuration>
若想要額外再專案外部使用log設定檔,以下是官方設定檔的參考範本。這邊我多新增寄信的設定,要請您注意就是,需要有mail server協助才會順利寄出log信件。
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${user.dir}/web/logs/application.log</file>
<!-- 這邊是要擺放application.log記錄檔的路徑,用途是會記錄我們Play自己的相關記錄 ex path : C:/playFrameWork/playLogs -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 隔一天的紀錄,會被壓縮成.gz減少使用空間,若伺服器量不大,可以把副檔名修改成原始的.log名稱 -->
<fileNamePattern>application-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- 這邊可以設定,記錄最久時間 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder> <!-- log印出前, 會增加前面的時間訊息與log等級-->
<pattern>%date{yyyy-MM-dd HH:mm:ss ZZZZ} [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<!-- 這邊是要擺放access log記錄檔的路徑,用途是會記錄下請求的對方相關資訊 ex path : C:/playFrameWork/playLogs -->
<appender name="ACCESS_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${user.dir}/web/logs/access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover with compression -->
<fileNamePattern>access-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- keep 1 week worth of history -->
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss ZZZZ} %message%n</pattern>
<!-- this quadruples logging throughput -->
<immediateFlush>false</immediateFlush>
</encoder>
</appender>
<!-- 這邊可以設定嚴重錯誤時,可以寄信給相關人員-->
<appender name="email" class="ch.qos.logback.classic.net.SMTPAppender">
<smtpHost>test.test.com.tw</smtpHost>
<to>[email protected],[email protected]</to> <!-- 多人的寄信,可以使用逗點區隔。 -->
<from>playServiceError</from> <!-- 可以設定從哪裡寄送出來的。 -->
<subject>[playServiceError] Log Message Host: %X{host} IP: %X{ip} Account:devuser</subject>
<layout class="ch.qos.logback.classic.html.HTMLLayout">
<pattern>%d{yyyy/MM/dd HH:mm:ss.SSS}%thread%level%c%X{abbreviateInfo}%X{remoteAddress}%msg</pattern>
</layout>
</appender>
<!-- additivity=false 是只保留access log 的紀錄而不會有其他記錄-->
<logger name="access" level="INFO" additivity="false">
<appender-ref ref="ACCESS_FILE" />
</logger>
<root level="INFO">
<appender-ref ref="FILE"/> <!-- 會根據ref指定log設定名稱,去記錄相關記錄-->
</root>
<!-- 當程式發生有ERROR等級的錯誤訊息時,可以依據ref的寄信設定,寄給相關人員-->
<root level="ERROR">
<appender-ref ref="email"/>
</root>
</configuration>
front end HTTP server
當我們線上有多個服務啟動的時候,通常會使用nginx或Apache來管理相關的線上服務。而想要把Play的服務加入到線上啟用的機器時,我們需要設定好Play的服務給nginx或Apache知道,我們的Play就可以被呼叫的到了,以下簡單介紹Play在nginx與Apache的設定。
nginx設定檔如下,通常需要修改/etc/nginx/nginx.conf的設定檔。當外部使用 www.mysite.com/ 網址呼叫服務時,會導向到設定檔所指定的Play服務。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
# 這邊是我們Play服務的設定
upstream my-backend {
server 127.0.0.1:9000;
}
# 當發現 location是 / 把服務導向到我們的Play
server {
listen 80;
server_name www.mysite.com;
location / {
proxy_pass http://my-backend;
}
}
}
apache設定如下。對外網址會是port是80,當使用 www.loadbalancedapp.com/ 網址呼叫服務時,會導向到設定檔所指定的Play服務。
<VirtualHost *:80>
ProxyPreserveHost On
ServerName www.loadbalancedapp.com
ProxyPass /excluded !
ProxyPass / http://127.0.0.1:9000/
ProxyPassReverse / http://127.0.0.1:9000/
</VirtualHost>
[Final]
呼! 以上就是本章節想要說明的部分,前半部分是說明Play常用的指令,需要先了解一番,後半部的部分都是Play部署相關的說明,這部分可以等到需要把程式上線到要部署的環境時,再好好研究即可,下個章節,會終於開始進入正題,如何寫Play程式。(這章節特別難寫啊~~~)
[Refernece]
1.The build system
網址 : https://www.playframework.com/documentation/2.5.x/Build
2.SBT官方教學
網址 : http://www.scala-sbt.org/0.13/docs/Getting-Started.html
3.sbt Command Line Reference
http://www.scala-sbt.org/0.13/docs/Command-Line-Reference.html
4.I can not import filters in playframework 2.3.0
http://stackoverflow.com/questions/24257288/i-can-not-import-filters-in-playframework-2-3-0
5.Deploying
https://www.playframework.com/documentation/2.5.x/Deploying
6.Using Play in production
https://www.playframework.com/documentation/2.5.x/Production
7.SettingsLoggern
https://www.playframework.com/documentation/2.5.x/SettingsLogger