摘要:本文将手把手带你使用Go语言,并遵循依赖倒置、分层架构等最佳实践,构建一个高性能、高可用的全栈短链接生成器。项目采用Echo框架、GORM、Redis、MySQL,并通过Docker和Docker Compose实现一键式容器化部署到阿里云服务器。文章将深入探讨设计思路、核心功能实现、部署流程以及排障经验,附带完整的GitHub源码和在线演示地址。

前言 (Introduction)

大家好,我是Joker。在日常开发和分享中,我们经常会遇到URL过长不便分享的问题,一个简洁的短链接服务便显得尤为重要。最近,我基于Go语言从零构建并部署了一个功能完备的短链接生成器,整个过程涵盖了现代后端开发的诸多最佳实践。

写这篇博客的目的,是希望将整个项目的设计思路、技术选型、核心功能实现、容器化部署流程以及过程中遇到的各种“坑”与大家分享。无论你是Go语言的初学者,还是希望寻找一个完整项目实践的开发者,相信都能从中有所收获。

  • 🚀 在线演示地址: http://116.62.241.55

  • 📦 GitHub源码地址: https://github.com/Joker-0111-G/shortlink-go

一、 设计思路与架构 (Architecture & Design)

在编码之前,清晰的顶层设计是项目成功的关键。本项目严格遵循了以下原则:

  1. 分层架构 (Layered Architecture):我们采用了经典的 Controller -> Service -> Repository 三层架构,确保各层职责单一、清晰。

    • Controller层:负责接收和解析HTTP请求,对参数进行基础校验,然后调用Service层处理业务,最后将结果以JSON格式返回给前端。

    • Service层:核心业务逻辑层。它编排一个或多个Repository的操作,处理复杂的业务规则,如链接的创建、刷新、复用和清理等。

    • Repository层:数据持久层,负责与数据库和缓存(MySQL、Redis)直接交互,提供原子化的数据操作接口。

  2. 依赖倒置原则 (DIP):这是我们项目“高内聚、低耦合”的核心。通过定义interface(接口),我们让上层完全不依赖下层的具体实现。

    • Controller 依赖 Service 的接口。

    • Service 依赖 Repository 的接口。

    • 好处:未来如果想把MySQL换成PostgreSQL,只需重新实现一个Repository接口,Service层和Controller层的代码一行都不用改!这也极大地便利了单元测试。

  3. 数据库设计:除了基础字段,我们特别设计了expires_atdeleted_at字段,以支持链接有效期和“软删除”功能。软删除是生产环境的最佳实践,它避免了数据物理删除带来的风险,并为链接码的“回收复用”提供了基础。

  4. 无状态服务 (Stateless):我们的Go应用本身是无状态的,不存储任何会话信息。这使得它可以轻松地进行水平扩展,以应对未来的高并发需求。

二、 技术栈详解 (Technology Stack)

本项目采用了一套现代化且高效的技术栈:

核心后端 (Core Backend)

  • Go (Golang): 项目的主要编程语言,用于构建高性能的后端服务。

  • Echo v4: 一个高性能、可扩展、极简的Go语言Web框架,用于处理HTTP请求、路由和中间件。

  • GORM: Go语言中最流行的ORM(对象关系映射)库,用于以类型安全的方式操作数据库,并内置了连接池和防SQL注入等功能。

  • go-redis/v9: 用于在Go程序中与Redis进行交互的高性能官方客户端库。

  • Viper: 一个强大的Go配置库,用于管理config.yaml文件,实现代码与配置的分离。

前端 (Frontend)

  • HTML5: 构建网页的基本结构。

  • CSS3: 为网页提供样式,使其美观。

  • JavaScript (ES6+): 实现前端的动态逻辑,特别是:

    • Fetch API: 用于向后端异步发送HTTP请求(创建和获取链接列表)。

    • DOM 操作: 动态地将后端返回的数据渲染到页面上,实现历史记录的展示和实时更新。

数据库与缓存 (Database & Caching)

  • MySQL 8.0: 作为主数据库,用于持久化存储链接的映射关系、有效期等核心数据。

  • Redis 7.0: 作为高性能的内存缓存,用于缓存热点数据(短链接到原始链接的映射),极大地减轻数据库压力并提高访问速度。

架构与设计原则 (Architecture & Design Principles)

  • 分层架构: 采用了经典的Controller -> Service -> Repository分层设计,使得各层职责清晰,易于维护和测试。

  • 依赖倒置原则 (DIP): 通过定义interface(接口),实现了层与层之间的高层模块不依赖低层模块,两者都依赖于抽象,是项目可扩展、可重构的核心。

  • RESTful API: 后端接口遵循REST风格设计,使用HTTP动词(GET, POST)和清晰的URL结构来表达操作。

  • JSON: 作为前端和后端之间数据交换的标准格式。

  • 软删除 (Soft Deletion): 数据库设计最佳实践,通过deleted_at字段来标记数据为“已销毁”而不是物理删除,为数据恢复和链接码复用提供了基础。

  • 后台任务 (Background Job): 使用Go的Goroutine和time.Ticker实现了一个后台定时任务,用于自动清理过期的链接。

容器化与部署 (Containerization & Deployment)

  • Docker: 用于将Go应用、MySQL和Redis分别打包成独立的、环境一致的容器。

  • Docker Compose: 用于编排和管理多个Docker容器(应用、数据库、缓存),通过一个docker-compose.yml文件实现一键构建、启动和联网。

  • Dockerfile: 用于定义如何将我们的Go源代码、配置文件和前端文件打包成一个标准化的Docker镜像。

  • 阿里云 ECS (Elastic Compute Service): 作为项目的生产环境云服务器,提供了公网IP和稳定的运行环境。

  • 安全组 (Security Group): 阿里云提供的云端防火墙,用于控制服务器哪些端口可以被外部访问。

开发与协作工具 (Development & Collaboration Tools)

  • WSL2 (Windows Subsystem for Linux 2): 在Windows上提供了完整的Linux开发环境,用于本地开发和测试。

  • Visual Studio Code (VS Code): 项目的主要代码编辑器。

  • Git: 用于项目代码的版本控制。

  • GitHub : 作为远程代码仓库,用于代码托管、协作以及从云服务器上拉取代码。

底层协议与标准 (Underlying Protocols & Standards)

  • HTTP/1.1: Web应用通信的基础协议。

  • SSH (Secure Shell): 用于安全地远程登录和管理阿里云服务器,我们配置了更安全的密钥对认证

  • TCP/IP: 所有网络通信的基础协议栈,我们在排查端口问题时曾涉及。

三、 核心功能实现亮点

项目中包含了一些有趣且实用的功能实现:

  1. 链接的创建、刷新与复用逻辑 当用户请求创建一个短链接时,CreateShortLink服务会执行一个带事务的复杂逻辑:

    • Step 1: 检查是否存在:首先根据长链接查询数据库,看是否存在一个完全相同且未过期的短链接。如果存在,则直接刷新其有效期并返回,实现“刷新”功能。

    • Step 2: 优先复用:如果不存在,则尝试在数据库中寻找一个**最旧的、已被“软删除”**的记录。如果找到,就用新的长链接和有效期“复活”这条记录,并返回它原有的短链接码。这实现了短链接码的回收和循环利用。

    • Step 3: 创建全新:如果连可复用的记录也找不到,最后才会创建一条全新的记录,并生成新的短链接码。

    • 数据库锁:在“查找复用记录”的步骤中,我们使用了FOR UPDATE行锁,确保在高并发下,两个请求不会同时抢到同一个可复用的记录,保证了数据的一致性。

  2. 自动销毁后台任务 为了实现链接到期后自动“销毁”(软删除),我们在main.go中启动了一个后台Goroutine。它使用time.Ticker,每分钟触发一次,调用CleanupExpiredLinks服务,该服务会执行一条SQL语句,将所有expires_at早于当前时间的链接标记为“已删除”。

  3. 前端实时倒计时 在前端的历史记录表格中,我们使用setInterval定时器,每秒钟调用一次JavaScript函数来重新计算并渲染每个链接的“剩余时间”,实现了动态倒计时的效果,提升了用户体验。

四、 容器化与部署流程

容器化是本项目的一大亮点,它使得复杂的部署流程变得异常简单。

  1. 多阶段构建 Dockerfile: 我们为Go应用编写了一个多阶段构建的Dockerfile。第一阶段使用完整的golang镜像进行编译,第二阶段则只将编译好的二进制文件复制到一个极小的alpine镜像中。这使得我们的最终镜像体积仅有十几MB,非常轻量。

  2. docker-compose.yml 编排: 我们用一个文件定义了app, mysql_db, redis_cache三个服务,并配置了它们之间的依赖关系(depends_on)和网络。在Docker的内部网络中,Go应用可以通过服务名(如mysql_db)直接访问数据库,无需关心IP地址。

  3. 一键部署: 在阿里云服务器上配好环境后,整个部署流程浓缩为几步:

    # 1. 克隆代码
    git clone <your-repo-url>
    cd shortlink-go# 2. 创建生产环境配置文件 configs/config.yaml
    # (填入域名、数据库密码,并将数据库主机改为服务名 mysql_db)# 3. 一键构建并启动所有服务
    docker compose up --build -d
    

五、 踩坑与总结 (Troubleshooting)

在整个开发和部署过程中,我们也遇到了一些经典问题,这里分享一下:

  • 端口冲突:在本地和服务器上,反复遇到port is already in use的错误。最终发现,除了程序本身,Windows防火墙、第三方安全软件(如火绒)、阿里云安全组,都是需要检查和配置的地方。

  • WSL2与Windows的网络迷局:深刻理解了WSL2的网络模型。从外部设备访问WSL2中的服务,请求必须先经过Windows主机的网络堆栈和防火墙,这是解决跨设备访问问题的关键。

  • Docker构建问题:遇到了Go版本不匹配、国内服务器访问proxy.golang.org超时等问题。通过修改Dockerfile中的FROM镜像版本和添加国内GOPROXY代理配置,顺利解决。

结语 (Conclusion)

        从一个想法到完成云端部署,这个短链接项目让我们完整地体验了现代Web服务的开发全流程。通过拥抱Go语言的高性能、Docker的便捷部署以及分层解耦的架构设计,我们构建了一个虽小但“五脏俱全”的可靠服务。希望这篇文章能对你有所启发。如果你对项目有任何疑问或建议,欢迎在下方评论区交流,或者直接在GitHub上提Issue!

        感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/91157.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/91157.shtml
英文地址,请注明出处:http://en.pswp.cn/web/91157.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis_3

上一篇文章&#xff0c;我们学习了使用XML实现MyBatis进行增、删、查、改等操作&#xff0c;本篇文章&#xff0c;我们将学习#{ }和${ }获取方法参数的区别和使用MyBatisXML实现动态SQL语句。 #{ }和${ }的区别 在之前的文章中我们都是使用#{ }进行赋值&#xff0c;但实际上M…

智能图书馆管理系统开发实战系列(一):项目架构设计与技术选型

项目背景 智能图书馆管理系统&#xff08;ILMS&#xff09;是一个现代化的桌面应用程序&#xff0c;采用前后端分离架构&#xff0c;结合了Web技术的灵活性和桌面应用的用户体验。本项目从高保真原型设计开始&#xff0c;经过完整的软件开发生命周期&#xff0c;最终实现为一个…

应急前端“黄金3分钟”设计:极端场景下的操作界面极速搭建技术

摘要**地震突发&#xff0c;应急指挥系统的操作界面却因加载缓慢无法及时调取数据&#xff1b;火灾现场&#xff0c;消防员手持终端的操作步骤繁琐&#xff0c;延误救援时机。在分秒必争的极端场景中&#xff0c;传统前端操作界面为何频频 “掉链子”&#xff1f;怎样才能在 “…

【Android】三种弹窗 Fragment弹窗管理

三三要成为安卓糕手 零&#xff1a;布局转换 在很多工程当中用的都是LinearLayout和relativelayout&#xff0c;这两者都可以转化为Constrainlayout 注&#xff1a;这种用法并不能精确转换&#xff0c;具体还是要根据自己的需求来做布局约束一&#xff1a;snackbar显示弹窗 ((2…

【AI绘画】Stable Diffusion webUI 与 ComfyUI 全解析:安装、模型、插件及功能对比

一、Stable Diffusion 与 UI 工具概述 Stable Diffusion 是当前最主流的开源 AI 绘画模型&#xff0c;通过文本描述生成高质量图像。为降低使用门槛&#xff0c;开发者推出了多种图形界面&#xff08;UI&#xff09;工具&#xff0c;其中AUTOMATIC1111 webUI&#xff08;简称 …

ABP VNext + GraphQL Federation:跨微服务联合 Schema 分层

ABP VNext GraphQL Federation&#xff1a;跨微服务联合 Schema 分层 &#x1f680; 在微服务架构下&#xff0c;服务之间往往需要相互通信&#xff0c;而 GraphQL Federation 提供了一个有效的解决方案&#xff0c;帮助我们将多个微服务的 GraphQL API 聚合成一个统一的入口…

小程序组件的生命周期,以及在小程序中进行接口请求的方法设置

微信小程序组件生命周期与接口请求方法详解一、小程序组件生命周期微信小程序组件的生命周期指的是组件在不同阶段自动触发的函数&#xff0c;开发者可以利用这些钩子函数在特定时机执行相应操作。小程序组件的生命周期主要分为两类&#xff1a;组件自身生命周期和组件所在页面…

在线游戏玩家与物品交互处理

玩家与物品接触后的判定if (hit ! null && hit.CompareTag("Item")){Debug.Log("捡东西");var worldItem hit.gameObject.GetComponent<WorldItem>();if (worldItem ! null){var inventory GetComponent<PlayerInventory>();if (inv…

深入解析Java Stream 构建:AbstractPipeline

Java Stream 宏观介绍见&#xff1a;深入解析 Java Stream 设计&#xff1a;从四幕剧看流水线设计与执行机制-CSDN博客 PipelineHelper PipelineHelper 是 Java Stream API 内部一个至关重要的辅助类。正如其名&#xff0c;它是一个“管道助手”。可以把它想象成一个执行上下文…

《林景媚与命运回响》

《林景媚与命运回响》——当数据库开始回响命运&#xff0c;现实是否还能被信任&#xff1f;《林景媚数据库宇宙》系列第九部第一章&#xff1a;命运的涟漪公元 2089 年&#xff0c;数据库神谕的运行已趋于稳定&#xff0c;PostgreSQL Quantum Engine&#xff08;PQE&#xff0…

图神经网络入门:从GNN开始01图卷积网络GCN节点分类 02图注意力网络GAT 03图自编码器GAE 04 门控图神经网络GGNN

目录 一.基础1-[图论、图算法、CNN] 二.基础2-[图卷积神经网络GCN] 三.torch-geometric.nn工具包安装&#xff08;包含各种算法和数据集&#xff09; 四.GCN任务[节点分类-Cora 数据集] 五.图注意力网络&#xff08;GAT&#xff09; 六.图自编码器&#xff08;GAE&#x…

001 Configuration结构体构造

目录DramSys 代码分析1 Configuration结构体构造1.1 from_path 函数详解1.2 构造过程总结这种设计的好处2 Simulator 例化过程2.1 instantiateInitiatorDramSys 代码分析 1 Configuration结构体构造 好的&#xff0c;我们来详细解释一下 DRAMSysConfiguration.cpp 文件中 fro…

以太坊十年:智能合约与去中心化的崛起

以太坊10周年&#xff0c;敬开发者&#xff0c;敬构建者&#xff0c;敬还在链上的我们 以太坊即将迎来十周年纪念,作为一名在这个生态中深耕了8到9年的见证者&#xff0c;我亲历了它从一纸白皮书的构想到成长为全球领先去中心化平台的全过程。这十年间&#xff0c;以太坊经历了…

kafka 3.9.1版本: kraft + sasl+ standlone 模式完整可行安装步骤

Kafka 3.9.1 Kraft 单机模式安装 安装 OpenJDK 11 CentOS/RHEL yum install -y java-11-openjdk-develUbuntu/Debian apt install -y openjdk-11-jdk下载安装包 wget https://mirrors.aliyun.com/apache/kafka/3.9.1/kafka_2.12-3.9.1.tgz tar -zxvf kafka_2.12-3.9.1.tgz -C /…

Gitee DevOps平台深度评测:本土化优势与功能特性全面解析

Gitee DevOps平台深度评测&#xff1a;本土化优势与功能特性全面解析 在数字化转型浪潮下&#xff0c;企业软件开发流程的自动化与协作效率成为核心竞争力。作为国内领先的代码托管与DevOps平台&#xff0c;Gitee&#xff08;码云&#xff09;凭借其本土化服务与全流程支持能力…

从零开始本地化部署Dify:开源大模型应用平台搭建全指南

在AI应用开发的浪潮中&#xff0c;Dify作为一款开源的大语言模型(LLM)应用开发平台&#xff0c;正逐渐成为开发者和企业的首选工具。它巧妙地融合了后端即服务&#xff08;BaaS&#xff09;和LLMOps的理念&#xff0c;让开发者能够快速搭建生产级的生成式AI应用。无论是构建智能…

Qt 多媒体开发:音频与视频处理

Qt 多媒体模块提供了一套完整的 API&#xff0c;用于开发音频和视频处理应用。从简单的媒体播放到复杂的音视频编辑&#xff0c;Qt 都提供了相应的工具和组件。本文将从基础到高级全面解析 Qt 多媒体开发。 一、Qt 多媒体模块概述 1. 主要组件 Qt 多媒体模块包含以下核心组件&a…

Mac 专业图像处理 Pixelmator Pro

原文地址&#xff1a;Pixelmator Pro Mac 专业图像处理 Pixelmator Pro&#xff0c;是一款非常强大、美观且易于使用的图像编辑器&#xff0c;专为 Mac 设计。 采用单窗口界面、基于机器学习的智能图像编辑、自动水平检测&#xff0c;智能快速选择及更好的修复工具等功能优点…

iptables和IPVS比较

iptables 和 IPVS (IP Virtual Server) 都是 Linux 系统上用于处理网络流量的强大工具&#xff0c;但它们的设计目标、工作原理和适用场景有显著区别&#xff1a; 核心区别&#xff1a;主要目的&#xff1a; iptables&#xff1a; 核心是一个包过滤防火墙和网络地址转换工具。它…

语音识别指标计算 WER

目录 CER&#xff08;Character Error Rate&#xff09; WER Word Error Rate&#xff08;词错误率&#xff09; &#x1f9ee; WER 计算方式 &#x1f4cc; 示例 ✅ 理解要点 CER&#xff08;Character Error Rate&#xff09; 语音识别中的 CER&#xff08;Character …