Apache2.4 <=> Tomcat 連携

/etc/httpd/conf.d/ の中にインクルードする設定ファイルを作り、以下のような記述を入れます。
8009 はデフォルトのTomcatの server.xml に設定されたポート番号なので、変えた場合、変える必要あります。

<Location /tomcat_sitename>
  ProxyPass ajp://127.0.0.1:8009/tomcat_sitename
</Location>

Apache2.4 ログローテーションの設定

httpd.conf に以下のような記述を入れてます。
プロキシされてるサーバーなので、SSLの設定入れてませんが、必要な場合、ssl.confに同様の設定入れるとよいです。

<IfModule log_config_module>
    #
    # The following directives define some format nicknames for use with
    # a CustomLog directive (see below).
    #
    ### last %D means micro second ###
    LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
    LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      # You need to enable mod_logio.c to use %I and %O
      LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    #
    # The location and format of the access logfile (Common Logfile Format).
    # If you do not define any access logfiles within a <VirtualHost>
    # container, they will be logged here.  Contrariwise, if you *do*
    # define per-<VirtualHost> access logfiles, transactions will be
    # logged therein and *not* in this file.
    #
    #CustomLog "logs/access_log" common

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    SetEnvIf User-Agent "ELB-HealthChecker.*" nolog
    #CustomLog "logs/access_log" combined env=!nolog
    CustomLog "|/usr/sbin/rotatelogs /home/Log/apache/access_log_%Y%m%d 86400 540" combined env=!nolog
</IfModule>

jq でJSON を整形

本家 Tutorial : https://stedolan.github.io/jq/tutorial/

わかりやすい紹介 : https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af

inotify-tools の分かり易い説明 : https://qiita.com/stc1988/items/464410382f8425681c20

アプリケーションのログがJSONテキストで、フィールドを分けて、データベースのテーブルに追加できるスクリプトを作りました。
MySQL 5.7 から、JSON型が提供されたので、整形しないでそのまま追加すれば使えますが、抽出のSQLに慣れてなく、列で分けた方が視認性良いのでそうしてます。

[ 大まかな流れ ]

1) ログは逐次出力されるので、inotify で更新を待ち受け
2) ログの行が追加された時点で、発火
3) 最終行を取得して、sedとかgawkで変換
4) jqで各列値を取得
5) SQL文に整形して、INSERTコマンドを渡しテーブルに追加

[ コード例 ]


#!/bin/bash

### NextCloud log add to my table log ###

# $1 : SiteName (end part of URI) 
# required package: inotify-tools

## --------- const ------------- ##

FIELD_ARRAY=(reqId level time remoteAddr user app method url message userAgent version,)
INSSQL="INSERT INTO log_use (NM_SITE,"

INTERVAL_COMMIT=10         # 一括した時スキップするので
# in order to avoid 
# should write notify result to file. and check row count by wc. and write SQL script file

## ----------------------------- ##

nmsite=$1

watch_file=/home/ncdata/${nmsite}/nextcloud.log
#events=(-e CREATE -e MODIFY -e MOVED_TO)

cnt=0
argsql=""
cmdpost="";
while inotifywait -e MODIFY ${watch_file}; do
  row=`tail -n 1 ${watch_file}`
  echo ${row}
  echo "------------------------------------------------------------"

  # execute jq #
  #echo ${row} | jq
  
  #echo "-- method"
  #echo ${row} | jq -r '.method'
  let cnt++
  echo ${cnt}

  echo "-- SQL"
  cursql=${INSSQL}
  # Field part # 
  for fld in ${FIELD_ARRAY[@]}; do
    cursql=${cursql}${fld}","
  done
  cursql=${cursql}") VALUES ("
  cursql=`echo ${cursql} | sed 's/,,//g'`

  # Value part #
  cursql=${cursql}"'"${nmsite}"',"
  for fld in ${FIELD_ARRAY[@]}; do
    nmfld=`echo ${fld} | sed 's/,//'`
    curval=`echo ${row} | jq ."${nmfld}"`

    if [ ${nmfld} = "time" ]; then
      curval=`echo ${curval} | sed 's/\+[0-9][0-9]:[0-9][0-9]//'`
    fi

    cursql=${cursql}${curval}","
  done
  cursql=${cursql}");"
  cursql=`echo ${cursql} | sed 's/,);/);\n/g'`
  #cursql=`echo -e $cursql"\n"`
  #echo ${cursql}


  argsql=${argsql}${cursql}

  # Execute command #
  if [ ${cnt} -eq ${INTERVAL_COMMIT} ]; then
    #cmdpost=${CMD_SQL}${argsql}"'"
    echo ${argsql} > ${INSSQL_FILENAME}

    ## debug
    tmcur=`date "+%Y%m%d-%H%M%S"`
    #cp ${INSSQL_FILENAME} ${INSSQL_FILENAME}"."${tmcur}

    echo `ls -l ${INSSQL_FILENAME}`
    cmdpost=${CMD_SQL}${INSSQL_FILENAME}
    echo "-- MySQL shell command"
    #echo ${cmdpost}
    #`${cmdpost}`      ???????????? script incorrect

    # Write MySQL database #
    mysql -u???? -p????????? mytable < ${INSSQL_FILENAME}

    argsql=""
    echo "" > ${INSSQL_FILENAME}
    cnt=0
  fi


done

CentOS7系 6系より便利なところ

基本的に設定ファイルをいじる方式から、コマンドで設定を変更する方式に変わってきてる。

1)  systemd で起動、終了、自動起動、ステータスがわかりやすい。自作サービスも作りやすい

2) firewalld でファイアウォールの設定がやりやすい

3) nmtui, nmcui のネットワーク設定が便利

詳しくはこちらのリク: https://qiita.com/sion_cojp/items/115e1671fcbc8f214aee 

https://liginc.co.jp/343687

 

JAVA 本番環境リリース時変更をなくす (プロキシサーバー)

開発環境がプロキシなし, 実行環境がプロキシありの場合、そのままでは動かないので、違う設定する必要ありますが、最小限に済ます方法です。
プロキシの設定は、httpclient, seleniumのconnect, jsoupのconnect, curlのシェル実行とかで多用するので、どこに居ても開発がはかどります。

1) web.xmlに使うか使わないかを設定


   <!-- Use proxy or not for curl command -->
  <context-param>
    <param-name>IsUseProxy</param-name> <param-value>0</param-value>
  </context-param>

2) 判別と、使う場合のcurlコマンドに使う引数を、静的設定用クラスに定義


  /**
   * プロキシ利用フラグ
   */
  public static boolean isUseProxy = false;
  /**
   * curl用プロキシ引数
   */
  public static final String ARG_PROXY_CURL = "--proxy http://10.70.1.80:8080";

3) JSPでの利用例


  // クレジットバランス用 //
  ServletContext cntxt = getServletContext();
  String crblcURL = cntxt.getInitParameter("CreditBalanceURL");
 
  crblc.setIsUseProxy(DBini.isUseProxy);

  crblc.setUrl(crblcURL);
  String crrest = crblc.getCreditBalance();
  pageContext.setAttribute("crrest", crrest);

        // == ツールバー == //
        var htmlds = 'From ' + "${dtpcsumsel}" +
                '<span style="margin-left:12px;">' + '${crrest}' + '</span>';
        $('#t_pcsum').prepend(htmlds); // 後でリフレッシュボタンを付けてるのでprepend

  /**
   * curlでクレジットバランス取得
   *
   * @return 文字列
   */
  public String getCreditBalance() {

    int res = 0;
    String proxy = this.isUseProxy ? DBini.ARG_PROXY_CURL: "";

    // コマンド文字列作成 //
    String curcmd = "curl -k --connect-timeout 5 " + proxy + " " + url;
    System.out.println(curcmd);

    String restxt = "";
    try {

      Runtime runtime = Runtime.getRuntime();
      Process p = runtime.exec(curcmd);
      InputStream is = p.getInputStream();

      // レスポンス取得 //
      int nread;
      byte[] rbuf = new byte[500];
      while ((nread = is.read(rbuf)) > 0) {
      }
      restxt = new String(rbuf, "US-ASCII");

    }
    catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println(restxt);

    String blctxt = "";
    if (restxt != null) {
      int crblcstpos = restxt.indexOf("CREDIT_BALANCE=\"");
      int lastchgpos = restxt.indexOf("\" LAST_CHARGED");
      if (crblcstpos != -1 && lastchgpos != -1) {
        blctxt = restxt.substring(crblcstpos + 16, lastchgpos);
      }
      if (blctxt.indexOf("Connection timed out") > -1) {
        blctxt = "TimedOut";
      }
      if (blctxt.equals("")) {
        blctxt = "No Response";
      }
      return blctxt;
    }
    // エラー //
    else {     
      return "Error";
    }
  }

4) Servletでの利用例


    // コマンド //
    String curlcmd = "curl -k " + (DBini.isUseProxy ? DBini.ARG_PROXY_CURL: "")
            + (isSimple ? DBini.vesselPositionURLSimple : DBini.vesselPositionURL) + imo;
    System.out.println(curlcmd);

    // 開始時間取得 //
    long startTime = System.currentTimeMillis();

    VesselPosition vsp = new VesselPosition(DBini.tmNowFmt());

    String restxt = "";
    try {

      Runtime runtime = Runtime.getRuntime();
      Process p = runtime.exec(curlcmd);
      InputStream is = p.getInputStream();

      // レスポンス取得 //
      int nread;
      byte[] rbuf = new byte[2048];
      while ((nread = is.read(rbuf)) > 0) {
      }
      restxt = new String(rbuf, "US-ASCII");

    }
    catch (Exception e) {
      e.printStackTrace();
      vsp.setResmsg(this.FAIL_MESSAFE);
    }