在 实战(四) 中,使用 HAProxy 和 Tomcat 搭建了一个简单的 Tomcat 集群。 这节会去掉 Tomcat,使用 Spring Boot 和 MySQL 组成一个比较典型的负载均衡集群。
目录 1 2 3 4 5 6 compose-haproxy-web - docker-compose.yml + haproxy - haproxy.cfg + web - paper-0.0.1-SNAPSHOT.jar
docker-compose.yml MySQL 配置 1 2 3 4 5 6 7 image: batizhao/mysql environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: paper MYSQL_ROOT_HOST: "%" expose: - "3306"
MYSQL_DATABASE 需要在启动时创建 paper 数据库。MYSQL_ROOT_HOST 在 mysql user 中增加客户端远程访问的权限。
在 batizhao/mysql 这个镜像中,有一个自定义的 my.cnf 文件,主要是定义了 bind-address ,否则会遇到 CommunicationsException: Communications link failure 的错误,还有一些服务端、客户端 UTF-8 编码的定义。
Web 配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 image: batizhao/java:8 command: java -jar opt/paper.jar volumes: - ./web/paper-0.0.1-SNAPSHOT.jar:/opt/paper.jar depends_on: - "mysql" links: - "mysql:database" expose: - "8080" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/paper?useUnicode=true&useSSL=false - SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_PASSWORD=password - SPRING_DATASOURCE_SQL-SCRIPT-ENCODING=UTF-8
volumes 这个 Spring Boot 应用在 Github ,可以自己打包放到 web 目录。SPRING_DATASOURCE_SQL-SCRIPT-ENCODING 这个配置必须要有,否则初始化脚本会插入乱码到数据库。已经确定和 MySQL 无关,因为在宿主机启动 App 直接连接 MySQL 容器,并且在启动后插入中文数据都没有问题。只是在容器中启动 App 初始化时才会乱码,后来改 Web 容器编码也不起作用,加上这个配置就好了。
全部的 compose 配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 version: '2' services: mysql: image: batizhao/mysql environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: paper MYSQL_ROOT_HOST: "%" expose: - "3306" weba: image: batizhao/java:8 command: java -jar opt/paper.jar volumes: - ./web/paper-0.0.1-SNAPSHOT.jar:/opt/paper.jar depends_on: - "mysql" links: - "mysql:database" expose: - "8080" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/paper?useUnicode=true&useSSL=false - SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_PASSWORD=password - SPRING_DATASOURCE_SQL-SCRIPT-ENCODING=UTF-8 webb: image: batizhao/java:8 command: java -jar opt/paper.jar volumes: - ./web/paper-0.0.1-SNAPSHOT.jar:/opt/paper.jar depends_on: - "mysql" links: - "mysql:database" expose: - "8080" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/paper?useUnicode=true&useSSL=false - SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_PASSWORD=password - SPRING_DATASOURCE_SQL-SCRIPT-ENCODING=UTF-8 haproxy: image: haproxy volumes: - ./haproxy:/haproxy-override - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro links: - weba - webb ports: - "80:80" - "70:70" expose: - "80" - "70"
haproxy.cfg 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 4096 daemon defaults log global mode http option httplog option dontlognull retries 3 option redispatch maxconn 2000 timeout connect 5000 timeout client 50000 timeout server 50000 frontend balancer bind 0.0.0.0:80 mode http default_backend servers backend servers option httpchk OPTIONS / option forwardfor cookie JSESSIONID prefix server tomcat1 weba:8080 cookie JSESSIONID_SERVER_1 check inter 5000 server tomcat2 webb:8080 cookie JSESSIONID_SERVER_2 check inter 5000 listen status mode http default_backend servers bind 0.0.0.0:70 stats enable stats hide-version stats uri /stats stats auth admin:password stats admin if TRUE
启动容器 1 2 3 4 5 6 7 8 9 10 11 $ docker-compose up Creating network "composehaproxyweb_default" with the default driver Creating composehaproxyweb_mysql_1 Creating composehaproxyweb_webb_1 Creating composehaproxyweb_weba_1 Creating composehaproxyweb_haproxy_1 Attaching to composehaproxyweb_mysql_1, composehaproxyweb_webb_1, composehaproxyweb_weba_1, composehaproxyweb_haproxy_1 mysql_1 | Initializing database haproxy_1 | <7>haproxy-systemd-wrapper: executing /usr/local/sbin/haproxy -p /run/haproxy.pid -f /usr/local/etc/haproxy/haproxy.cfg -Ds mysql_1 | Database initialized mysql_1 | MySQL init process in progress...
访问 http://localhost 使用 admin/123456 可以登录系统。
访问 http://localhost:70/stats 使用 admin/password 可以看到集群状态。