{T}

搭建开发环境

由于本课程是前后端分离架构,不涉及到微服务体系,所以开发环境相对比较容易搭建,对硬件环境的要求也不高

本课程一共包含了四个项目:

  • patient-wx(小程序)
  • patient-wx-api(小程序后端)
  • hospital-vue(MIS 前端)
  • hospital-api(MIS 后端)

HBase+Phoenix 大数据平台

MySQL 数据库有一个绕不过去的坎:单表数据量超过 2000万,CRUD 的性能会急速下降。所以要安排 DBA 或者自动化脚本,定期把半年或者一年的数据,迁移到归档数据库中,这样就可以起到缩表的目的。

如果开发的是普通的 MIS 系统,业务数据没有那么多,一个 MySQL 不用做定期归档也能支撑下来。但是类似于电商平台的项目,每天都会产生大量业务数据,一两个月就能累积几千万条数据。这种情况下,要么频繁的做数据归档,要么选择可以容纳数百 TB 而不需要归档的大数据平台。这里我选择了后者,既可以降低开发难度,又能减少请 DBA 的运维成本

HBase 技术

HBase 是一个分布式,版本化,面向列的开源数据库,构建在 Apache Hadoop 和 Apache ZooKeeper 之上。

HBase 是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用 HBase 技术可在廉价 PC Server上搭建起大规模结构化存储集群。HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库,HBase 基于列的而不是基于行的模式。

HBase 的特点

  1. 海量数据存储,HBase 中的表可以容纳上百亿行x上百万列的数据
  2. 列式存储,HBase 中的数据是基于列进行存储的,能够动态的增加和删除列
  3. 准实时查询,HBase 在海量的数据量下能够接近准实时的查询(百毫秒以内)
  4. 多版本,HBase 中每一列的数据都有多个版本。
  5. 高可靠性,HBase 中的数据存储于 HDFS 中且依赖于 Zookeeper 进行 Master 和 RegionServer 的协调管理

HBase 虽然支持表结构,但是操作起来并不方便。例如下面是个学生表,里面包含了若干的字段。如果给学生表添加新的记录,就需要执行下面的命令。 bash put 'Student', '0001', 'Stulnfo:Name', 'Tom Green', 1

img

想要获取数据的时候,我们执行get命令就可以了。

bash
get 'Student', '0001'

对于平时习惯 SQL 语句的人来说,上面的命令如果简单还行,要是叠加上复杂的条件和函数,那么阅读性就非常差,所以要引入Phoenix 技术

Phoenix

Phoenix 是给 HBase 添加了一个语法表示层,允许用 SQL 语句读写 HBase 中的数据,可以做联机事务处理,拥有低延迟的特性。

Phoenix 会把 SQL 编译成一系列的 Hbase 的 scan 操作,然后把 scan 结果生成标准的 JDBC 结果集,处理千万级行的数据也只用毫秒或秒级就搞定。而且 Phoenix 还支持 MyBatis 框架

部署 HBase 与 Phoenix

特此声明:尝试了无数遍之后,终于找到了完美支持 Phoenix 的图形客户端方案,但是 HBase 和 Phoenix 只能运行在Docker环境之外,安装步骤比较麻烦。如果你愿意尝试,可以查看本章附录5的内容。

找到 phoenix.tar.gz 镜像文件上传到 CentOS 系统中,执行命令把镜像文件导入 Docker 之中

bash
docker load < phoenix.tar.gz

镜像中已经包含和 HBase 和 Phoenix,所以只需要创建出容器即可。由于 HBase 需要使用的内存较大,这里没有规定具体的内存大小,容器会自动使用空闲的内存。容器中数据目录是 /tmp/hbase-root/hbase/data ,把这个目录映射到宿主机的 /root/hbase/data 目录

bash
docker run -it -d -p 2181:2181 -p 8765:8765 -p 15165:15165 \
-p 16000:16000 -p 16010:16010 -p 16020:16020 \
-v /root/hbase/data:/tmp/hbase-root/hbase/data \
-e TZ=Asia/Shanghai \
--name phoenix \
boostport/hbase-phoenix-all-in-one:2.0-5.0

运行上面命令报错 Error response from daemon: error creating overlay mount to /var/lib/docker/overlay2 。这个是因为用的 overlay2 文件系统,而系统默认只能识别 overlay 文件系统,所以就要更新文件系统了

bash
# systemctl stop docker      // 停掉 docker 服务
# rm -rf /var/lib/docker     // 注意会清掉 docker images 的镜像
# vim /etc/sysconfig/docker-storage       // 将文件里的 overlay2 改成 overlay 即可
例:DOCKER_STORAGE_OPTIONS="--storage-driver overlay"

# vim /etc/sysconfig/docker         //去掉 option 后面的 --selinux-enabled
然后启动docker即可:systemctl start docker

开放 Linux 的 2181、8765、15165、16000、16010、16020 端口

初始化Phoenix

运行命令,进入到 Phoenix 容器中,然后执行命令设置 HBASE_CONF_DIR 环境变量

bash
docker exec -it phoenix bash

export HBASE_CONF_DIR=/opt/hbase/conf/

连接 Phoenix 的命令行客户端。虽然 IDEA 也内置了 Phoenix 客户端,但是 Bug 挺多的用着并不方便,建议使用 Phoenix 自带的命令行客户端更好一些。而且要执行的 SQL 语句也并不多,命令行客户端已经足够用了

bash
/opt/phoenix-server/bin/sqlline.py localhost

image-20240403181943031

创建逻辑库和数据表

需要像操作 MySQL一样,先创建逻辑库然后定义数据表。在 Phoenix 的命令行客户端先来执行创建逻辑库的命令

bash
CREATE SCHEMA hospital;

USE hospital;

# 退出 Phoenix
!exit 

# 退出 docker
exit

把这个 SQL 文件中的语句复制粘贴到 Phoenix 的命令行中执行即可,过程需要几分钟

image-20240403182919900

配置 JDBC 连接信息

把 hospital-api 和 patient-wx-api 两个项目的 application.yml 文件打开,确认其中 JDBC 数据库连接信息

yaml
spring:
  datasource:
    driver-class-name: org.apache.phoenix.queryserver.client.Driver
    url: jdbc:phoenix:thin:url=http://124.222.10.5:8765;serialization=PROTOBUF
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      test-on-borrow: true
      test-while-idle: true
      max-active: 8
      min-idle: 4
      validation-query: SELECT 1

安装其他中间件

Redis 容器

把 Redis 镜像导入到 Docker 环境中

bash
docker load < Redis.tar.gz

在 CentOS 系统中创建 /root/redis/conf/redis.conf 文件,然后添加如下内容:

code
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 0
loglevel notice
logfile ""
databases 4
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
requirepass !xy343545

执行命令创建 Redis 容器,做好端口映射

bash
docker run -it -d --name redis -p 6379:6379 \
-v /root/redis/conf:/usr/local/etc/redis \
-e TZ=Asia/Shanghai \
redis:6.0.10 \
redis-server /usr/local/etc/redis/redis.conf

修改 Java 项目的 application.yml 文件,把其中 Redis 连接配置一下

yaml
spring:
  ……
  redis:
    database: 0
    host: localhost
    port: 6379
    password: !xy343545
    jedis:
      pool:
        max-active: 1000
        max-wait: -1ms
        max-idle: 16
        min-idle: 8

RabbitMQ 容器

通知消息用到 RabbitMQ 技术,不管什么数据库,MySQL 也好、MongoDB 也好,甚至说 HBase,都无法给保存的记录设置过期时间。

在一个对外运营的商业项目中,总是会有很多僵尸用户常年不上线。如果我们发送系统公告消息的时候,要不要给这些人发送消息呢?当然要,但是不必永久保存。把公告消息发送到 RabbitMQ 的消息队列中,给消息设置过期时间。假如在消息过期时间,用户上线了,那么他就可以收到公告消息,并且系统会把他收到的公告消息转存到数据库中,永久保存。

那些常年不上线的僵尸用户,发给他们的系统公告消息过了过期时间,会自动从 RabbitMQ 中删除,也不会转存到数据库中,这样我们就避免了为大量僵尸用户保存系统消息而占用海量存储存空间

bash
docker load < RabbitMQ.tar.gz

执行命令,创建出 RabbitMQ 容器,做好端口映射 4369、5671 和 5672 这些端口

plain
docker run -it -d --name mq \
-p 4369:4369 -p 5671:5671 -p 5672:5672 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=abc123456 \
-e TZ=Asia/Shanghai \
rabbitmq:3.8.9

创建 Minio 容器

采用 Minio 来充当私有云存储服务。我之前的一些实战课用的是腾讯云对象存储服务,公有云存储也挺好用的。但是作为医疗类的项目,我们把患者的诊断和处方等文件保存到公有云上面,不太尊重患者的隐私。

Minio 本质上就是个存储文件的服务器,操作起来更腾讯云存储类似。都是先要创建存储桶,然后在存储桶里面创建文件夹放置文件。我们可以给存储桶设置读写的权限和访问过期时间等等,总之用起来很简单就是了 img

把 Minio.tar.gz 文件,上传到 CentOS系统,然后执行命令,往 Docker 中导入镜像文件

bash
docker load < Minio.tar.gz

首先创建 /root/minio/data 文件夹,然后给这个文件夹设置权限,否则 Minio 将无法使用该文件夹保存文件

bash
chmod -R 777 /root/minio/data/

接下来创建 Minio 容器,设定的访问帐户是 root,密码为 abc123456,可以用浏览器访问 Web 管理画面。大家一定先做好端口映射,把 Linux 的 9000 和 9001 端口映射到 Windows系统

plain
docker run -it -d --name minio \
-p 9000:9000 -p 9001:9001 \
-v /root/minio/data:/data \
-e TZ=Asia/Shanghai --privileged=true \
--env MINIO_ROOT_USER="root" \
--env MINIO_ROOT_PASSWORD="abc123456" \
--env MINIO_SKIP_CLIENT="yes" \
bitnami/minio:latest

创建好容器之后,我们打开浏览器,访问 http://124.222.10.5:9001/login 然后填写好登陆信息,就能进入Web管理画面

在 Web 管理画面中创建 hospital 存储桶,并且把存储桶的访问权限设定成 Public

image-20240403190743757

image-20240403190911712

把课程 Git 上面 Minio 目录中的 doctor 和 patient-wx 两个文件夹,上传到 CentOS 的 /root/minio/data/hospital 目录中。然后在Minio 的 Web 管理画面中刷新一下,就能看到存储桶里面的这两个目录和里面的文件

重启 Linux 的任务清单

启动虚拟机之后,首先要运行 Docker服务,然后还要把 Docker 里面的容器逐一运行起来

plain
service docker start
docker start phoenix
docker start redis
docker start mq
docker start minio

运行 docker ps -a 指令看一下容器运行的状态,如果是是 Exited ,说明容器没有启动,可以用 docker logs 容器名称查看一下容器日志信息,找出其中的异常信息

运行初始化项目

到目前为止,我们已经把 Docker 环境中的各种中间件程序都搭建好了,这节课我们可以尝试运行初始化项目,看看能不能启动成功。

本课程GIT并没有放置最终版本代码,具体原因显而易见:非常不建议初学者使用最终版代码。因为你不知道数据库要添加什么记录,用什么角色登录,怎么去操作MIS系统,如何填写表单信息等等,更不知道前后端项目配置文件都意味什么。如果出现错误,你还没开始学习,所以异常信息肯定看不懂。所以你要从初始项目开始做起,一点点的熟悉全部业务。

启动 Java 项目

Java 项目的控制台没有报错信息的话,说明 Java 项目启动成功。

注意事项:尽量不要挪动 Java 项目在硬盘上的位置。通常情况,挪动 Java 项目之后,项目会出现启动失败的现象。解决办法是关闭 IDEA 工具,删除 Java 项目中的 .idea 文件夹,然后重新运行 IDEA 工具

启动小程序项目

配置小程序项目

在 HBuilderX 工具中导入 patient-wx 项目,然后在 manifest.json 文件中,填写小程序 APPID

main.js 文件上修改 minioUrlbaseUrl 两处 URL 路径。这里必须写你 Windows 电脑或者云主机的 IP 地址

img

打开 style.less 文件,把其中的 IP 地址写成云主机或者本地电脑的 IP

javascript
@baseUrl: 'http://1.117.154.252:9000/hospital/patient-wx';

初始化小程序项目

小程序项目引用 NodeJs 的一些依赖库,要用CNPM 命令下载这些依赖库,完成小程序项目依赖库的初始化。在命令行中进入到小程序所在的目录,执行下面的初始化命令:

plain
cnpm install

注意事项:小程序项目和前端 VUE 项目,都不要随便移动在硬盘上的位置。如果移动了位置,必须删除项目中的 node_modules 文件夹,然后重新初始化项目。另外项目最好不要放在中文目录下,否则容易导致项目无法启动

运行小程序项目

在运行菜单中找到小程序的运行选项,然后查看是否可以在微信开发者工具上面运行该项目,目前暂时不需要手机真机调试 img

启动前端 VUE 项目

打开 main.js 文件修改其中的 minioUrl 地址。另外 baseUrl 不需要修改,因为后端 Java 项目和前端 Vue 项目都运行在本地电脑上,所以用 localhost 可以访问到后端的 Java 项目

img

在命令行窗口执行启动前端项目的命令,然后打开浏览器访问 http://localhost:3000/hospital-vue,就能看到前端项目的登陆画面

plain
npm run dev

如果在登陆画面上,看到的只有背景图片,说明屏幕分辨率不足 1080p,要外接一个满足 1080p 以上分辨率的显示器就可以了。

如果你用的是 MacOS 系统,需要给 main.js 文件中添加一句话,否则 ElementPlus 组件库的 CSS 样式引用不上去

javascript
import 'element-plus/theme-chalk/el-message.css'