前端打包

碎念念

Java项目是真的栈内存,JVM参数调几下还是难受

前提先包装nodejs,建议使用 nvm 进行安装方便版本管理(前端各种版本兼容问题很多)

总体逻辑:先install,再service、build(必须先安装前端项目需要的依赖才能正常启动服务和打包)

具体install、service、build的命令不用去管,根据使用的框架不同有不同的打包方式和命令,它们都定义在package.json文件中,我们只需直接使用npm、yarn、npmn之类的包管理工具简化命令(具体选哪个看你的喜好吧,nodejs安装后默认有npm,其他的yarn、npmn也好都可以使用npm先安装后使用),所以你需要做的就是形如:yarn installyarn serviceyarn build

打包成功后,会在根目录下生成dist目录,上传到服务器的静态资源路径中即可

环境搭建

#todo/note 可以先参考之前的文章:打造舒适开发环境

根据具体情况,选择安装方式,centos为例(使用包管理器:yum

本机

直接在服务器物理主机上安装

Nginx

更新系统软件包列表。

sudo yum update

安装 Nginx 命令。

sudo yum install nginx

安装完成后,可以使用以下命令启动 Nginx。

sudo systemctl start nginx

同时还需要设置 Nginx 开机自启。

sudo systemctl enable nginx

docker

通过Docker安装

项目部署

说白了,两种方法:物理机部署或者容器部署

物理机部署

以Java程序为例,前面步骤一致

  1. 安装JDK,配置Java环境
  2. 后端项目、前端项目打包
  3. 上传打包文件
  4. 若使用Nginx反代,事先安装并配置反代路由(建议物理机安装)
    最后,我们要启动Jar包,有两种方式:直接启动或者服务单元
Abstract
  1. 使用 nohup 启动命令

    • nohupnohup 是一个 Unix/Linux 命令,用于在后台运行命令,同时将命令的输出重定向到一个指定的文件中,即使当前终端关闭,命令也会继续运行。
    • /usr/local/java/zulu17.44.53-ca-jdk17.0.8.1-linux_x64/bin/java:Java 可执行文件的路径。
    • -Xms2048m -Xmx2048m:指定 Java 虚拟机的初始堆大小和最大堆大小。
    • -D 参数:通过 -D 参数设置 Java 系统属性。
    • -jar /home/12306/index12306-gateway-service.jar:指定要执行的 Java 可执行 JAR 文件。
    • > logs/index12306-gateway-service.file 2>&1:将标准输出和标准错误重定向到日志文件中。
    • &:在命令末尾加上 & 符号表示以后台方式运行命令。
  2. 服务单元:详情参考文章:Linux常用命令 > 启动系统服务

    • 服务单元是一种管理和控制系统服务的机制,通常用于 Linux 系统上。你可以创建一个服务单元来定义服务的启动、停止、重启等操作,以及服务的各种配置参数。
    • 使用服务单元可以方便地管理和控制系统服务,并且可以在系统启动时自动启动服务。

总的来说,使用 nohup 命令启动 Java 程序是一种简单的方式,适用于一次性或者临时的任务。而使用服务单元则更适合长期运行的服务,并且提供了更多的管理和控制功能。

容器部署

Tip
  • 编写dockerfile,适合单体
  • 编写docker-compose,适合微服务,容器编排,网络配置等,适合个人使用,一键启动
  • 但事实上两者都可以容器编排,两者可以结合使用

教学示例

以下是一个简单的 Dockerfile 示例,用于构建一个基于 OpenJDK 的 Java 应用容器镜像:

# 使用 OpenJDK 镜像作为基础镜像
FROM adoptopenjdk/openjdk17:alpine-jre

# 设置容器中的工作目录
WORKDIR /app

# 复制 Jar 文件到容器中
COPY index12306-aggregation-service.jar /app/
COPY index12306-gateway-service.jar /app/

# 复制 Nginx 配置文件到容器中
COPY nginx.conf /etc/nginx/nginx.conf

# 复制静态前端页面到容器中
COPY dist /usr/share/nginx/html

# 安装 Nginx
RUN apk update && \
    apk add --no-cache nginx && \
    rm -rf /var/cache/apk/*

# 暴露 Nginx 端口
EXPOSE 80

# 定义容器启动时运行的命令
CMD ["sh", "-c", "java -Xms2048m -Xmx2048m \
-Dunique-name=-lzy12306 \
-Dframework.cache.redis.prefix=lzy12306: \
-Dspring.data.redis.password=<REDIS_PASSWORD> \
-Dspring.data.redis.port=<REDIS_PORT> \
-Dspring.data.redis.host=<REDIS_HOST> \
-Drocketmq.name-server=<ROCKETMQ_SERVER> \
-Dspring.cloud.nacos.discovery.server-addr=<NACOS_SERVER> \
-Dpay.alipay.notify-url=<ALIPAY_NOTIFY_URL> \
-jar /app/index12306-aggregation-service.jar > /app/logs/index12306-aggregation-service.file 2>&1 \
& java -Xms2048m -Xmx2048m \
-Dunique-name=-lzy12306 \
-Dframework.cache.redis.prefix=lzy12306: \
-Dspring.data.redis.password=<REDIS_PASSWORD> \
-Dspring.data.redis.port=<REDIS_PORT> \
-Dspring.data.redis.host=<REDIS_HOST> \
-Dspring.cloud.nacos.discovery.server-addr=<NACOS_SERVER> \
-jar /app/index12306-gateway-service.jar > /app/logs/index12306-gateway-service.file 2>&1 \
& nginx -g 'daemon off;'"]

这个 Dockerfile 的主要作用是:

  1. 基于 adoptopenjdk/openjdk17:alpine-jre 镜像构建一个容器镜像。
  2. 设置容器的工作目录为 /app。
  3. 将 index12306-aggregation-service.jar 和 index12306-gateway-service.jar 文件复制到容器的工作目录。
  4. 复制 Nginx 配置文件 nginx.conf 到容器中的 /etc/nginx/nginx.conf。
  5. 复制静态前端页面 dist 到容器的 /usr/share/nginx/html 目录。
  6. 使用 apk 包管理器安装 Nginx。
  7. 暴露 Nginx 的80端口。
  8. 定义容器启动时运行的命令,启动 Java 服务和 Nginx 服务。

关于 Docker Compose 文件的编写,你可以创建一个名为 docker-compose.yml 的文件,内容如下:

version: '3'
services:
  app:
    build: .
    ports:
      - "80:80"
    volumes:
      - ./logs:/app/logs

这个 docker-compose.yml 文件指定了一个名为 app 的服务,使用当前目录下的 Dockerfile 构建容器镜像,并将容器的 80 端口映射到主机的 80 端口。同时将容器内的日志目录 logs 映射到主机的 ./logs 目录。

完善实例

这是开源项目Halo提供的docker-compose,这是直接使用对方已经通过dockerfile构建好并发布到容器仓库的halo和mysql镜像来构建服务,只需配置好挂载卷、端口映射、启动命令、网络桥接即可,还可以设置服务的启动顺序和依赖顺序。最终只需要在自己服务器创建一个这样的docker-compose文件并一键启动即可。

version: "3"

services:
  halo:
    image: halohub/halo:2.9
    container_name: halo
    restart: on-failure:3
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      halo_network:
    volumes:
      - ./:/root/.halo2
    ports:
      - "8090:8090"
    command:
      - --spring.r2dbc.url=r2dbc:pool:mysql://halodb:3306/halo
      - --spring.r2dbc.username=root
      # MySQL 的密码,请保证与下方 MYSQL_ROOT_PASSWORD 的变量值一致。
      - --spring.r2dbc.password=XXX
      - --spring.sql.init.platform=mysql
      # 外部访问地址,请根据实际需要修改
      - --halo.external-url=https://cytl.ink
      # 初始化的超级管理员用户名
      - --halo.security.initializer.superadminusername=admin
      # 初始化的超级管理员密码
      - --halo.security.initializer.superadminpassword=root

  halodb:
    image: mysql:8.0.31
    container_name: halodb
    restart: on-failure:3
    networks:
      halo_network:
    command: 
      - --default-authentication-plugin=mysql_native_password
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_general_ci
      - --explicit_defaults_for_timestamp=true
    volumes:
      - ./mysql:/var/lib/mysql
      - ./mysqlBackup:/data/mysqlBackup
    ports:
      - "3306:3306"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 3s
      retries: 5
      start_period: 30s
    environment:
      # 请修改此密码,并对应修改上方 Halo 服务的 SPRING_R2DBC_PASSWORD 变量值
      - MYSQL_ROOT_PASSWORD=XXX
      - MYSQL_DATABASE=halo

networks:
  halo_network:

备案

Tip
  • 备案主要是公信力,使用国内服务器空间必须备案。开启网站的域名访问,开启https,加密传输流量
  • 使用国外服务器空间,无上述限制

之前备案过一次,之后如果再次备案很多基本信息会默认填写

备案指的是域名备案,但域名备案必须依赖云空间

只要你使用的云空间(服务器)是国内的,那么你要想域名访问网站就必须完成备案

免备案方法

不用备案,域名访问国内空间

CloudFlare回源

利用cloudflare让未备案域名自动转发至自己服务器地址_cloudfare转发-CSDN博客
页面规则转发,免费用户可以设置三个,会暴露ip

Nginx反代

由于国内服务器允许未备案域名使用除80、443端口访问,所以我们可以直接将域名解析到国外服务器IP上,然后在国外服务器上设置反向代理,这种方法本质就是套娃

隧道-内网穿透⭐

本地机器也可以通过CloudFlare隧道完成内网穿透

优点:

  • 支持代理http协议,提供SSL证书,自动升级https
  • 免费,基本无流量限制
    缺点:
  • 需要自定义域才能使用它的隧道服务(这是你的缺点
  • 增加延迟(国内访问响应变慢)

开源的内网穿透方案:ftp,需要自行准备服务器搭建