【软件系统架构】单体架构

news2025/3/19 5:33:23

一、引言

        在软件开发的漫长历程中,架构的选择一直是至关重要的决策。单体架构作为一种经典的架构模式,曾经在许多项目中发挥着不可替代的作用。虽然如今微服务等架构逐渐流行,但理解单体架构对于深入掌握软件架构体系仍然有着重要意义。

二、单体架构定义

        单体架构是一种将所有功能模块(如业务逻辑、数据访问、用户界面等)都打包在一个单一的可执行程序中的软件架构。就像是一个大的容器,里面包含了应用程序的所有部分,各个部分紧密耦合,共享代码库、数据库等资源。

三、单体架构发展历史

        早期的软件系统相对简单,单体架构因其简单直接的构建方式而被广泛采用。在计算机技术发展的初期,硬件资源有限,开发人员更倾向于构建紧凑、一体化的应用。随着业务需求的不断增长,单体架构也在不断扩展,但基本的架构模式在很长一段时间内保持不变。例如,许多传统的企业级应用,如早期的ERP系统,大多采用单体架构构建。

四、单体架构特点

(一)简单性

        开发相对简单,所有功能都在一个项目中,对于小型项目或者团队经验不足的情况下,易于上手。开发人员可以快速搭建起一个功能完整的应用,不需要处理复杂的分布式系统的通信、协调等问题。

(二)易于部署

        整个应用只需要部署一个单元,与分布式系统相比,部署过程更加直接。不需要考虑多个服务之间的部署顺序、依赖关系等复杂情况。

(三)紧耦合

        各个功能模块之间相互依赖,共享代码和数据结构。这种紧耦合的特性使得在修改一个模块时,可能会影响到其他模块的功能,导致系统的可维护性随着项目规模的扩大而降低。

五、单体架构细分类型

(一)分层式单体架构

  • 架构特点
    • 通常按照功能将应用分为表示层、业务逻辑层和数据访问层。表示层负责与用户交互,业务逻辑层处理业务规则,数据访问层与数据库交互。这种分层结构使得代码具有一定的组织性,便于开发人员理解和维护。
    • 各层之间通过接口进行通信,上层依赖下层,下层为上层提供服务。例如,表示层调用业务逻辑层的方法来处理用户请求,业务逻辑层再调用数据访问层的方法来获取或存储数据。
  • 适用场景
    • 适用于业务逻辑相对简单、规模较小的应用。比如一些小型的企业内部管理系统,如员工考勤系统,主要功能集中在数据的录入、查询和简单的统计分析,分层式单体架构可以很好地满足需求。

(二)模块化单体架构

  • 架构特点
    • 将应用划分为多个模块,每个模块负责特定的功能集。模块之间有一定的独立性,但仍然在同一个代码库中。例如,在一个电商应用中,可以将用户管理、商品管理、订单管理等分别作为不同的模块。
    • 模块之间可能存在一定的依赖关系,通过定义良好的接口来进行交互。这种架构在一定程度上提高了代码的可维护性和可扩展性,相比分层式单体架构,模块之间的耦合度更低。
  • 适用场景
    • 对于中等规模、功能相对较多但还不足以拆分微服务的应用比较适合。比如一个具有多种业务功能,如在线教育平台中的课程管理、学生学习记录管理、教师管理等功能的应用,可以采用模块化单体架构。

六、单体架构优缺点

分类具体描述示例说明
优点
开发效率单代码库快速开发,无需处理分布式系统复杂性,适合快速原型开发和简单需求项目。初创公司开发用户管理系统,1 周内完成核心功能并上线验证市场。
资源利用仅需单个运行环境,硬件资源占用低,适合小型项目或资源受限场景。小型企业使用 1 台服务器部署单体 ERP 系统,支撑 50 人同时在线办公。
缺点
可维护性差代码库庞大复杂,模块紧耦合,修改易引发连锁反应。修改订单表字段需同步更新订单处理、库存管理、财务结算等多个模块。
扩展性有限无法针对单一功能扩展,需整体升级,导致资源浪费。电商平台订单量激增时,需整体扩容服务器,而非仅扩展订单处理模块。

(一)优点

开发效率

        在项目初期,由于开发人员可以在一个代码库中快速开发功能,不需要考虑复杂的分布式系统构建,所以开发速度较快。对于一些快速原型开发或者需求明确、功能简单的项目来说,能够快速上线。

资源利用

        单体架构的应用只需要一个运行环境,相比于分布式架构,在资源消耗方面可能更低。例如,不需要为多个服务分别配置独立的服务器资源,在小型项目中可以充分利用有限的硬件资源。

(二)缺点

可维护性差

        随着应用规模的增大,代码库变得庞大复杂。由于各个功能模块之间的紧耦合,一个小的修改可能会在整个应用中产生连锁反应。例如,修改数据库结构可能会影响到多个业务逻辑模块,需要对整个应用进行全面的测试。

扩展性有限

        当需要对应用的某个功能进行大规模扩展时,由于单体架构的限制,很难做到独立扩展。例如,在一个单体架构的电商应用中,如果订单处理模块需要应对大量订单的处理,很难单独对该模块进行水平扩展,往往需要对整个应用进行扩展,这可能会带来不必要的资源浪费。

七、单体架构的案例

        以一个传统的图书馆管理系统为例。这个系统包含了图书信息管理(包括图书的录入、查询、借阅等)、读者信息管理(读者注册、借阅记录查询等)以及系统管理(用户权限管理等)等功能。整个系统采用单体架构构建,所有功能都在一个可执行程序中。开发人员使用分层式单体架构,将表示层、业务逻辑层和数据访问层分开。表示层提供用户界面,业务逻辑层处理诸如借阅规则、还书规则等业务逻辑,数据访问层与数据库交互存储和获取相关信息。

早期的 eBay 网站​

        eBay 在发展初期采用了单体架构。当时,其业务主要集中在提供一个在线拍卖平台,功能相对单一。单体架构使得 eBay 能够快速开发和部署网站,满足用户的基本需求。开发团队可以专注于核心业务功能的实现,如商品发布、竞拍、交易等功能的开发。随着业务的增长,eBay 逐渐面临性能和可扩展性的挑战,才开始逐步向分布式架构转型。​

小型企业的内部管理系统​

        许多小型企业的内部管理系统,如财务管理系统、人力资源管理系统等,常采用单体架构。以一个小型制造企业为例,其财务管理系统涵盖了账务处理、报表生成、预算管理等功能。由于企业规模较小,业务流程相对简单,采用单体架构可以满足企业的日常管理需求。开发和维护成本较低,企业内部的 IT 人员能够轻松应对系统的日常运维工作。

八、系统整体框架代码举例

以简单的Java分层式单体架构为例

(一)表示层(以JSP页面为例)

<%@ page contentType="text/html; charset=UTF - 8" %>
<html>
<head>
    <title>图书馆管理系统 - 图书查询</title>
</head>
<body>
    <h1>图书查询</h1>
    <form action="bookQueryServlet" method="post">
        <label for="bookTitle">图书标题:</label>
        <input type="text" id="bookTitle" name="bookTitle"><br>
        <input type="submit" value="查询">
    </form>
</body>
</html>

(二)业务逻辑层(BookQueryService.java)

import java.util.List;

public class BookQueryService {
    private BookDao bookDao;

    public BookQueryService(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public List<Book> queryBooksByTitle(String title) {
        return bookDao.getBooksByTitle(title);
    }
}

(三)数据访问层(BookDao.java)

import java.util.List;

public interface BookDao {
    List<Book> getBooksByTitle(String title);
}

// 假设的数据库连接类
class DatabaseConnection {
    // 数据库连接相关代码
}

// 实现BookDao接口的类
class BookDaoImpl implements BookDao {
    @Override
    public List<Book> getBooksByTitle(String title) {
        // 数据库查询逻辑,假设使用JDBC
        DatabaseConnection connection = new DatabaseConnection();
        // 执行查询并返回结果
        return null;
    }
}

以 Java Spring Boot 为例)

        下面是一个简单的基于 Spring Boot 的单体架构 Web 应用示例,实现了一个用户管理模块的基本功能,包括用户注册和查询。​

项目结构​

src/​

├── main/​

│ ├── java/​

│ │ └── com/​

│ │ └── example/​

│ │ ├── config/​

│ │ │ └── WebMvcConfig.java​

│ │ ├── controller/​

│ │ │ └── UserController.java​

│ │ ├── model/​

│ │ │ └── User.java​

│ │ ├── repository/​

│ │ │ └── UserRepository.java​

│ │ ├── service/​

│ │ │ └── UserService.java​

│ │ └── Application.java​

│ └── resources/​

│ ├── application.properties​

│ └── static/​

│ └── index.html​

└── test/​

└── java/​

└── com/​

└── example/​

└── ApplicationTests.java​

User 模型类​

package com.example.model;​

import javax.persistence.Entity;​

import javax.persistence.GeneratedValue;​

import javax.persistence.GenerationType;​

import javax.persistence.Id;​

​

@Entity​

public class User {​

@Id​

@GeneratedValue(strategy = GenerationType.IDENTITY)​

private Long id;​

private String username;​

private String password;​

​

// Getters and Setters​

public Long getId() {​

return id;​

}​

​

public void setId(Long id) {​

this.id = id;​

}​

​

public String getUsername() {​

return username;​

}​

​

public void setUsername(String username) {​

this.username = username;​

}​

​

public String getPassword() {​

return password;​

}​

​

public void setPassword(String password) {​

this.password = password;​

}​

}​

​

User 仓库接口​

package com.example.repository;​

​

import com.example.model.User;​

import org.springframework.data.jpa.repository.JpaRepository;​

​

public interface UserRepository extends JpaRepository<User, Long> {​

}​

User 服务类​

package com.example.service;​

import com.example.model.User;​

import com.example.repository.UserRepository;​

import org.springframework.beans.factory.annotation.Autowired;​

import org.springframework.stereotype.Service;​

​

@Service​

public class UserService {​

@Autowired​

private UserRepository userRepository;​

​

public User saveUser(User user) {​

return userRepository.save(user);​

}​

​

public User findUserById(Long id) {​

return userRepository.findById(id).orElse(null);​

}​

}​

User 控制器类​

package com.example.controller;​

import com.example.model.User;​

import com.example.service.UserService;​

import org.springframework.beans.factory.annotation.Autowired;​

import org.springframework.web.bind.annotation.*;​

​

@RestController​

@RequestMapping("/users")​

public class UserController {​

@Autowired​

private UserService userService;​

​

@PostMapping("/register")​

public User registerUser(@RequestBody User user) {​

return userService.saveUser(user);​

}​

​

@GetMapping("/{id}")​

public User getUserById(@PathVariable Long id) {​

return userService.findUserById(id);​

}​

}​

应用主类​

package com.example;​​

import org.springframework.boot.SpringApplication;​

import org.springframework.boot.autoconfigure.SpringBootApplication;​

​

@SpringBootApplication​

public class Application {​

public static void main(String[] args) {​

SpringApplication.run(Application.class, args);​

}​

}​

        这个简单的示例展示了一个单体架构 Web 应用的基本结构,各个模块(模型、仓库、服务、控制器)协同工作,实现了用户管理的部分功能。

九、未来发展趋势

        随着技术的不断发展,单体架构虽然在一些场景下仍然会被使用,但也在逐渐向混合架构发展。例如,在大型企业应用中,可能会将一些核心的、不易拆分的功能保留在单体架构部分,而将一些边缘的、需要独立扩展或频繁更新的功能拆分成微服务或者Serverless函数。同时,容器化技术也为单体架构的部署和管理提供了新的思路,通过将单体应用容器化,可以提高其可移植性和资源利用率。另外,为了提高单体架构的可维护性,代码模块化和自动化测试技术也会不断得到加强。

        尽管面临着诸多挑战,但单体架构在未来仍有其存在的价值。在一些特定场景下,如小型项目、对成本和开发速度要求极高的初创业务、功能简单且不需要频繁扩展的内部工具等,单体架构依然是一个不错的选择。同时,随着技术的发展,单体架构也在不断演进。例如,通过采用容器化技术(如 Docker),可以提高单体应用的部署效率和可移植性;利用云原生技术,将单体应用更好地融入云环境,享受云服务带来的弹性和便捷。此外,结合一些现代化的开发理念和工具,如微前端架构,可以在一定程度上缓解单体架构在大型项目中面临的可维护性和扩展性问题。未来,单体架构将与其他新型架构相互补充,共同为软件系统的构建提供多样化的选择。​

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【求助】【建议放弃】【谷粒商城版】Kubernetes

本文作者&#xff1a; slience_me 文章目录 Kubernetes【谷粒商城版】【建议放弃】1. docker安装2. kubernetes安装前3. kubeadm,kubelet,kubectl3.1 简介kubeadmkubeletkubectl常用指令 3.2 安装3.3 kubeadm初始化3.4 加入从节点(工作节点)3.5 安装Pod网络插件&#xff08;CNI…

C# Unity 唐老狮 No.10 模拟面试题

本文章不作任何商业用途 仅作学习与交流 安利唐老狮与其他老师合作的网站,内有大量免费资源和优质付费资源,我入门就是看唐老师的课程 打好坚实的基础非常非常重要: Unity课程 - 游习堂 - 唐老狮创立的游戏开发在线学习平台 - Powered By EduSoho C# 1. 内存中&#xff0c;堆和…

第十五届蓝桥杯2024JavaB组省赛试题A:报数游戏

简单的找规律题目。题目给得数列&#xff0c;第奇数项是20的倍数&#xff0c;第偶数项时24的倍数。题目要求第n 202420242024 项是多少。这一项是偶数&#xff0c;所以答案一定是24的倍数&#xff0c;并且偶数项的个数和奇数项的个数各占一半&#xff0c;所以最终的答案ans( n…

Matlab 汽车二自由度转弯模型

1、内容简介 Matlab 187-汽车二自由度转弯模型 可以交流、咨询、答疑 2、内容说明 略 摘 要 本文前一部分提出了侧偏角和横摆角速度作为参数。描述了车辆运动的运动状态&#xff0c;其中文中使用的参考模型是二自由度汽车模型。汽车速度被认为是建立基于H.B.Pacejka的轮胎模…

学c++的人可以几天速通python?

学了俩天啊&#xff0c;文章写纸上了 还是蛮有趣的

Rocky Linux 9.x 基于 kubeadm部署k8s 1.32

一、部署说明 1、主机操作系统说明 序号操作系统及版本备注1Rocky Linux release 9下载链接&#xff1a;https://mirrors.163.com/rocky/9.5/isos/x86_64/Rocky-9.5-x86_64-minimal.iso 2、主机硬件配置说明 作用IP地址操作系统配置关键组件k8s-master01192.168.234.51Rocky…

解决git init 命令不显示.git

首先在自己的项目代码右击 打开git bash here 输入git init 之后自己的项目没有.git文件&#xff0c;有可能是因为.git文件隐藏了&#xff0c;下面是解决办法

利用AI让数据可视化

1. 从问卷星上下载一份答题结果。 序号用户ID提交答卷时间所用时间来源来源详情来自IP总分1、《中华人民共和国电子商务法》正式实施的时间是&#xff08;&#xff09;。2、&#xff08;&#xff09;可以判断企业在行业中所处的地位。3、&#xff08;&#xff09;是指店铺内有…

解决qt中自定插件加载失败,不显示问题。

这个问题断断续续搞了一天多&#xff0c;主要是版本不匹配问题。 我们先来看下 Based on Qt 6.6.0 → 说明 Qt Creator 本身 是基于 Qt 6.6.0 框架构建的。MSVC 2019, 64-bit → 说明 Qt Creator 是使用 Microsoft Visual C 2019 编译器&#xff08;64 位&#xff09; 编译的。…

智慧社区3.0

项目介绍&#xff1a; 此项目旨在推动成都市探索**超大城市社区发展治理新路**&#xff0c;由三个实验室负责三大内容 1、**研发社区阵地空间管理模块**&#xff1a;AI算法实现态势感知&#xff08;如通过社区图片和视频、文本&#xff0c;对环境 空间质量、绿视率、安全感分…

Springboot+Vue登录、注册功能(含验证码)(后端!)

我们首先写一个接口&#xff0c;叫login&#xff01;然后对传入一个user&#xff0c;因为我们前端肯定是要传过来一个user&#xff0c;然后我们后端返回一个user&#xff0c;因为我们要根据这个去校验&#xff01;我们还引入了一个hutool的一个东西&#xff0c;在pom文件里面引…

搞定python之八----操作mysql

本文是《搞定python》系列文章的第八篇&#xff0c;讲述利用python操作mysql数据库。相对来说&#xff0c;本文的综合性比较强&#xff0c;包含了操作数据库、异常处理、元组等内容&#xff0c;需要结合前面的知识点。 1、安装mysql模块 PyMySql模块相当于数据库的驱动&#…

LVGL 中设置 UI 层局部透明,显示下方视频层

LVGL层次 LVGL自上而下分别是layer_sys > layer_top > lv_sreen_active > layer_bottom 即 系统层、顶层、活动屏幕、底层 原理 如果将UI设置为局部透明&#xff0c;显示下方的视频层&#xff0c;不仅仅需要将当前活动屏幕的背景设置为透明&#xff0c;还需要将底层…

21.多态

一、多态概念 多种形态。 静态多态&#xff1a;编译时多态。&#xff08;函数重载&#xff09; 动态多态&#xff1a;运行时多态。&#xff08;继承关系下&#xff0c;调用父类指针或引用&#xff0c;对于不同的对象有不同的行为&#xff09; 二、多态的定义及实现 1&#xff…

【蓝桥杯】第十三届C++B组省赛

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;蓝桥杯 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 试题A&#xff1a;九进制转十进制试题B&#xff1a;顺子日期试题C&#xff1a;刷题统计试题D&#xff1a;修剪灌木试题E&#xf…

C# PaddleOCR字符识别

1 安装Nuget 2 C# using System; using OpenCvSharp; using Sdcb.PaddleOCR; using Sdcb.PaddleOCR.Models.Local; using Sdcb.PaddleOCR.Models; using Sdcb.PaddleInference;namespace ConsoleApp1 {public class MichaelOCR{string imagePath "D:\\BUFFER\\VS\\Text\…

多环境开发-Profiles

在实际的项目开发中&#xff0c;我们通常会涉及多个环境&#xff0c;如开发环境&#xff08;dev&#xff09;、测试环境&#xff08;test&#xff09;和生产环境&#xff08;pro&#xff09;。在不同的环境下&#xff0c;程序的配置信息会有所不同&#xff0c;例如连接的数据库…

《TCP/IP网络编程》学习笔记 | Chapter 18:多线程服务器端的实现

《TCP/IP网络编程》学习笔记 | Chapter 18&#xff1a;多线程服务器端的实现 《TCP/IP网络编程》学习笔记 | Chapter 18&#xff1a;多线程服务器端的实现线程的概念引入线程的背景线程与进程的区别 线程创建与运行pthread_createpthread_join可在临界区内调用的函数工作&#…

MambaVision:一种Mamba-Transformer混合视觉骨干网络

摘要 我们提出了一种新型混合Mamba-Transformer主干网络&#xff0c;称为MambaVision&#xff0c;该网络专为视觉应用而设计。我们的核心贡献包括重新设计Mamba公式&#xff0c;以增强其对视觉特征的高效建模能力。此外&#xff0c;我们还对将视觉Transformer&#xff08;ViT&…

深度学习-服务器训练SparseDrive过程记录

1、cuda安装 1.1 卸载安装失败的cuda 参考&#xff1a;https://blog.csdn.net/weixin_40826634/article/details/127493809 注意&#xff1a;因为/usr/local/cuda-xx.x/bin/下没有卸载脚本&#xff0c;很可能是apt安装的&#xff0c;所以通过执行下面的命令删除&#xff1a; a…