前回 HA 構成を UDPマルチキャスト で作ってみましたが
UDPマルチキャスト が使えない環境向けに
TCP(JDBC PING)を使用してHA構成を作ってみました。

目指す構成

構築する keycloak の構成

  • スタンドアロンモード
  • DB;postgres
  • Infinispanクラスタ構成
    • プロトコル;JDBC PING
    • キャッシュモード;Replicated Mode(sessions)

環境

  • Virtualbox 5.1.3
  • Ubuntu16.04 Server(最小構成インストール)
  • Keycloak 3.4.1.Final (執筆時最新)

JBoss CLI で 管理サーバを起動します。

# $JBOSS_HOME/bin/jboss-cli.sh
[disconnected /] embed-server --server-config=standalone-ha.xml --std-out=echo

09:33:53,376 INFO  [org.jboss.modules] (AeshProcess: 1) JBoss Modules version 1.6.1.Final
09:33:53,531 INFO  [org.jboss.msc] (AeshProcess: 1) JBoss MSC version 1.2.7.SP1

      ;
      ;

[standalone@embedded /]

起動したら、以下の設定を行っていきます

/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions:remove
/subsystem=infinispan/cache-container=keycloak/replicated-cache=sessions:add()
/subsystem=infinispan/cache-container=keycloak/replicated-cache=sessions:write-attribute(name="mode",value="SYNC")

/subsystem=jgroups/stack=tcpping:add()
/subsystem=jgroups/stack=tcpping/transport=TCP:add(socket-binding=jgroups-tcp)
/subsystem=jgroups/stack=tcpping/transport=TCP/property=external_addr:add(value=${jboss.bind.address:127.0.0.1})

/subsystem=jgroups/stack=tcpping/protocol=JDBC_PING:add()
/subsystem=jgroups/stack=tcpping/protocol=JDBC_PING/property=datasource_jndi_name:add(value=java:jboss/datasources/KeycloakDS)
/subsystem=jgroups/stack=tcpping/protocol=JDBC_PING/property=initialize_sql:add(value="CREATE TABLE IF NOT EXISTS JGROUPSPING (own_addr varchar(200) NOT NULL,bind_addr varchar(200) NOT NULL,created timestamp NOT NULL,cluster_name varchar(200) NOT NULL,ping_data BYTEA,constraint PK_JGROUPSPING PRIMARY KEY (own_addr, cluster_name))")
/subsystem=jgroups/stack=tcpping/protocol=JDBC_PING/property=insert_single_sql:add(value="INSERT INTO JGROUPSPING (own_addr, bind_addr, created, cluster_name, ping_data) values (?,'${jboss.bind.address:127.0.0.1}',NOW(), ?, ?)")
/subsystem=jgroups/stack=tcpping/protocol=JDBC_PING/property=delete_single_sql:add(value="DELETE FROM JGROUPSPING WHERE own_addr=? AND cluster_name=?")
/subsystem=jgroups/stack=tcpping/protocol=JDBC_PING/property=select_all_pingdata_sql:add(value="SELECT ping_data FROM JGROUPSPING WHERE cluster_name=?;")

/subsystem=jgroups/stack=tcpping/protocol=MERGE3:add()
/subsystem=jgroups/stack=tcpping:add-protocol(type="FD_SOCK",socket-binding="jgroups-tcp-fd")
/subsystem=jgroups/stack=tcpping/protocol=FD_SOCK/property=external_addr:add(value=${jboss.bind.address:127.0.0.1})
/subsystem=jgroups/stack=tcpping/protocol=FD:add()
/subsystem=jgroups/stack=tcpping/protocol=VERIFY_SUSPECT:add()
/subsystem=jgroups/stack=tcpping/protocol=pbcast.NAKACK2:add()
/subsystem=jgroups/stack=tcpping/protocol=UNICAST3:add()
/subsystem=jgroups/stack=tcpping/protocol=pbcast.STABLE:add()
/subsystem=jgroups/stack=tcpping/protocol=pbcast.GMS:add()
/subsystem=jgroups/stack=tcpping/protocol=MFC:add()
/subsystem=jgroups/stack=tcpping/protocol=FRAG2:add()

/subsystem=jgroups/channel=ee:remove
/subsystem=jgroups/channel=ee:add(stack=tcpping)
/subsystem=jgroups:write-attribute(name=default-channel, value=ee)

/socket-binding-group=standard-sockets/socket-binding=jgroups-tcp:write-attribute(name="interface",value="public")
/socket-binding-group=standard-sockets/socket-binding=jgroups-tcp-fd:add()
/socket-binding-group=standard-sockets/socket-binding=jgroups-tcp-fd:write-attribute(name="interface",value="public")
/socket-binding-group=standard-sockets/socket-binding=jgroups-tcp-fd:write-attribute(name="port",value="57600")

設定終了時には 以下コマンドでJBoss管理サーバを止めます

[standalone@embedded /] stop-embedded-server

[disconnected /] exit

うまくいくと standalon-ha.xml は以下の状態になります。

standalone-ha.xml

$JBOSS_HOME/standalone/configuration/standalone-ha.xml

        <subsystem xmlns="urn:jboss:domain:infinispan:4.0">
            <cache-container name="keycloak" jndi-name="infinispan/Keycloak">
                <transport lock-timeout="60000"/>
                <local-cache name="realms">
                    <eviction strategy="LRU" max-entries="10000"/>
                </local-cache>
                <local-cache name="users">
                    <eviction strategy="LRU" max-entries="10000"/>
                </local-cache>
                <local-cache name="authorization">
                    <eviction strategy="LRU" max-entries="10000"/>
                </local-cache>
                <local-cache name="keys">
                    <eviction strategy="LRU" max-entries="1000"/>
                    <expiration max-idle="3600000"/>
                </local-cache>
                <replicated-cache name="work" mode="SYNC"/>
                <replicated-cache name="sessions" mode="SYNC"/>
<!--
distributed mode の場合
                <distributed-cache name="sessions" mode="SYNC" owners="2"/>
-->

  ・・・

        <subsystem xmlns="urn:jboss:domain:jgroups:5.0">
                <channels default="ee">
                     <channel name="ee" stack="tcpping"/>
                </channels>
 
  ・・・
                <stack name="tcpping">
                    <transport type="TCP" socket-binding="jgroups-tcp">
                        <property name="external_addr">
                            ${jboss.bind.address:127.0.0.1}
                        </property>
                    </transport>
                    <protocol type="org.jgroups.protocols.JDBC_PING">
                        <property name="datasource_jndi_name">
                            java:jboss/datasources/KeycloakDS
                        </property>
                        <property name="initialize_sql">
                            CREATE TABLE IF NOT EXISTS JGROUPSPING (own_addr varchar(200) NOT NULL,bind_addr varchar(200) NOT NULL,cr
eated timestamp NOT NULL,cluster_name varchar(200) NOT NULL,ping_data BYTEA,constraint PK_JGROUPSPING PRIMARY KEY (own_addr, cluster_
name))
                        </property>
                        <property name="insert_single_sql">
                            INSERT INTO JGROUPSPING (own_addr, bind_addr, created, cluster_name, ping_data) values (?,'${jboss.bind.a
ddress:127.0.0.1}',NOW(), ?, ?)
                        </property>
                        <property name="delete_single_sql">
                            DELETE FROM JGROUPSPING WHERE own_addr=? AND cluster_name=?
                        </property>
                        <property name="select_all_pingdata_sql">
                            SELECT ping_data FROM JGROUPSPING WHERE cluster_name=?;
                        </property>
                    </protocol>
                    <socket-protocol type="MPING" socket-binding="jgroups-mping"/>
                    <protocol type="MERGE3"/>
                    <protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd">
                        <property name="external_addr">
                            ${jboss.bind.address:127.0.0.1}
                        </property>
                    </protocol>
                    <protocol type="FD"/>
                    <protocol type="VERIFY_SUSPECT"/>
                    <protocol type="pbcast.NAKACK2"/>
                    <protocol type="UNICAST3"/>
                    <protocol type="pbcast.STABLE"/>
                    <protocol type="pbcast.GMS"/>
                    <protocol type="MFC"/>
                    <protocol type="FRAG2"/>
                </stack>

  ・・・

        <socket-binding name="jgroups-tcp" interface="public" port="7600"/>
        <socket-binding name="jgroups-udp" interface="private" port="55200" multicast-address="${jboss.default.multicast.address:230.
0.0.4}" multicast-port="45688"/>

  ・・・

参考

https://qiita.com/yoonis/items/4f4a9df0f6f8e858bd4a https://developer.jboss.org/wiki/JDBCPING