前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >升级了项目的部署方式,坑死我了!

升级了项目的部署方式,坑死我了!

作者头像
程序员鱼皮
发布2024-04-30 17:20:45
1050
发布2024-04-30 17:20:45
举报
文章被收录于专栏:鱼皮客栈鱼皮客栈

大家好,我是程序员鱼皮。如标题所言,最近这两天,我对我们公司部分项目的部署方式进行了改造升级。

由于部署方式的调整可能会影响到线上用户的正常访问,所以只能挑在用户少的时间(凌晨)进行调整和测试。

结果没想到踩了不少坑,直到昨天半夜我还在跟其他团队的技术同学一起找 Bug:

这篇文章给大家分享下我们项目部署方式升级的形式、过程以及遇到的一些坑点,说不定以后大家也会用到~

为什么要进行升级?

最开始的时候,我们的项目几乎都是部署到服务器上的,而且很多项目是共用一台服务器,像这样:

为啥要这么做呢?

答案很简单,成本低啊!因为我正好有几台配置很高的服务器,这些服务器如果只部署 1 - 2 个项目,CPU、内存、带宽都用不满,妥妥的浪费资源。

而且现在小公司或个人部署项目可以直接使用宝塔 Linux 面板,非常方便。

所以除非必要,我们尽量不会使用额外产生费用的 CDN、按量计费的容器平台等等。

转眼从我创业到现在已经过去了一年多,为什么我们现在要重新调整项目的部署方式呢?

主要的几个原因:

1)随着业务增长,单体项目未必能够满足诉求,我们可能要将同一个项目部署在多个节点上,实现负载均衡和容错,手动部署就太麻烦了。这就需要能够灵活扩缩容机器节点的能力和流水线部署的能力。

2)项目部署在同一服务器,如果服务器宕机,将同时影响多个项目。

3)项目之间存在资源竞争,比如某个项目正在做大力推广、占用大量带宽资源,其他项目的可用带宽就很少了,访问会很慢。

4)权限风险。一旦给开发者开通服务器的访问权限,将能改动所有项目,还有误操作的可能性。

基于这些原因,再加上出现过一些事故,我们决定升级项目的部署方式。

部署方式变更

以前,我们的部署方式如下图:

用户要请求网站时,先通过 DNS 域名解析,找到服务器对应的 IP,经过高仿服务器后请求发送到 Nginx Web 服务器。然后 Nginx 根据请求路径判断,如果要访问文件,找到前端网站文件;如果请求的是接口,反向代理到后端服务。

升级后,我们的部署方式如下图:

主要有 3 个改动:

1)接入有安全防护和资源加速能力的 CDN,可以提高前端网站的加载速度。

2)后端使用容器平台进行部署,拥有动态扩缩容、负载均衡的能力。

3)前后端部署分离,不再依赖 Nginx 进行转发,而是区分不同的请求域名,通过 DNS 解析到不同的 CDN 上。

CDN 平台我是同时使用了腾讯云 CDN 和蓝易云 CDN,不同的项目选择了不同的 CDN。蓝易云 CDN(tsycdn.com)虽然不像腾讯云那么有名,但是性价比更高,能够有效防止 DDOS 攻击。在我网站被频繁攻击的那段时间,他们也帮了我不少。

而且最打动我的还是他们的技术支持,能耐心陪我一起改几个小时的 Bug,没谁了:

容器平台的话,我们将一部分服务放在了微信云托管上,可以很方便地配置流水线,实现提交代码到 GitHub 后自动发布和部署:

还可以查看服务日志、资源占用情况:

虽然微信云托管平台感觉很久没更新了,配置容器的灵活性也没那么高,但是能够满足大多数开发者的使用诉求了。

升级过程

1、后端服务迁移

既然后端服务要部署到容器平台,肯定要把项目制作为 Docker 镜像。

方法很简单,在后端项目根目录创建一个 Dockerfile ,编写构建镜像的命令即可。

比如 Spring Boot 项目可以使用类似下面的配置:

代码语言:javascript
复制
# 选择基础镜像
FROM maven:3.8.1-jdk-8-slim as builder

# 解决容器时期与真实时间相差 8 小时的问题
RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone

# 复制代码到容器内
WORKDIR /app
COPY pom.xml .
COPY src ./src

# 打包构建
RUN mvn package -DskipTests

# 容器启动时运行 jar 包
CMD ["java","-jar","/app/target/server.jar","--spring.profiles.active=prod"]

这里有个比较坑的地方,要注意容器环境的时间,有可能会和真实时间相差 8 小时,导致日志时间、以及插入到数据库的时间错误。

2、配置 CDN

配置 CDN 的关键是配置源站的地址。CDN 相当于是缓存,如果用户需要的数据在 CDN 上找不到,CDN 节点就会请求源站来获取数据,所以源站配置一定不能错。

上图中的回源设置,是指 CDN 请求源站的方式,包括协议、域名端口号等。

这里有 2 个注意事项:

1)避免给源站添加任何的重定向逻辑,否则可能重定向时直接暴露了源站地址。

比如 cdn 地址是 "yupi.icu",源站地址是 "base.yupi.icu",一般源站地址是要隐藏起来的,否则用户就可以绕过 CDN 直接攻击你的源站。如果源站配置了重定向逻辑,比如将后缀 "/" 路由到 "/aaa"。那么用户在访问 "yupi.icu/" 时,可能会被自动重定向到 "base.yupi.icu/aaa"!暴露了!

2)如果 CDN 站点开启了 HTTPS,回源协议尽量用 HTTP,否则可能会出现因为相同证书子域名 SSL 配置不一致导致的 421 错误(Misdirected Request),这个错误可以说是非常冷门了,不自己上线个项目,大概率听都没听说过。

3、配置 DNS

打通 CDN 到源站(容器平台)的访问后,最后一步就是配置 DNS,让用户访问的域名(比如 www.code-nav.cn)解析到 CDN。

需要注意的是,DNS 的解析生效时长在全国各地是不等的,所以有可能更改解析后,北京的用户访问不了、上海的用户能访问。所以不要急着把老服务下线掉!

本来以为很顺利,结果呢,CDN 访问源站竟然失败了,源站返回了 444 错误码(连接已关闭)!又是一个冷门的错误!

这个错误可把我折腾坏了,为啥我的服务器会拒绝国内 CDN 节点的连接呢?首先第一个猜测就是服务器封禁了 IP,于是查了高防、查了服务器防火墙、还咨询了云服务商的客服,结果都说没有封禁 IP。。。

于是,我去看了下 Nginx 的日志:

代码语言:javascript
复制
CDN 节点的 IP - - [29/Apr/2024:00:06:41 +0800] "GET /favicon.ico HTTP/1.1" 444 0 "https://www.code-nav.cn/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"

Nginx 既然已经收到了请求,说明大概率是 Nginx 配置拒绝了连接。但是我翻烂了 Nginx 的配置,也没找到在哪配置了 IP 封禁。。。

最后你猜怎么着?我突然想起来几年前,我曾经在这个服务器上购买过 Nginx 防火墙。虽然它早已过期,但貌似还能帮我自动封禁一些 IP。。。估计是因为昨天配 CDN 时我为了测试验证,使得访问源站频率过高导致的。

于是我把 Nginx 防火墙卸载了,就没有这个错误了。

用 4 个字来形容,我想到了 “阴魂不散”。 以上就是本期分享。当然,实际的升级过程,可比我这篇文章描述地还要麻烦,因为还涉及到一些平台(比如微信公众平台)的白名单配置。而且我们升级肯定是需要灰度的,先拿访问量最低的项目去验证流程,再陆续迁移其他项目。

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-29,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 程序员鱼皮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要进行升级?
  • 部署方式变更
  • 升级过程
    • 1、后端服务迁移
      • 2、配置 CDN
        • 3、配置 DNS
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com