—— Love98

服务器的使用和服务的部署

服务器的使用

为什么要服务器

首先我们需要知道什么是服务器,维基百科将其定义为为其他设备提供信息的硬件或软件。理论上,在自己的 IDE 中启动了一个项目,并为其他进程提供信息时,你的电脑或者你的IDE 均也可以被视为一个服务器。但是我们的服务通常需要长期稳定的运行,故一台供电、网络、系统都稳定且可靠的设备才会被我们作为服务器长期使用。

我们的服务需要部署在一台有公网 IP 的设备上面,才能被其他设备通过互联网访问。在国内,由于运营商的服务条款,我们基本无法在家宽上面部署公网服务。所以一台有公网 IP 的服务器成为了我们部署公网服务的必备工具。

选配服务器

现在想要购买一台服务器可以说是非常简单,云服务商们的内卷还是很严重的。对于新人,为会推荐购买国内的服务器,一方面是延迟较低,另一方面国内各大云服务商对于学生有很大的优惠,一台2c4g的服务器一年只要100RMB,当然也仅限首年,这里避免引流的嫌疑,为就不说是哪家厂商了。国内的服务器网络带宽普遍偏小,但是作为后端服务器基本够用了。

一般的云服务器商都会提供很多系统镜像,包括主流的 CentOS, Debian, Ubuntu, Red Hat, Windows Server,有些甚至会提供 ArchLinux, FreeBSD 等系统,这里我个人只推荐使用 Debian 系。

CentOS 停止维护;Ubuntu 强绑 snap,且图形化的优化在服务器上完全无意义;Red Hat 属于企业级的方案,太贵了;Windows Server 狗都不用;ArchLinux 跑服务器维护成本太高;FreeBSD,是谁?

我个人会更推荐低配机器(RAM < 1.5G)使用 Debian 11 系统,仅仅因为它的系统占用比 Debian 12 少 100M。

服务器的使用 (以 Debian 11 为例)

安全地连接

我们需要用到 ssh 工具连接云服务器,这几乎是我们通过正常手段操作服务器的唯一选择。

但是既然是通过网络的远程连接,我们就需要考虑安全问题,这里列举几种 ssh 的登录方式。

方法 安全性
root user + password 非常不安全,不推荐
root user + SSH key 相对安全,但是不推荐
general user + password 不安全,不推荐
general user + SSH key 安全,推荐

一般大厂在创建了机器后都会提供一个使用 sudo 无需密码的普通用户,并给你提供该用户的 SSH 私钥,让你使用上表中最后一种登录方式。

如果你的云服务商只提供了 root user + password 这种登录方案,也没有关系我们可以自行创建用户,详情可以参考学长博客:Linux SSH 远程配置及登录

优雅地初始化

如果你嫌每一行命令前面都加 sudo 麻烦,你可以在登录之后使用 root shell:

1
sudo su

拿到手的新机,第一件事情是更换软件源(简称:换源;仅中国大陆机器需要)和更新软件包(简称:滚包)

执行以下命令进行 “滚包”:

1
sudo apt update

如果你想的话,也可以顺手把预装的包更新了(不更新一般也没什么问题):

1
sudo apt upgrade

之后,我们需要安装一些非常常用的工具:

1
sudo apt install vim curl

你可能听说过 vim,也可能用过,甚至可能已经被它的高门槛劝退,但是这个是一定要学会使用的工具,它能够大幅减少你在服务器上面编辑文件的时间,就我本人而言,我甚至在 Windows 上面都会使用它编辑一些文件,或者写一些脚本。

此外,我们还需要对端口进行限制,我们需要放行22, 80, 443,同时阻断其他端口的请求。

我们可以使用系统自带的 iptables 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Flush existing rules
sudo iptables -F

# Set default policies to drop
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

# Allow SSH (port 22)
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Allow HTTP (port 80)
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# Allow HTTPS (port 443)
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Save the rules
sudo iptables-save > /etc/iptables/rules.v4

也可以使用防火墙工具 ufw 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Install ufw
sudo apt install ufw

# Deny incoming
sudo ufw default deny incoming

# Allow SSH
sudo ufw allow 22/tcp

# Allow HTTP
sudo ufw allow 80/tcp

# Allow HTTPS
sudo ufw allow 443/tcp

# Enable ufw
sudo ufw enable

服务的部署

部署一个服务有非常多的办法,对于不同语言编写的服务还有很多独特的部署方式。

部署 INFRA

Infra (基础设施) 包括但不限于 Nginx、MySQL、Redis,通常被多个服务共用。

部署 Nginx

Nginx 是一个 Web 服务器,有反向代理、负载均衡等等功能,我们通常使用其反向代理的功能。

对于 Nginx,我觉得用 “安装” 会比用 “部署” 更加贴切,毕竟我们通常是直接使用包管理器安装在宿主机上面。

安装 Nginx:

1
sudo apt install nginx

查看 Nginx 状态:

1
sudo systemctl status nginx

访问首页:

1
curl http://[your_server_ip]

设置自启动:

1
sudo systemctl enable nginx

它的配置文件放在 /etc/nginx 目录下,我们通常在 /etc/nginx/conf.d 目录下创建新的 web 服务的配置文件。

更多细节请访问官方文档

部署 Docker

我们之前讲过怎么在 Windows 上面部署 Docker,现在我们需要在服务器上面部署 Docker,它可以很好地帮我们做环境隔离,也可以很快地部署其他 Infra。

手动安装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Install required tools
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
gnupg-agent \
lsb-release \
software-properties-common

# Add GPG key
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo apt-key add -

# Add apt-get repo
sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/debian \
$(lsb_release -cs) \
stable"

# Update and Install
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

手动安装的过程相当繁琐,而且需要你有一定的包管理器使用基础,所以官方也提供了另外一种解决方案——安装脚本,这个脚本还提供了 “阿里云” 和 “Azure 中国” 两个镜像源可选

1
2
3
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun
# sudo sh get-docker.sh --mirror AzureChinaCloud

中国大陆服务器需要进行换源,可以在docker-registry-cn-mirror-test 查看可用源。然后在 /etc/docker/daemon.json 中添加可用源。

1
2
3
4
5
6
{
"registry-mirrors": [
"https://registry-1.docker.io",
"https://mirror.baidubce.com"
]
}

之后重启服务:

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

安装完成之后,执行以下命令验证:

1
sudo docker run hello-world

部署 MySQL & Redis

请参考Docker Hub 的 mysqlredis 进行安装。

需要注意的是如果你的一个容器需要访问另外一个 容器内的资源,如:你部署是后端服务需要访问 Redis,你需要在创建容器的时候添加额外参数 --link

部署自己的服务

我们以 Spring 服务的部署为例。

打包并上传

我们使用 Spring + Maven 的项目可以在 IDE 中使用 Maven 插件的 build 直接打包成 jar 包。

为了方便,我习惯在 Terminal 中开启两个终端

1
2
3
4
5
|———————|———————|
| | |
| ssh | sftp |
| | |
|———————|———————|

使用 ssh 连接到服务器,在用户目录下创建一个新的目录,如 deploy_test

使用 sftp 连接至服务器,它连接服务器的方法与 ssh 一致。将本地构建好的 jarput 至刚刚创建的目录下,同时将本地准备好的配置文件 (如果本地没有准备好,还需要在服务器上面编辑) 也上传至同一目录下,在上传完成之后就可以关闭 sftp 的连接了。

直接部署

我们需要安装对应版本的 JDK 或者 JRE,不过图省事,我们还是安装 JDK。

1
2
3
sudo apt install openjdk-{your-version}-jdk
# 查看是否安装成功
java -version

之后在 /etc/systemd/system 目录下创建文件 my-spring-app.service,然后写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=My Spring Boot Application
After=syslog.target

[Service]
User={your-username}
Group={your-user-group}
ExecStart=/usr/bin/java -jar /home/{your-username}/deploy_test/{your-snapshot}.jar --spring.config.location=/home/{your-username}/deploy_test/{your-application}.yaml
SuccessExitStatus=143
Restart=always
RestartSec=30
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target

重载 systemd 并启动你的服务:

1
2
3
4
5
6
sudo systemctl daemon-reload
sudo systemctl start my-spring-app
# 自启动
sudo systemctl enable my-spring-app
# 查看服务状态
sudo systemctl status my-spring-app

测试服务:

1
2
# Get Request
curl localhost:{your-port}{your-path}

Docker 部署

使用 Docker 部署只需要一行命令:

1
sudo docker run -d --link mysql --link redis -p 127.0.0.1:{your-port}:{your-port} -v /home/{your-username}/deploy_test:/dt -w /dt -e TZ=Asia/Shanghai --name deploy_test eclipse-temurin:{your-java-version}-jre-alpine java -jar {your-snapshot}.jar --spring.config.location={your-application}.yaml

使用 Nginx 反向代理

没有人会想要在访问网站的时候还加上一长串端口,开发者访问 API 的时候也一样,同时也为了方便我们管理入站和出站请求,我们需要将我们刚刚部署的服务端口通过 80 或 443 暴露出去。但是我们的服务器只有一个 80,也只有一个 443,如果我们有多个服务,同时在服务器上面部署,比如一个前端、一个后端,那么大家都想要抢占 80, 443,这在系统层面是不允许的,所以我们使用 Nginx 监听这两个端口,再根据其他特征,比如域名、路径等,发送给对应的端口。

创建并编辑文件 /etc/nginx/conf.d/my-spring-app.conf:

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
server_name example.com; # 你的域名或IP

location / {
proxy_pass http://localhost:{your-port}; # 反向代理到本地端口上的应用程序
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_set_header X-Forwarded-Proto $scheme;
}
}

重载配置文件:

1
sudo systemctl reload nginx

此时你的服务可以在公网访问。

参考资料