linux服务-Nginx+Tomcat+Redis之Session 共享 - 容器单机版

Nginx+Tomcat+Redis之Session 共享 - 容器单机版

一、docker构建redis集群

参考:豆包ai使用docker搭建redis集群示例容器归集 提取码:1234

1.1、准备阶段

  • 下载基础镜像

    bash 复制代码
    docker pull docker.gh-proxy.com/ubuntu:20.04
    docker tag docker.gh-proxy.com/ubuntu:20.04 ubuntu:20.04
  • 准备构建好的redis服务: 参考:redis安装

    bash 复制代码
    目录: /data/redis
    目录结构:
    redis
        ├── bin
        │   ├── ...
        │   └── redis-server
        ├── conf
        │   └── redis.conf
        └── logs
    
    包准备为: redis-7.2.12.tar.gz
  • redis配置文件: /data/redis/bin/redis.conf

    bash 复制代码
    # 容器要运行在前台
    daemonize no
    bind 0.0.0.0
    # 其它的后续用的时候都会覆盖原始配置,它能起来一次测试就行
  • Dockerfile

    bash 复制代码
    from ubuntu:20.04
    
    ADD redis-7.2.12.tar.gz /data
    
    ENV redis_home=/data/redis  VERSION=7.2.12
    
    EXPOSE 6379
    
    CMD ["/data/redis/bin/redis-server","/data/redis/conf/redis.conf"]
  • 构建并检查服务是否正常

    bash 复制代码
    [root@localhost opt]# docker build -t redis:7.2.12 .
    [root@localhost opt]# docker images
    REPOSITORY                   TAG       IMAGE ID       CREATED              SIZE
    redis                        7.2.12    1916e2f38ccd   About a minute ago   149MB
    
    [root@localhost opt]# docker run -d -P --name t1 1916e2f38ccd
    
    [root@localhost opt]# docker ps
    CONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS        PORTS                                         NAMES
    541721bbab2a   9bb       "/data/redis/bin/red..."   2 seconds ago   Up 1 second   0.0.0.0:32768->6379/tcp, :::32768->6379/tcp   t2
    
    # 本地redis不需要启动
    [root@localhost opt]# /data/redis/bin/redis-cli -h 127.0.0.1 -p 32768
    127.0.0.1:32768> auth xiong
    OK
    127.0.0.1:32768> set 1 1
    OK
    127.0.0.1:32768> get 1
    "1"
  • 做成集群其实也只是把它的原始配置文件覆盖

1.2、集群构建

  • redis 集群原理与部署

  • 准备配置文件 redis.conf

    bash 复制代码
    ##################### 基础配置
    port 6379
    # 数据存储目录
    dir /data/redis/conf
    # 前台运行
    daemonize no
    # 日志文件
    logfile /data/redis/conf/redis.log
    
    ##################### 集群核心配置
    # 启用集群模式
    cluster-enabled yes
    # 集群节点信息文件(自动生成/更新)
    cluster-config-file nodes.conf
    # 节点超时时间(毫秒,故障检测阈值)
    cluster-node-timeout 15000
    # 从节点选举有效性因子(默认 10)
    cluster-replica-validity-factor 10
    # 主节点最小从节点数(防止脑裂,默认 1)
    cluster-migration-barrier 1
    
    ##################### 其他优化配置
    bind 0.0.0.0
    # 关闭保护模式(需配合密码或IP限制)
    protected-mode no
    # 节点密码(所有节点密码必须一致)
    requirepass xiong
    # 主从同步密码(与 requirepass 一致)
    masterauth xiong
    # 开启AOF持久化(保证数据不丢失)
    appendonly yes
    # AOF同步策略(每秒同步)
    appendfsync everysec
  • 自行定义网络段

    bash 复制代码
    # 自行定义名称吧
    [root@localhost redisdata]# docker network create p1 --subnet 10.0.1.0/24
    343183d2efbf260393cff935feead28c7b4730a76a74bc76e44a60dd7e14902f
    
    [root@localhost redisdata]# docker network ls
    343183d2efbf   p1        bridge    local
  • 创建并复制配置文件

    bash 复制代码
    # 用上面准备好的redis配置文件
    data]# for ((i=1;i<=6;i++));do mkdir /data/redisdata/redis$i -p;cp /data/redis.conf /data/redisdata/redis$i;done
    
    data]# tree redisdata/
    redisdata/
    ├── redis1
    │   └── redis.conf
    ├── redis2
    │   └── redis.conf
    ├── .....
  • 运行六个容器

    bash 复制代码
    for ((i=1;i<=6;i++));do
        docker run -d -p 637${i}:6379 --name redis-${i} -v /data/redisdata/redis$i:/data/redis/conf --net p1 --ip 10.0.1.10${i} redis:7.2.12 
    done
    
    # 详解一下
    run  -d               						 # 后台运行容器
    -p 637${i}:6379      						 # 端口映射
    --name redis-${i}     						 # 容器命名:redis-1-6
    -v /data/redisdata/redis$i:/data/redis/conf  # 数据卷挂载
    --net p1                    				 # 容器接入p1 网络
    --ip 10.0.1.10${i}          				 # 分配固定 IP:10.0.1.101-106
    redis:7.2.12                				 # 使用Redis 7.2.12镜像
  • 如果测试中失败

    bash 复制代码
    # 清掉无效的容器
    docker rm $(docker stop $(docker ps -a -q))
  • 构建集群

    bash 复制代码
    docker exec -it redis-1 echo yes| /data/redis/bin/redis-cli -a xiong --cluster create 10.0.1.101:6379 10.0.1.102:6379 10.0.1.103:6379 10.0.1.104:6379 10.0.1.105:6379 10.0.1.106:6379 --cluster-replicas 1
    
    # docker exec -it redis-1 指定redis-1 执行某个命令
    # 免输yes, 详解看一下redis集群章节
    echo yes| /data/redis/bin/redis-cli -a xiong --cluster create 10.0.1.101:6379 10.0.1.102:6379 10.0.1.103:6379 10.0.1.104:6379 10.0.1.105:6379 10.0.1.106:6379 --cluster-replicas 1
  • 检查集群状态

    bash 复制代码
    # 查看集群16384糟点是否都正常分配
    [root@localhost data]# docker exec -it redis-1 /data/redis/bin/redis-cli -a xiong cluster info
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    cluster_state:ok
    cluster_slots_assigned:16384
    cluster_slots_ok:16384
    cluster_size:3
    cluster_current_epoch:6
    
    # 查看集群内节点分配的糟位,三主三从没问题
    [root@localhost data]# docker exec -it redis-1 /data/redis/bin/redis-cli -a xiong cluster nodes
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    9e3...c5a 10.0.1.102:6379@16379 master - 0 1763644282434 2 connected 5461-10922
    066...120 10.0.1.104:6379@16379 slave 5ac...d21 0 1763644283478 3 connected
    5ac...d21 10.0.1.103:6379@16379 master - 0 1763644281000 3 connected 10923-16383
    801...8d8 10.0.1.106:6379@16379 slave 9e3...c5a 0 1763644281387 2 connected
    d5c...1c6 10.0.1.105:6379@16379 slave 3e5...540 0 1763644280000 1 connected
    3e5...540 10.0.1.101:6379@16379 myself,master - 0 1763644280000 1 connected 0-5460
  • 在检查挂载点

    bash 复制代码
    redisdata]# tree
    .
    ├── redis1
    │   ├── appendonlydir
    │   │   ├── appendonly.aof.1.base.rdb
    │   │   ├── appendonly.aof.1.incr.aof
    │   │   └── appendonly.aof.manifest
    │   ├── dump.rdb
    │   ├── nodes.conf
    │   ├── redis.conf
    │   └── redis.log
    ├── redis2
    ├── redis3
    	.......
  • 此时都构建完毕

二、docker构建tomcat

2.1、准备阶段

  • 基础镜像还是用:ubuntu:20.04

  • tomcat: 8.5.100 , jdk1.8.461

  • tomcat原理与安装jar包看session章节示例配置归集

    bash 复制代码
    # 准备集群版本的包 ,  这五个jar包放到 tomcat/lib目录下面
    commons-pool2-2.11.1.jar
    jedis-3.6.3.jar
    redis-session-cluster-plugin.jar
    slf4j-api-1.7.36.jar
    slf4j-simple-1.7.36.jar
  • context.xml 用环境变量的方式试了好几种办法行不通,后续用 envsubst 启动时动态生成context.xml成功

    • 压缩 tomcat.tar.gz前操作

    • 删除 /data/tomcat/conf/context.xml(用模板文件替代)

      bash 复制代码
      tomcat]# vi tomcat/conf/context.xml.template
      
      <?xml version="1.0" encoding="UTF-8"?>
      <Context>
          <WatchedResource>WEB-INF/web.xml</WatchedResource>
          <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
          <Resources cachingAllowed="true" cacheMaxSize="102400" />
      
          <Valve className="com.naritech.nicole.gump.RedisSessionHandlerValve" />
          <Manager className="com.naritech.nicole.gump.RedisSessionManager"
                   nodes="$REDIS_CLUSTER_NODES"
                   password="$REDIS_PASSWORD"
                   database="0"
                   maxInactiveInterval="1800"
                   timeout="3000"
                   maxRedirections="5"
                   cluster="$REDIS_CUSTER_FLAG" />
      </Context>
    • 将上面的 context.xml.template 放到 /data/tomcat/conf/ 目录下

    • 此时目录结构

      bash 复制代码
      [root@localhost tomcat]# tree -L 3tomcat
      .
      ├── context.xml
      ├── Dockerfile
      ├── jdk1.8
      ├── tomcat
      │   ├── bin
      │   │   ├── ... 默认tomcat脚本
      │   │   ├── catalina.bat
      │   ├── conf
      │   │   ├── context.xml.template
      │   ├── lib
      │   │   ├── .... 其它默认jar
      │   │   ├── commons-pool2-2.11.1.jar
      │   │   ├── jedis-3.6.3.jar
      │   │   ├── redis-session-cluster-plugin.jar
      │   │   ├── slf4j-api-1.7.36.jar
      │   │   ├── slf4j-simple-1.7.36.jar
      │   ├── LICENSE
      │   ├── logs
      │   ├── NOTICE
      │   ├── README.md
      │   ├── RELEASE-NOTES
      │   ├── RUNNING.txt
      │   ├── temp
      │   ├── webapps
      │   └── work
    • 压缩: tar zcf tomcat.tar.gz jdk1.8 tomcat

  • Dockerfile

    bash 复制代码
    from ubuntu:20.04
    
    # 安装 gettext(包含 envsubst 工具,用于替换变量)
    RUN apt-get update && apt-get install -y gettext && rm -rf /var/lib/apt/lists/*
    
    ADD tomcat.tar.gz /data
    
    # 环境变量(默认值,运行时可覆盖)
    ENV JAVA_HOME=/data/jdk1.8 \
        TOMCAT_HOME=/data/tomcat \
        TOMCAT_VERSION=8.5.100 \
        JAVA_VERSION=1.8.461 \
        LC_ALL=en_US.UTF-8 \
        REDIS_CLUSTER_NODES="1.1.1.1:6379" \
        REDIS_PASSWORD="default" \
        REDIS_CUSTER_FLAG="false"
    
    EXPOSE 8090
    
    # 核心命令:
    # 1. 用 envsubst 替换模板中的变量,生成真正的 context.xml(纯硬编码)
    # 2. 启动 Tomcat
    CMD ["/bin/sh", "-c", "envsubst '$REDIS_CLUSTER_NODES $REDIS_PASSWORD $REDIS_CUSTER_FLAG' < $TOMCAT_HOME/conf/context.xml.template > $TOMCAT_HOME/conf/context.xml && $TOMCAT_HOME/bin/catalina.sh run"]
    
    #####
    LC_ALL=en_US.UTF-8  <-- 解决容器内访问中文乱码
  • 构建容器

    bash 复制代码
    [root@localhost opt]# docker build -t tomcatcluster:8.5.100 .
    [root@localhost opt]# docker images
    REPOSITORY                   TAG       IMAGE ID       CREATED              SIZE
    tomcatcluster                8.5.100   ----------     8 seconds ago   272MB

2.1、集群构建

  • 准备jsp文件

    bash 复制代码
    mkdir /data/tomcatdata/webapps/ROOT -p
    mkdir /data/tomcatdata/logs -p
    
    vi /data/tomcatdata/webapps/ROOT/index.jsp
    
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ page import="java.net.InetAddress" %>
    <%@ page import="java.net.NetworkInterface" %>
    <%@ page import="java.util.Enumeration" %>
    <%@ page import="java.io.File" %>
    
    <html>
    <head>
        <title>Tomcat 核心信息查询(含运行路径)</title>
    </head>
    <body>
        <h3>🎯 Tomcat 核心信息汇总</h3>
        <hr>
        
        <!-- 1. Session 会话信息 -->
        <p><strong>📌 Session 信息:</strong></p>
        <p>Session ID:<%= session.getId() %></p>
        <p>创建时间:<%= new java.util.Date(session.getCreationTime()) %></p>
        <p>最后活动时间:<%= new java.util.Date(session.getLastAccessedTime()) %></p>
        <p>会话超时时间:<%= session.getMaxInactiveInterval() / 60 %> 分钟</p>
        <hr>
        
        <!-- 2. 服务器(Tomcat 所在机)信息 -->
        <p><strong>🖥️ 服务器信息:</strong></p>
        <p>服务器主机名:<%= InetAddress.getLocalHost().getHostName() %></p>
        <p>服务器内网 IP 列表:</p>
        <ul>
            <%
                // 获取所有有效内网 IPv4(排除回环地址)
                Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
                boolean hasIp = false;
                while (netInterfaces.hasMoreElements()) {
                    NetworkInterface ni = netInterfaces.nextElement();
                    Enumeration<InetAddress> ips = ni.getInetAddresses();
                    while (ips.hasMoreElements()) {
                        InetAddress ip = ips.nextElement();
                        if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && !ip.isLinkLocalAddress()) {
                            out.println("<li>" + ip.getHostAddress() + "(网卡:" + ni.getDisplayName() + ")</li>");
                            hasIp = true;
                        }
                    }
                }
                if (!hasIp) out.println("<li>未获取到有效内网 IP</li>");
            %>
        </ul>
        <hr>
        
    </body>
    </html>
  • 执行容器

    bash 复制代码
    # 启动新容器,传递环境变量(会被动态替换到 context.xml)
    docker run -d -P --net p1 --name tt1 \
      -e REDIS_CLUSTER_NODES="10.0.1.101:6379,10.0.1.102:6379,10.0.1.103:6379,10.0.1.104:6379,10.0.1.105:6379,10.0.1.106:6379" \
      -e REDIS_PASSWORD="xiong" \
      -e REDIS_CUSTER_FLAG="true" \
      -v /data/tomcatdata/webapps/:/data/tomcat/webapps/ \
      -v /data/tomcatdata/logs/:/data/tomcat/logs/ \
      tomcatcluster:8.5.100
  • 检查是否生效

    bash 复制代码
    # 此时能看到文件都被替换了
    [root@localhost tomcat]# docker exec -it tt1 cat /data/tomcat/conf/context.xml
        nodes="10.0.1.101:6379,10.0.1.102:6379,........9"
        password="xiong"
        cluster="true"
  • 也可以用 docker 容器name代替 <-- 我们用这个

    bash 复制代码
    docker run -d -P --net p1 --name tt2 \
      -e REDIS_CLUSTER_NODES="redis-1:6379,redis-2:6379,redis-3:6379,redis-4:6379,redis-5:6379,redis-6:6379" \
      -e REDIS_PASSWORD="xiong" \
      -e REDIS_CUSTER_FLAG="true" \
      -v /data/tomcatdata/webapps/:/data/tomcat/webapps/ \
      -v /data/tomcatdata/logs/:/data/tomcat/logs/ \
      tomcat:8.5.100
    
    [root@localhost tomcat]# docker exec -it tt2 cat /data/tomcat/conf/context.xml
       nodes="redis-1:6379,redis-2:6379,....6379"

三、docker构建nginx

3.1、准备阶段

  • 基础镜像还是用:ubuntu:20.04

  • nginx原理与安装, 这里用nginx:1.29, 任意一个版本都行

  • 目录及文件准备

    bash 复制代码
    nginx.conf    <-- 如果是其它的  加上 include 也可以自行定
    	user root; 
        include /data/nginx/conf/conf.d/*.conf;
  • Dockerfile

    bash 复制代码
    from ubuntu:20.04
    
    ADD nginx.tar.gz /data
    
    ENV nginx_home=/data/nginx VERSION=1.29.3
    
    EXPOSE 8080
    
    CMD ["/data/nginx/sbin/nginx", "-g", "daemon off;"]
    
    # 如果启动后报缺少nobody用户 需要加上 RUN useradd nobody
  • 构建

    bash 复制代码
    docker build --no-cache -t nginx:1.29.3 -f Dockerfile .
    mkdir /data/nginxdata/conf/conf.d/cache -p
  • tomcat.conf

    bash 复制代码
    vim /data/nginxdata/conf/conf.d/tomcat.conf
    
    # 我们直接指向它的 容器名称,由docker自行维护
    upstream backend_servers {
        server tt2:8090 weight=1;  # 服务器 1,权重 5(请求占比更高)
        server tt3:8090 weight=1;  # 服务器 2,权重 3
    }
    
    # 反向代理的 server 块
    server {
        listen       8080;
        server_name  127.0.0.1;
        access_log  /data/nginx/logs/access.log;
    
        # 所有请求转发到 backend_servers 集群
        location / {
            proxy_pass http://backend_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_connect_timeout 30;
            proxy_read_timeout 60;
        }
    }
  • 运行容器

    bash 复制代码
    docker run -d -P --name n2 --net p1  -v /data/nginxdata/conf/conf.d:/data/nginx/conf/conf.d nginx:1.29.3
  • 查看并访问

    bash 复制代码
    [root@localhost nginx]# docker ps
    CONTAINER ID   IMAGE                   COMMAND                   CREATED             STATUS              PORTS                                         NAMES
    7ef5fc81d772   nginx:1.29.3            "/data/nginx/sbin/ng..."   5 minutes ago       Up About a minute   0.0.0.0:32784->8080/tcp, :::32784->8080/tcp   n2
    
    # 浏览器访问  http://本机ip:32784
    Session ID:3588FA1B135C8F53B54FC354A6A7DDE3
    服务器主机名:bc0ab8300a65
    服务器内网 IP 列表:10.0.1.4(网卡:eth0)
    
    # sessionID 会话保持成功
    服务器主机名:9a0aaa78882b
    服务器内网 IP 列表:10.0.1.3(网卡:eth0)

四、归集说明

  • 测试中运行容器

    bash 复制代码
    [root@localhost nginx]# docker ps
    CONTAINER ID   IMAGE                    PORTS                  NAMES
    7ef5fc81d772   nginx:1.29.3            0.0.0.0:32784->8080/tcp  n2
    bc0ab8300a65   tomcat:8.5.100          0.0.0.0:32778->8090/tcp  tt3
    9a0aaa78882b   tomcat:8.5.100          0.0.0.0:32777->8090/tcp  tt2
    715eb014f95d   tomcatcluster:8.5.100   0.0.0.0:32776->8090/tcp  tt1
    93dcac7c3ae0   redis:7.2.12            0.0.0.0:6376->6379/tcp  redis-6
    ec5d3b969e7c   redis:7.2.12            0.0.0.0:6375->6379/tcp  redis-5
    2c7ddfa15364   redis:7.2.12            0.0.0.0:6374->6379/tcp  redis-4
    a1a0b0ac4d57   redis:7.2.12            0.0.0.0:6373->6379/tcp  redis-3
    e581687184ff   redis:7.2.12            0.0.0.0:6372->6379/tcp  redis-2
    64a59bd26870   redis:7.2.12            0.0.0.0:6371->6379/tcp  redis-1
  • 容器名称

    bash 复制代码
    [root@localhost nginx]# docker images
    REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
    nginx           1.29.3    318b6eff3815   12 minutes ago   82.5MB
    tomcatcluster   8.5.100   b25b27e2e6d7   2 hours ago      339MB
    redis           7.2.12    5994741e64ea   5 hours ago      149MB
    ubuntu          20.04     b7bab04fd9aa   7 months ago     72.8MB
    
    [root@localhost nginx]# docker save -o nginx-1.29.3.tar.gz 318b6eff3815
    [root@localhost nginx]# docker save -o tomcatcluster-8.5.100.tar.gz b25b27e2e6d7
    [root@localhost nginx]# docker save -o redis.7.2.12.tar.gz 5994741e64ea
    [root@localhost nginx]# docker save -o ubuntu.20.04.tar.gz b7bab04fd9aa
相关推荐
q***01651 小时前
Windows操作系统部署Tomcat详细讲解
java·windows·tomcat
linchare4 小时前
linux debian上只装mysql的客户端步骤
linux·mysql·debian
m0_488777656 小时前
Web与Nginx网站服务
nginx·web
百***75746 小时前
linux上redis升级
linux·运维·redis
顾安r6 小时前
11.22 脚本打包APP 排错指南
linux·服务器·开发语言·前端·flask
Neur0toxin6 小时前
入侵排查_2025/11/23
linux·windows·应急响应
小小编程能手7 小时前
Linux文件编程
linux·运维·服务器
木童6627 小时前
nginx安装步骤详解
linux·运维·服务器·网络·nginx
暴躁的菜鸡8 小时前
Ubuntu安装向日葵
linux·运维·ubuntu