## 模块 1: 负载均衡和会话管理器 - TiProxy

TiProxy 是 TiDB 的官方代理组件，通过提供负载均衡、连接持久性和服务发现来增强数据库的功能。它作为客户端和 TiDB 服务器之间的中介，确保在各种维护操作（如扩容、滚动升级和重启）期间客户端连接保持稳定和不中断。这在需要保持客户端连接持续性的场景中特别有用，例如在计划服务器停机期间或在多个 TiDB 服务器实例之间平衡工作负载时。

在本模块中，您将部署一个新的 TiDB 集群以及 TiProxy 组件，并验证其负载均衡和会话迁移功能。

### 步骤 1. 连接到 TiUP 控制机

+ 点击这里 - [终端 1](ssh://monitor1-ssh#1) 打开一个新的终端，连接到为你的实践实验分配的虚拟机。

+ 获取分配给您用于本实验的所有服务器实例 IP 地址的概览。环境变量前缀分别代表它们在 TiDB 集群中的角色。请注意，`sample_output` 中显示的 IP 地址会与您的不同。

  + `HOST_MONITOR` will host Prometheus and Grafana.
  + `HOST_CM` will host the TiUP Control Machine.
  + `HOST_PD` for Placement Driver server.
  + `HOST_DB` for TiDB server.
  + `HOST_KV` for TiKV server.
  + `HOST_TIFALSH` for TiFlash server.
  + `HOST_TIPROXY` for TiProxy server.

  ```bash
  cat hosts-env.sh
  ```

  ```output
  export HOST_MONITOR1_PRIVATE_IP=10.90.4.40
  export HOST_MONITOR1_PUBLIC_IP=35.166.47.245
  export HOST_CM_PRIVATE_IP=10.90.4.40
  export HOST_CM_PUBLIC_IP=35.166.47.245
  export HOST_PD1_PRIVATE_IP=10.90.2.51
  export HOST_PD1_PUBLIC_IP=52.27.45.10
  export HOST_DB1_PRIVATE_IP=10.90.2.14
  export HOST_DB1_PUBLIC_IP=44.244.238.105
  export HOST_DB2_PRIVATE_IP=10.90.2.43
  export HOST_DB2_PUBLIC_IP=34.219.136.55
  export HOST_KV1_PRIVATE_IP=10.90.1.93
  export HOST_KV1_PUBLIC_IP=52.12.133.66
  export HOST_KV2_PRIVATE_IP=10.90.1.30
  export HOST_KV2_PUBLIC_IP=18.236.119.16
  export HOST_KV3_PRIVATE_IP=10.90.1.208
  export HOST_KV3_PUBLIC_IP=35.90.161.51
  export HOST_TIFLASH1_PRIVATE_IP=10.90.4.243
  export HOST_TIFLASH1_PUBLIC_IP=34.210.114.26
  export HOST_TIPROXY1_PRIVATE_IP=10.90.4.154
  ```

### 步骤 2. 创建一个配备 TiProxy 的新 TiDB 集群

+ 检查提供的拓扑文件 `topology-with-tiproxy.yaml`，该文件用于部署 TiDB 集群。请注意拓扑文件中的 TiProxy 设置（TiDB 服务器配置下的 `security.auto-tls: true`、`graceful-wait-before-shutdown: 10` 以及 `tiproxy_servers`）。请注意，`sample_output` 中显示的 IP 地址会与您的不同。

  ```bash
  cat topology-with-tiproxy.yaml
  ```

  ```output
  ...
  server_configs:
  ...
    tidb:
      security.auto-tls: true
      graceful-wait-before-shutdown: 10
  ...
  tiproxy_servers:
    - host: 10.90.4.113
  ```

+ 以下代码块中的命令将按顺序执行一系列操作：1. 更改 [TiUP mirror](https://docs.pingcap.com/tidb/stable/production-deployment-using-tiup) 设置，2. 检查系统设置，3. 修复失败的检查，4. 部署 TiDB 集群，最后 5. 启动 TiDB 集群。大约需要 3 分钟完成。

  ```bash
  export PATH="$PATH:/home/ec2-user/.tiup/bin"
  tiup mirror set tidb-community-server-${LAB:TIDB_VERSION}-linux-amd64
  tiup cluster check ./topology-with-tiproxy.yaml \
   --user ec2-user \
   -i /home/ec2-user/.ssh/pe-class-key-${LAB:REGION_NAME}.pem \
   --apply
  tiup cluster deploy tidb-demo v${LAB:TIDB_VERSION} ./topology-with-tiproxy.yaml \
   --user ec2-user \
   -i /home/ec2-user/.ssh/pe-class-key-${LAB:REGION_NAME}.pem \
   --yes
  tiup cluster start tidb-demo
  sleep 5;
  tiup cluster display tidb-demo
  ```

  ```output
  Successfully set mirror to /home/ec2-user/tidb-community-server-${LAB:TIDB_VERSION}-linux-amd64
  /home/ec2-user/tidb-community-server-${LAB:TIDB_VERSION}-linux-amd64
  ...
  Cluster type:       tidb
  Cluster name:       tidb-demo
  Cluster version:    v${LAB:TIDB_VERSION}
  Deploy user:        ec2-user
  SSH type:           builtin
  Dashboard URL:      http://52.27.45.10:2379/dashboard
  Grafana URL:        http://10.90.4.40:3000
  ID                 Role          Host         Ports                            OS/Arch       Status  Data Dir                      Deploy Dir
  --                 ----          ----         -----                            -------       ------  --------                      ----------
  10.90.4.40:9093    alertmanager  10.90.4.40   9093/9094                        linux/x86_64  Up      /tidb-data/alertmanager-9093  /tidb-deploy/alertmanager-9093
  10.90.4.40:3000    grafana       10.90.4.40   3000                             linux/x86_64  Up      -                             /tidb-deploy/grafana-3000
  10.90.2.51:2379    pd            10.90.2.51   2379/2380                        linux/x86_64  Up|L    /tidb-data/pd-2379            /tidb-deploy/pd-2379
  10.90.4.40:9090    prometheus    10.90.4.40   9090/12020                       linux/x86_64  Up      /tidb-data/prometheus-9090    /tidb-deploy/prometheus-9090
  10.90.2.14:4000    tidb          10.90.2.14   4000/10080                       linux/x86_64  Up      -                             /tidb-deploy/tidb-4000
  10.90.2.43:4000    tidb          10.90.2.43   4000/10080                       linux/x86_64  Up      -                             /tidb-deploy/tidb-4000
  10.90.4.243:9000   tiflash       10.90.4.243  9000/3930/20170/20292/8234/8123  linux/x86_64  Down    /tidb-data/tiflash-9000       /tidb-deploy/tiflash-9000
  10.90.1.208:20160  tikv          10.90.1.208  20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.1.30:20160   tikv          10.90.1.30   20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.1.93:20160   tikv          10.90.1.93   20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.4.154:6000   tiproxy       10.90.4.154  6000/3080                        linux/x86_64  Up      -                             /tidb-deploy/tiproxy-6000
  Total nodes: 11
  ```

+ 请注意，`tiproxy` 组件也列在集群显示输出中。自管理集群由一个 TiProxy 实例和两个 TiDB 服务器实例组成。此外，虽然我们通常使用至少三个 PD 服务器，但这里只使用了一个 PD 服务器，因为本动手实验不涉及 PD 相关主题。

### 步骤 3. 验证负载均衡功能

+ 默认情况下，TiProxy 实例监听端口 6000 而不是端口 4000。让我们通过 TiProxy 连接到 TiDB 服务器实例。

  ```bash
  mysql -h ${HOST_TIPROXY1_PRIVATE_IP} --port 6000 -u root
  ```

  ```output
  mysql>
  ```

+ 创建一个名为 `test.tiproxy_test` 的表并退出连接。我们将使用它来证明 TiProxy 的连接负载均衡能力。

  ```sql
  DROP TABLE IF EXISTS test.tiproxy_test;
  CREATE TABLE test.tiproxy_test (id INT AUTO_INCREMENT PRIMARY KEY, tidb_server_instance VARCHAR(30));
  EXIT
  ```

  ```output
  Query OK, 0 rows affected, 1 warning (0.00 sec)
  Query OK, 0 rows affected (0.06 sec)
  Bye
  ```

+ 通过 TiProxy 生成 50 个数据库连接，在每个连接中，它将插入一个新行，然后关闭连接。请注意，`test.tiproxy_test` 表中的 `tidb_server_instance` 列将显示接受连接并处理插入 DML 的 TiDB 服务器实例的身份（格式为 **TIDB_SERVER_IP_ADDRESS:10080**）。

  ```bash
  cat > insert_one_row.sql <<EOF
  INSERT INTO test.tiproxy_test (tidb_server_instance)
  VALUES (
      (SELECT instance FROM information_schema.cluster_processlist
       WHERE host=(SELECT host FROM information_schema.processlist WHERE id=CONNECTION_ID())
      )
  );
  EOF
  cat > insert_one_row.sh <<EOF
  mysql -h ${HOST_TIPROXY1_PRIVATE_IP} --port 6000 -u root < insert_one_row.sql
  EOF
  chmod +x insert_one_row.sh
  for c in {1..50}; do
  ./insert_one_row.sh &
  done;
  sleep 1;
  jobs
  ```

  ```output
  ...
  [43]   Done                    ./insert_one_row.sh
  [44]   Done                    ./insert_one_row.sh
  [45]   Done                    ./insert_one_row.sh
  [46]   Done                    ./insert_one_row.sh
  [47]   Done                    ./insert_one_row.sh
  [48]   Done                    ./insert_one_row.sh
  [49]-  Done                    ./insert_one_row.sh
  [50]+  Done                    ./insert_one_row.sh
  ```

+ 连接到 TiDB 服务器实例。

  ```bash
  mysql -h ${HOST_TIPROXY1_PRIVATE_IP} --port 6000 -u root
  ```

+ 检查 `test.tiproxy_test` 表，您会发现连接和插入操作已被两个 TiDB 服务器实例均匀处理。请注意，如果您注意到连接计数有轻微差异，例如 28 对 22，这是正常且预期的。

  ```sql
  SELECT tidb_server_instance, COUNT(1)
  FROM test.tiproxy_test
  GROUP BY tidb_server_instance;
  EXIT
  ```

  ```output
  +----------------------+----------+
  | tidb_server_instance | count(1) |
  +----------------------+----------+
  | 10.90.1.14:10080     |       25 |
  | 10.90.1.43:10080     |       25 |
  +----------------------+----------+
  2 rows in set (0.00 sec)
  Bye
  ```

### 步骤 4. 验证会话迁移功能

+ 在计划维护操作期间，如 TiDB 扩容、缩容或集群升级，TiProxy 通过在活动的 TiDB 服务器实例之间无缝迁移现有会话，确保客户端应用程序的连接不中断。TiProxy 的主要目标是在维护 TiDB 服务器之间的负载均衡的同时，为您的应用程序提供零停机时间。

+ 查看提供的迷你 Java 程序代码，它将初始化 4 个线程来对表 `test.tiproxy_test` 运行插入工作负载。

  ```bash
  cat InsertJobNoExceptionHandling.java | grep -A1 -B1 'new Thread'
  ```

  ```output
          for (int i = 0; i < 4; i++) {
              new Thread(new Worker(tidbHost, port, dbUsername, dbPassword, (i + 1))).start();
          }
  ```

+ 如果线程遇到任何异常，它将打印错误堆栈并退出。

  ```bash
  cat InsertJobNoExceptionHandling.java | grep -A3 catch
  ```

  ```output
          } catch (Exception e) {
              e.printStackTrace();
              System.exit(1);
          }
  ```

+ 在端口 6000 上启动针对 TiProxy 的工作负载。请注意，它将使用 4 个线程连接到 TiDB 集群，从而产生 4 个数据库连接。

  ```bash
  rm -f InsertJobNoExceptionHandling.class
  javac -cp .:mysql-connector-java-5.1.36-bin.jar InsertJobNoExceptionHandling.java
  sleep 1
  java -cp .:mysql-connector-java-5.1.36-bin.jar InsertJobNoExceptionHandling ${HOST_TIPROXY1_PRIVATE_IP} 6000 root
  ```

  ```output
  Inserting 0 by worker 3
  Inserting 0 by worker 1
  Inserting 0 by worker 4
  Inserting 0 by worker 2
  Inserting 1 by worker 1
  Inserting 1 by worker 2
  Inserting 1 by worker 3
  Inserting 1 by worker 4
  Inserting 2 by worker 1
  Inserting 2 by worker 3
  Inserting 2 by worker 2
  Inserting 2 by worker 4
  ...
  ```

+ 点击 [Grafana 监控](http://${LAB:HOST_MONITOR1_PUBLIC_IP}:3000) 并使用用户名和密码（都是"admin"）登录。导航到 `Home` > `tidb-demo` > `tidb-demo-TiProxy-Summary` > `Balance`。观察 `Backend Connections` 面板，每个 TiDB 服务器应该有 2 个连接。

    ![90%](https://lab-static.pingcap.com/quick-demo/TiProxyBalance_2x2.png)

+ 将 `Refresh time` 更改为 `10s`。保持浏览器中的 `Balance` 面板打开，并保持 Java 程序运行。

+ 点击这里 - [终端 2](ssh://monitor1-ssh#2) 打开一个新的终端，连接到为你的实践实验分配的虚拟机。

+ 通过从集群中移除 IP 地址为 ${HOST_DB2_PRIVATE_IP} 的 TiDB 服务器来缩减 SQL 层。完成后，集群中只有 1 个 TiDB 服务器。

  ```bash
  export PATH="$PATH:/home/ec2-user/.tiup/bin"
  tiup cluster scale-in tidb-demo --node ${HOST_DB2_PRIVATE_IP}:4000 -y
  sleep 2
  tiup cluster display tidb-demo
  ```

  ```output
  ...
  Stopping component tidb
  ...
  Scaled cluster `tidb-demo` in successfully
  ...
  Cluster type:       tidb
  Cluster name:       tidb-demo
  Cluster version:    v${LAB:TIDB_VERSION}
  Deploy user:        ec2-user
  SSH type:           builtin
  Dashboard URL:      http://13.115.186.238:2379/dashboard
  Grafana URL:        http://10.90.4.53:3000
  ID                 Role          Host         Ports                            OS/Arch       Status  Data Dir                      Deploy Dir
  --                 ----          ----         -----                            -------       ------  --------                      ----------
  10.90.4.53:9093    alertmanager  10.90.4.53   9093/9094                        linux/x86_64  Up      /tidb-data/alertmanager-9093  /tidb-deploy/alertmanager-9093
  10.90.4.53:3000    grafana       10.90.4.53   3000                             linux/x86_64  Down    -                             /tidb-deploy/grafana-3000
  10.90.3.19:2379    pd            10.90.3.19   2379/2380                        linux/x86_64  Up|L    /tidb-data/pd-2379            /tidb-deploy/pd-2379
  10.90.4.53:9090    prometheus    10.90.4.53   9090/12020                       linux/x86_64  Up      /tidb-data/prometheus-9090    /tidb-deploy/prometheus-9090
  10.90.1.202:4000   tidb          10.90.1.202  4000/10080                       linux/x86_64  Up      -                             /tidb-deploy/tidb-4000
  10.90.4.75:9000    tiflash       10.90.4.75   9000/3930/20170/20292/8234/8123  linux/x86_64  Up      /tidb-data/tiflash-9000       /tidb-deploy/tiflash-9000
  10.90.3.10:20160   tikv          10.90.3.10   20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.3.207:20160  tikv          10.90.3.207  20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.3.208:20160  tikv          10.90.3.208  20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.4.56:6000    tiproxy       10.90.4.56   6000/3080                        linux/x86_64  Up      -                             /tidb-deploy/tiproxy-6000
  Total nodes: 10
  ```

+ 在[终端 1](ssh://monitor1-ssh#1) 上，迷你 Java 程序继续运行而不中断。

  ```output
  ...
  Inserting 1295 by worker 4
  Inserting 1295 by worker 3
  Inserting 1295 by worker 1
  Inserting 1295 by worker 2
  Inserting 1296 by worker 4
  Inserting 1296 by worker 3
  ...
  ```

+ 从浏览器中检查 Grafana TiProxy `Balance` 面板。4 个连接现在都在单个 TiDB 服务器上。2 个连接已被迁移。

![90%](https://lab-static.pingcap.com/quick-demo/TiProxyBalance_4x0.png)

+ 切换到[终端 2](ssh://monitor1-ssh#2) ，通过向集群添加一个 TiDB 服务器来扩展 SQL 层。完成后，集群中有 2 个 TiDB 服务器。

  ```bash
  export PATH="$PATH:/home/ec2-user/.tiup/bin"
  tiup cluster scale-out tidb-demo scale-out-tidb.yaml \
   --user ec2-user \
   -i ~/.ssh/pe-class-key-${LAB:REGION_NAME}.pem \
   -y
  tiup cluster display tidb-demo
  ```

  ```output
  ...
  Deploy TiDB instance
  ...
  Scaled cluster `tidb-demo` out successfully
  ...
  Cluster type:       tidb
  Cluster name:       tidb-demo
  Cluster version:    v${LAB:TIDB_VERSION}
  Deploy user:        ec2-user
  SSH type:           builtin
  Dashboard URL:      http://13.115.186.238:2379/dashboard
  Grafana URL:        http://10.90.4.53:3000
  ID                 Role          Host         Ports                            OS/Arch       Status  Data Dir                      Deploy Dir
  --                 ----          ----         -----                            -------       ------  --------                      ----------
  10.90.4.53:9093    alertmanager  10.90.4.53   9093/9094                        linux/x86_64  Up      /tidb-data/alertmanager-9093  /tidb-deploy/alertmanager-9093
  10.90.4.53:3000    grafana       10.90.4.53   3000                             linux/x86_64  Up      -                             /tidb-deploy/grafana-3000
  10.90.3.19:2379    pd            10.90.3.19   2379/2380                        linux/x86_64  Up|L    /tidb-data/pd-2379            /tidb-deploy/pd-2379
  10.90.4.53:9090    prometheus    10.90.4.53   9090/12020                       linux/x86_64  Up      /tidb-data/prometheus-9090    /tidb-deploy/prometheus-9090
  10.90.1.202:4000   tidb          10.90.1.202  4000/10080                       linux/x86_64  Up      -                             /tidb-deploy/tidb-4000
  10.90.1.233:4000   tidb          10.90.1.233  4000/10080                       linux/x86_64  Up      -                             /tidb-deploy/tidb-4000
  10.90.4.75:9000    tiflash       10.90.4.75   9000/3930/20170/20292/8234/8123  linux/x86_64  Up      /tidb-data/tiflash-9000       /tidb-deploy/tiflash-9000
  10.90.3.10:20160   tikv          10.90.3.10   20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.3.207:20160  tikv          10.90.3.207  20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.3.208:20160  tikv          10.90.3.208  20160/20180                      linux/x86_64  Up      /tidb-data/tikv-20160         /tidb-deploy/tikv-20160
  10.90.4.56:6000    tiproxy       10.90.4.56   6000/3080                        linux/x86_64  Up      -                             /tidb-deploy/tiproxy-6000
  Total nodes: 11
  ```

+ 再次返回到[终端 1](ssh://monitor1-ssh#1) ，您会发现迷你 Java 程序继续运行而不中断。

  ```output
  ...
  Inserting 1707 by worker 1
  Inserting 1707 by worker 3
  Inserting 1706 by worker 4
  Inserting 1708 by worker 2
  Inserting 1708 by worker 1
  Inserting 1708 by worker 3
  Inserting 1707 by worker 4
  ...
  ```

+ 再次从浏览器中检查 Grafana TiProxy `Balance` 面板。每个 TiDB 服务器有 2 个连接。2 个连接已被迁移。

![90%](https://lab-static.pingcap.com/quick-demo/TiProxyBalance_2x2_2.png)

+ 这就结束了 TiProxy 的会话/连接迁移能力演示。关于使用 TiProxy 支持计划的数据库在线滚动升级，我们有另一个独立的动手实验来演示这个功能，请访问 [使用 TiProxy 实现数据库零停机在线升级](/labs/demo_005) 了解更多详情。

+ 转到[终端 1](ssh://monitor1-ssh#1) ，按**CTRL-C**停止 Java 工作负载。然后，继续下一个模块。
