ICPでRabbitMQを稼働してみる(2/2)

[ICPでRabbitMQを稼働してみる(1/2)](https://qiita.com/yurak/items/53db262d214786da6837)の続きです。

## Summary
### やったこと
* ローカル端末にインストールした IBM Cloud Private (以下ICP)上で、RabbitMQ を稼働させます。(1/2)
* Kubernetes から RabbitMQ の管理画面を見れるようにします。(1/2)
* **Liberty アプリケーションから MQ Put、MQ Get します。(2/2)**

### やっていないこと
* RabbitMQ についての説明はしていません。
* Liberty アプリケーションの詳細な説明はしていません。


## Liberty アプリケーションから MQ Put、MQ Get
### Web アプリの作成
MQ Put する画面、MQ Get する画面それぞれを作成します。
MQ Get は一般的な Cunsumer のようにキューに入れられたタスクを自身で処理する Push 型ではなく、
画面リクエストを契機に処理する Pull 型を使用します。

```PutMq.java
package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import servlet.util.CreateId;
import servlet.util.GetConfig;

public class PutMq extends HttpServlet {
    private static String queuename = GetConfig.getResourceBundle("queue.name");
    private static String username = GetConfig.getResourceBundle("jms.username");
    private static String password = GetConfig.getResourceBundle("jms.password");
    private static String host = GetConfig.getResourceBundle("jms.host");
    private static String vhost = GetConfig.getResourceBundle("jms.vhost");
    private static String message = GetConfig.getResourceBundle("common.message");
    private static String splitkey = GetConfig.getResourceBundle("jms.split.key");

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
	PrintWriter out = response.getWriter();
	out.println("Put MQ");
	ConnectionFactory connectionFactory = new ConnectionFactory();
	connectionFactory.setUsername(username);
	connectionFactory.setPassword(password);
	connectionFactory.setHost(host);
	connectionFactory.setVirtualHost(vhost);

	try {
	    Connection connection = connectionFactory.newConnection();
	    Channel channel = connection.createChannel();

	    String id = String.valueOf(CreateId.createid());
	    out.println("id: " + id);
	    out.println("msg: " + message);

	    StringBuilder buf = new StringBuilder();
	    buf.append(id);
	    buf.append(splitkey);
	    buf.append(message);
	    String body = buf.toString();

	    channel.basicPublish("", queuename, null, body.getBytes());

	    channel.close();
	    connection.close();

	    System.out.println("Set: id: " + id + ", msg:" + message);
	} catch (Exception e) {
	    System.out.println(e.getMessage());
	}
    }
}
```

```GetMq.java
package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.GetResponse;

import servlet.util.GetConfig;

public class GetMq extends HttpServlet {
    private static String queuename = GetConfig.getResourceBundle("queue.name");
    private static String username = GetConfig.getResourceBundle("jms.username");
    private static String password = GetConfig.getResourceBundle("jms.password");
    private static String host = GetConfig.getResourceBundle("jms.host");
    private static String vhost = GetConfig.getResourceBundle("jms.vhost");
    private static String splitkey = GetConfig.getResourceBundle("jms.split.key");

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
	PrintWriter out = response.getWriter();
	out.println("Get MQ");
	ConnectionFactory connectionFactory = new ConnectionFactory();
	connectionFactory.setUsername(username);
	connectionFactory.setPassword(password);
	connectionFactory.setHost(host);
	connectionFactory.setVirtualHost(vhost);

	try {
	    Connection connection = connectionFactory.newConnection();
	    Channel channel = connection.createChannel();
	    boolean durable = true;
	    channel.queueDeclare(queuename, durable, false, false, null);

	    /**
	     * 受信を常駐して監視する場合 Consumer consumer = new DefaultConsumer(channel) {
	     *
	     * @Override public void handleDelivery(String consumerTag, Envelope envelope,
	     *           AMQP.BasicProperties properties, byte[] body) throws IOException {
	     *           String message = new String(body, "UTF-8"); out.println("Received
	     *           '" + message + "'"); } }; channel.basicConsume(QUEUE_NAME, true,
	     *           consumer);
	     */

	    /**
	     * 1度受信する場合
	     */
	    GetResponse resp = channel.basicGet(queuename, true);
	    String jmsbody = new String(resp.getBody(), "UTF-8");
	    String[] body = jmsbody.split(splitkey, 0);
	    String id = body[0];
	    String message = body[1];
	    out.println("id: " + id);
	    out.println("msg: " + message);
	    System.out.println("Received: id: " + id + ", msg:" + message);

	    channel.close();
	    connection.close();
	} catch (Exception e) {
	    System.out.println(e.getMessage());
	}
    }
}
```

RabbitMQ への接続定義を記載します。

```java.properties
# JMS Client
queue.name = queue1
jms.username = ossapl
jms.password = ossapl
jms.host = rabbitmq
jms.vhost = vhost1
jms.split.key = ,
```
sample.warを作成します。

### server.xmlの作成
[公式サイト](https://hub.docker.com/_/websphere-liberty/)を参考に、`server.xml` を作成します。

```server.xml
<server description="new server">
  <featureManager>
    <feature>webProfile-8.0</feature>
    <feature>localConnector-1.0</feature>
  </featureManager>
  <httpEndpoint host="*" httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint" />
</server>
```

### Dockerfileの作成
Liberty の`Dockerfile` を作成します。

```Dockerfile
FROM websphere-liberty:webProfile8
COPY --chown=1001:0  sample.war /config/dropins/
COPY --chown=1001:0  server.xml /config/
ENV LICENSE accept
```

### ビルド、タグの作成、イメージのプッシュ
`Dockerfile`を用いてビルド、タグを作成し、ICPのプライベートDocker Registry へプッシュします。

```sh
＄ docker build . -t mycluster.icp:8500/default/docker_hub_id/wlp:v0.0.1
$ docker push mycluster.icp:8500/default/docker_hub_id/wlp:v0.0.1
```
ICPの管理画面から確認できます。
<img width="1662" alt="スクリーンショット 2019-04-20 22.50.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232123/946cf9a0-ee6a-7adf-a35c-7441845d0194.png">

### Deploymentの作成
ここから、Kubernetes へリソースを定義していきます。
使用するイメージは、先ほどICPのプライベート Docer Registryにプッシュしたものを指定します。

```wlp-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wlp
spec:
  selector:
    matchLabels:
      app: wlp
  replicas: 1
  template:
    metadata:
      labels:
        app: wlp
    spec:
      containers:
      - name: wlp
        image: mycluster.icp:8500/default/docker_hub_id/wlp:v0.0.1
        imagePullPolicy: Always
        ports:
        - containerPort: 9080
```

### Serviceの作成
Service を作成します。

```wlp-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: wlp
spec:
  type: ClusterIP
  selector:
    app: wlp
  ports:
  - protocol: TCP
    port: 9080
```

### Ingressの作成
Ingress の定義を作成します。

```rabbitmq-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: wlp
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host:
    http:
      paths:
      - path: /wlp
        backend:
          serviceName: wlp
          servicePort: 9080
```

### ICP上でLibertyを稼働
`kubectl apply`をします。
作成したファイルを再帰的にアプライします。

```sh
$ find . -name "*.yaml"|xargs -I {} kubectl apply -f {}
ingress.extensions/wlp created
service/wlp created
deployment.apps/wlp created
```

## Liberty アプリケーションから MQ Put、MQ Get
Put画面
<img width="662" alt="スクリーンショット 2019-04-20 23.09.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232123/12eccd4b-674f-0fac-de2a-c0249cb13722.png">

Get画面
<img width="650" alt="スクリーンショット 2019-04-20 23.10.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232123/a5109d69-94ef-342e-4619-5e94bdb49cf2.png">

ログ

```sh
$ kubectl get po
NAME                        READY   STATUS    RESTARTS   AGE
rabbitmq-7594895bdb-vkhm4   1/1     Running   0          57m
wlp-7cb68d5ff-mxkxs         1/1     Running   0          4m31s
$ kubectl logs -f wlp-7cb68d5ff-mxkxs
Set: id: 91007, msg:Hello oss-3tier-webapp!
Received: id: 91007, msg:Hello oss-3tier-webapp!
```