微服务架构中10个常用的设计模式,建议收藏!-程序员宅基地

技术标签: 云原生  微服务  架构  设计模式  

accaafda26971e124d3c7f4fbf0040c8.jpeg来源:网络

欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 /  赠书福利

全栈前后端分离博客项目 2.0 版本完结啦, 演示链接http://116.62.199.48/ ,新项目正在酝酿中。全程手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。目前已更新了239小节,累计38w+字,讲解图:1645张,还在持续爆肝中.. 后续还会上新更多项目,目标是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,已有1200+小伙伴加入(早鸟价超低)

b627a5968a81723417bc2d3bb09f2bc3.gif

从软件开发早期(1960 年代)开始,应对大型软件系统中的复杂性一直是一项令人生畏的任务。多年来为了应对软件系统的复杂性,软件工程师和架构师们做了许多尝试:David Parnas 的模块化和封装 (1972), Edsger W. Dijkstra (1974)的关注点分离以及 SOA(1988)。

他们都是使用分而治之这项成熟的传统技术来应对大型系统的复杂性。自 2010 年开始,这些技术被证实无法继续应对 Web 级应用或者现代大型企业级应用的复杂性。因此架构师和工程师们发展出了一种全新的现代方式来解决这个问题,就是微服务架构。它虽然延续了分而治之的思想,但却是以全新的方式来实现的。

软件设计模式是解决软件设计中常见问题的通用、可复用的解决方案。设计模式让我们可以分享通用词汇并使用经实战检验的方案,以免重复造轮子。我先简单介绍下微服务架构。

通过阅读这篇文章,你会学到:

  • 微服务架构

  • 微服务架构的优势

  • 微服务架构的劣势

  • 何时使用微服务架构

最重要的微服务架构设计模式,包括其优缺点、用例、上下文、技术栈示例及可用资源。

请注意,本清单中的大部分设计模式常出现在多种语境中,并且可以在非微服务架构中使用。而我将在微服务这个特定语境中介绍它们。

微服务架构

我在之前的博客《微服务架构概述及为什么要应用在下个项目》和《单体软件架构真的终结了吗?》中对微服务架构有非常详尽的介绍。如果你感兴趣,可以阅读这两篇博客来深入了解。

  • https://towardsdatascience.com/microservice-architecture-a-brief-overview-and-why-you-should-use-it-in-your-next-project-a17b6e19adfd

  • https://towardsdatascience.com/looking-beyond-the-hype-is-modular-monolithic-software-architecture-really-dead-e386191610f8

那到底什么是微服务架构?有很多种定义方法。我的定义是这这样的:

微服务架构指的是将大型复杂系统按功能或者业务需求垂直切分成更小的子系统,这些子系统以独立部署的子进程存在,它们之间通过轻量级的、跨语言的同步(比如 REST,gRPC)或者异步(消息)网络调用进行通信。

下面是基于微服务架构的商业 Web 应用的组件视图:

e0c56665223bcc602b574143b4e61ae7.png来自 Md Kamaruzzaman 的微服务架构

微服务架构的重要特征

  • 整个应用程序被拆分成相互独立但包含多个内部模块的子进程

  • 与模块化的单体应用(Modular Monoliths)或 SOA 相反,微服务应用程序根据业务范围或领域垂直拆分。

  • 微服务边界是外部的,微服务之间通过网络调用(RPC 或消息)相互通信。

  • 微服务是独立的进程,它们可以独立部署。

  • 它们以轻量级的方式进行通信,不需要任何智能通信通道。

微服务架构的优点

  • 更好的开发规模

  • 更快的开发速度

  • 支持迭代开发或现代化增量开发

  • 充分利用现代软件开发生态系统的优势(云、容器、 DevOps、Serverless)

  • 支持水平缩放和细粒度缩放

  • 小体量,较低了开发人员的认知复杂性

微服务架构的缺点

  • 更高数量级的活动组件(服务、数据库、进程、容器、框架)

  • 复杂性从代码转移到基础设施

  • RPC 调用和网络通信的大量增加

  • 整个系统的安全性管理更具有挑战性

  • 整个系统的设计变得更加困难

  • 引入了分布式系统的复杂性

何时使用微服务架构

  • 大规模 Web 应用开发

  • 跨团队企业级应用协作开发

  • 长期收益优先于短期收益

  • 团队拥有能够设计微服务架构的软件架构师或高级工程师

微服务架构的设计模式

独享数据库(Database per Microservice)

当一家公司将大型单体系统替换成一组微服务,首先要面临的最重要决策是关于数据库。单体架构会使用大型中央数据库。即使转移到微服务架构许多架构师仍倾向于保持数据库不变。虽然有一些短期收益,但它却是反模式的,特别是在大规模系统中,微服务将在数据库层严重耦合,整个迁移到微服务的目标都将面临失败(例如,团队授权、独立开发等问题)。

更好的方法是为每个微服务提供自己的数据存储,这样服务之间在数据库层就不存在强耦合。这里我使用数据库这一术语来表示逻辑上的数据隔离,也就是说微服务可以共享物理数据库,但应该使用分开的数据结构、集合或者表,这还将有助于确保微服务是按照领域驱动设计的方法正确拆分的。

6ffa82f742577bfa56c3dc473231e1e5.pngMd Kamaruzzaman 的微服务独享数据库

优点

  • 数据由服务完全所有

  • 服务的开发团队之间耦合度降低

缺点

  • 服务间的数据共享变得更有挑战性

  • 在应用范围的保证 ACID 事务变得困难许多

  • 细心设计如何拆分单体数据库是一项极具挑战的任务

何时使用独享数据库

  • 在大型企业应用程序中

  • 当团队需要完全把控微服务以实现开发规模扩展和速度提升

何时不宜使用独享数据库

  • 在小规模应用中

  • 如果是单个团队开发所有微服务

可用技术示例

  • 所有 SQL、 NoSQL 数据库都提供数据的逻辑分离(例如,单独的表、集合、结构、数据库)。

事件源(Event Sourcing)

在微服务架构中,特别使用独享数据库时,微服务之间需要进行数据交换。对于弹性高可伸缩的和可容错的系统,它们应该通过交换事件进行异步通信。在这种情况,您可能希望进行类似更新数据库并发送消息这样的原子操作,如果在大数据量的分布式场景使用关系数据库,您将无法使用两阶段锁协议(2PL),因为它无法伸缩。而 NoSQL 数据库因为大多不支持两阶段锁协议甚至无法实现分布式事务。

在这些场景,可以基于事件的架构使用事件源模式。在传统数据库中,直接存储的是业务实体的当前“状态”,而在事件源中任何“状态”更新事件或其他重要事件都会被存储起来,而不是直接存储实体本身。这意味着业务实体的所有更改将被保存为一系列不可变的事件。因为数据是作为一系列事件存储的,而非直接更新存储,所以各项服务可以通过重放事件存储中的事件来计算出所需的数据状态。

3790b60ad5aaa3a6b93b98521d1240b6.pngMd Kamaruzzaman 的事件源

优点

  • 为高可伸缩系统提供原子性操作

  • 自动记录实体变更历史,包括时序回溯功能

  • 松耦合和事件驱动的微服务

缺点

  • 从事件存储中读取实体成为新的挑战,通常需要额外的数据存储(CQRS 模式)。

  • 系统整体复杂性增加了,通常需要领域驱动设计。

  • 系统需要处理事件重复(幂等)或丢失

  • 变更事件结构成为新的挑战。

何时使用事件源

  • 使用关系数据库的、高可伸缩的事务型系统

  • 使用 NoSQL 数据库的事务型系统

  • 弹性高可伸缩微服务架构

  • 典型的消息驱动或事件驱动系统(电子商务、预订和预约系统)

何时不宜使用事件源

  • 使用 SQL 数据库的低可伸缩性事务型系统

  • 在服务可以同步交换数据(例如,通过 API)的简单微服务架构中。

可用技术示例

  • 事件存储:EventStoreDB、Apache Kafka、Confluent Cloud、AWS Kinesis、Azure Event Hub、GCP Pub/Sub、Azure Cosmos DB、MongoDB、Cassandra、Amazon DynamoDB

  • 框架:Lagom、Akka、Spring、akkatecture、Axon、Eventuate

命令和查询职责分离(CQRS)

如果我们使用事件源,那么从事件存储中读取数据就变得困难了。要从数据存储中获取实体,我们需要处理所有的实体事件。有时我们对读写操作还会有不同的一致性和吞吐量要求。

这种情况,我们可以使用 CQRS 模式。在该模式中,系统的数据修改部分(命令)与数据读取部分(查询)是分离的。而 CQRS 模式有两种容易令人混淆的模式,分别是简单的和高级的。

在其简单形式中,不同实体或 ORM 模型被用于读写操作,如下所示:

96d0b2d3aceb692d563449bb75dac4db.pngMd Kamaruzzaman 的 CQRS (简单)

它有助于强化单一职责原则和分离关注点,从而实现更简洁的设计。

在其高级形式中,会有不同的数据存储用于读写操作。高级的 CQRS 通常结合事件源模式。根据不同情况,会使用不同类型的写数据存储和读数据存储。写数据存储是“记录的系统”,也就是整个系统的核心源头。

ad3ac7c76397df43199febcb8eb191f5.pngMd Kamaruzzaman 的 CQRS(高级)

对于读频繁的应用程序或微服务架构,OLTP 数据库(任何提供 ACID 事务保证的关系或非关系数据库)或分布式消息系统都可以被用作写存储。对于写频繁的应用程序(写操作高可伸缩性和大吞吐量),需要使用写可水平伸缩的数据库(如全球托管的公共云数据库)。标准化的数据则保存在写数据存储中。

对搜索(例如 Apache Solr、Elasticsearch)或读操作(KV 数据库、文档数据库)进行优化的非关系数据库常被用作读存储。许多情况会在需要 SQL 查询的地方使用读可伸缩的关系数据库。非标准化和特殊优化过的数据则保存在读存储中。

数据是从写存储异步复制到读存储中的,所以读存储和写存储之间会有延迟,但最终是一致的。

优点

  • 在事件驱动的微服务中数据读取速度更快

  • 数据的高可用性

  • 读写系统可独立扩展

缺点

  • 读数据存储是弱一致性的(最终一致性)

  • 整个系统的复杂性增加了,混乱的 CQRS 会显着危害整个项目。

何时使用 CQRS

  • 在高可扩展的微服务架构中使用事件源

  • 在复杂领域模型中,读操作需要同时查询多个数据存储。

  • 在读写操作负载差异明显的系统中

何时不宜使用 CQRS

  • 在没有必要存储大量事件的微服务架构中,用事件存储快照来计算实体状态是一个更好的选择。

  • 在读写操作负载相近的系统中。

可用技术示例

  • 写存储:EventStoreDB, Apache Kafka, Confluent Cloud, AWS Kinesis, Azure Event Hub, GCP Pub/Sub, Azure Cosmos DB, MongoDB, Cassandra. Amazon DynamoDB

  • 读存储:Elastic Search, Solr, Cloud Spanner, Amazon Aurora, Azure Cosmos DB, Neo4j

  • 框架:Lagom, Akka, Spring, akkatecture, Axon, Eventuate

Saga

如果微服务使用独享数据库,那么通过分布式事务管理一致性是一个巨大的挑战。你无法使用传统的两阶段提交协议,因为它要么不可伸缩(关系数据库),要么不被支持(多数非关系数据库)。

但您还是可以在微服务架构中使用 Saga 模式实现分布式事务。Saga 是 1987 年开发的一种古老模式,是关系数据库中关于大事务的一个替代概念。但这种模式的一种现代变种对分布式事务也非常有效。Saga 模式是一个本地事务序列,其每个事务在一个单独的微服务内更新数据存储并发布一个事件或消息。Saga 中的首个事务是由外部请求(事件或动作)初始化的,一旦本地事务完成(数据已保存在数据存储且消息或事件已发布),那么发布的消息或事件则会触发 Saga 中的下一个本地事务。

da7f7c3d0a0fc6361a470e13e4056966.pngMd Kamaruzzaman 的 Saga

如果本地事务失败,Saga 将执行一系列补偿事务来回滚前面本地事务的更改。

Saga 事务协调管理主要有两种形式:

  • 事件编排 Choreography:分散协调,每个微服务生产并监听其他微服务的事件或消息然后决定是否执行某个动作。

  • 命令编排 Orchestration:集中协调,由一个协调器告诉参与的微服务哪个本地事务需要执行。

优点

  • 为高可伸缩或松耦合的、事件驱动的微服务架构提供一致性事务。

  • 为使用了不支持 2PC 的非关系数据库的微服务架构提供一致性事务。

缺点

  • 需要处理瞬时故障,并且提供等幂性。

  • 难以调试,而且复杂性随着微服务数量增加而增加。

何时使用 Saga

  • 在使用了事件源的高可伸缩、松耦合的微服务中。

  • 在使用了分布式非关系数据库的系统中。

何时不宜使用 Saga

  • 使用关系数据库的低可伸缩性事务型系统。

  • 在服务间存在循环依赖的系统中。

可用技术示例

  • Axon, Eventuate, Narayana

面向前端的后端 (BFF)

在现代商业应用开发,特别是微服务架构中,前后端应用是分离和独立的服务,它们通过 API 或 GraphQL 连接。如果应用程序还有移动 App 客户端,那么 Web 端和移动客户端使用相同的后端微服务就会出现问题。因为移动客户端和 Web 客户端有不同的屏幕尺寸、显示屏、性能、能耗和网络带宽,它们的 API 需求不同。

面向前端的后端模式适用于需要为特殊 UI 定制单独后端的场景。它还提供了其他优势,比如作为下游微服务的封装,从而减少 UI 和下游微服务之间的频繁通信。此外,在高安全要求的场景中,BFF 为部署在 DMZ 网络中的下游微服务提供了更高的安全性。

c4ab232ecb9ca7740e881e3565c0e495.pngMd Kamaruzzaman 的面向前端的后端

优点

  • 分离 BFF 之间的关注点,使得我们可以为具体的 UI 优化他们。

  • 提供更高的安全性

  • 减少 UI 和下游微服务之间频繁的通信

缺点

  • BFF 之间代码重复

  • 大量的 BFF 用于其他用户界面(例如,智能电视,Web,移动端,PC 桌面版)

  • 需要仔细的设计和实现,BFF 不应该包含任何业务逻辑,而应只包含特定客户端逻辑和行为。

何时使用 BFF

  • 如果应用程序有多个含不同 API 需求的 UI

  • 出于安全需要,UI 和下游微服务之间需要额外的层。

  • 如果在 UI 开发中使用微前端。

何时不宜使用 BFF

  • 如果应用程序虽有多个 UI,但使用的 API 相同。

  • 如果核心微服务不是部署在 DMZ 网络中。

可用技术示例

  • 任何后端框架(Node.js,Spring,Django,Laravel,Flask,Play,…)都能支持。

API 网关

在微服务架构中,UI 通常连接多个微服务。如果微服务是细粒度的(FaaS) ,那么客户端可能需要连接非常多的微服务,这将变得繁杂和具有挑战性。此外,这些服务包括它们的 API 还将不断进化。大型企业还希望能有其他横切关注点(SSL 终止、身份验证、授权、节流、日志记录等)。

一个解决这些问题的可行方法是使用 API 网关。API 网关位于客户端 APP 和后端微服务之间充当 facade,它可以是反向代理,将客户端请求路由到适当的后端微服务。它还支持将客户端请求扇出到多个微服务,然后将响应聚合后返回给客户端。它还支持必要的横切关注点。

8472d95e03245a3c06ad9958ab8fd314.pngMd Kamaruzzaman 的 API 网关

优点

  • 在前端和后端服务之间提供松耦合

  • 减少客户端和微服务之间的调用次数

  • 通过 SSL 终端、身份验证和授权实现高安全性

  • 集中管理的横切关注点,例如,日志记录和监视、节流、负载平衡。

缺点

  • 可能导致微服务架构中的单点故障

  • 额外的网络调用带来的延迟增加

  • 如果不进行扩展,它们很容易成为整个企业应用的瓶颈。

  • 额外的维护和开发费用

何时使用 API 网关

  • 在复杂的微服务架构中,它几乎是必须的。

  • 在大型企业中,API 网关是中心化安全性和横切关注点的必要工具。

何时不宜使用 API 网关

  • 在安全和集中管理不是最优先要素的私人项目或小公司中。

  • 如果微服务的数量相当少。

可用技术示例

  • Amazon API 网关, Azure API 管理, Apigee, Kong, WSO2 API 管理器

Strangler

如果想在运行中的项目中使用微服务架构,我们需要将遗留的或现有的单体应用迁移到微服务。将现有的大型在线单体应用程序迁移到微服务是相当有挑战性的,因为这可能破坏应用程序的可用性。

一个解决方案是使用 Strangler 模式。Strangler 模式意味着通过使用新的微服务逐步替换特定功能,将单体应用程序增量地迁移到微服务架构。此外,新功能只在微服务中添加,而不再添加到遗留的单体应用中。

然后配置一个 Facade (API 网关)来路由遗留单体应用和微服务间的请求。当某个功能从单体应用迁移到微服务,Facade 就会拦截客户端请求并路由到新的微服务。一旦迁移了所有的功能,遗留单体应用程序就会被“扼杀(Strangler)”,即退役。

abab80d8dde47f2111db6b7f4be4c295.pngMd Kamaruzzaman 的 Strangler

优点

  • 安全的迁移单体应用程序到微服务

  • 可以并行地迁移已有功能和开发新功能

  • 迁移过程可以更好把控节奏

缺点

  • 在现有的单体应用服务和新的微服务之间共享数据存储变得具有挑战性

  • 添加 Facade (API 网关)将增加系统延迟

  • 端到端测试变得困难

何时使用 Strangler

  • 将大型后端单体应用程序的增量迁移到微服务

  • 何时不宜使用 Strangler

  • 如果后端单体应用很小,那么全量替换会更好。

  • 如果无法拦截客户端对遗留的单体应用程序的请求。

可用技术示例

  • API 网关后端应用框架。

断路器

在微服务架构中,微服务通过同步调用其他服务来满足业务需求。服务调用会由于瞬时故障(网络连接缓慢、超时或暂时不可用) 导致失败,这种情况重试可以解决问题。然而,如果出现了严重问题(微服务完全失败),那么微服务将长时间不可用,这时重试没有意义且浪费宝贵的资源(线程被阻塞,CPU 周期被浪费)。此外,一个服务的故障还会引发整个应用系统的级联故障。这时快速失败是一种更好的方法。

在这种情况,可以使用断路器模式挽救。一个微服务通过代理请求另一个微服务,其工作原理类似于电气断路器,代理通过统计最近发生的故障数量,并使用它来决定是继续请求还是简单的直接返回异常。

068efb8515b4b54f47de083af28b876c.pngMd Kamaruzzaman 的断路器

断路器可以有以下三种状态:

  • 关闭: 断路器将请求路由到微服务,并统计给定时段内的故障数量,如果超过阈值,它就会触发并进入打开状态。

  • 打开: 来自微服务的请求会快速失败并返回异常。在超时后,断路器进入半开启状态。

  • 半开: 只有有限数量的微服务请求被允许通过并进行调用。如果这些请求成功,断路器将进入闭合状态。如果任何请求失败,断路器则会进入开启状态。

优点

  • 提高微服务架构的容错性和弹性

  • 阻止引发其他微服务的级联故障

缺点

  • 需要复杂的异常处理

  • 日志和监控

  • 应该支持人工复位

何时使用断路器

  • 在微服务间使用同步通信的紧耦合的微服务架构中

  • 如果微服务依赖多个其他微服务

何时不宜使用断路器

  • 松耦合、事件驱动的微服务架构

  • 如果微服务不依赖于其他微服务

可用技术示例

  • API 网关,服务网格,各种断路器库(Hystrix, Reselience4J, Polly)。

外部化配置

每个业务应用都有许多用于各种基础设施的配置参数(例如,数据库、网络、连接的服务地址、凭据、证书路径)。此外在企业应用程序通常部署在各种运行环境(Local、 Dev、 Prod)中,实现这些的一个方法是通过内部配置。这是一个致命糟糕实践,它会导致严重的安全风险,因为生产凭证很容易遭到破坏。此外,配置参数的任何更改都需要重新构建应用程序,这在在微服务架构中会更加严峻,因为我们可能拥有数百个服务。

更好的方法是将所有配置外部化,使得构建过程与运行环境分离,生产的配置文件只在运行时或通过环境变量使用,从而最小化了安全风险。

优点

  • 生产配置不属于代码库,因而最小化了安全漏洞。

  • 修改配置参数不需要重新构建应用程序。

缺点

  • 我们需要选择一个支持外部化配置的框架。

何时使用外部化配置

  • 任何重要的生产应用程序都必须使用外部化配置。

何时不宜使用外部化配置

  • 在验证概念的开发中。

可用技术示例

  • 几乎所有企业级的现代框架都支持外部化配置。

消费端驱动的契约测试

在微服务架构中,通常有许多有不同团队开发的微服务。这些微型服务协同工作来满足业务需求(例如,客户请求),并相互进行同步或异步通信。消费端微服务的集成测试具有挑战性,通常用 TestDouble 以获得更快、更低成本的测试运行。但是 TestDouble 通常并不能代表真正的微服务提供者,而且如果微服务提供者更改了它的 API 或 消息,那么 TestDouble 将无法确认这些。另一种选择是进行端到端测试,尽管它在生产之前是强制性的,但却是脆弱的、缓慢的、昂贵的且不能替代集成测试(Test Pyramid)。

在这方面消费端驱动的契约测试可以帮助我们。在这里,负责消费端微服务的团队针对特定的服务端微服务,编写一套包含了其请求和预期响应(同步)或消息(异步)的测试套件,这些测试套件称为显式的约定。对于微服务服务端,将其消费端所有约定的测试套件都添加到其自动化测试中。当特定服务端微服务的自动化测试执行时,它将一起运行自己的测试和约定的测试并进行验证。通过这种方式,契约测试可以自动的帮助维护微服务通信的完整性。

优点

  • 如果提供程序意外更改 API 或消息,可以被快速的自动发现。

  • 更少意外、更健壮,特别是包含大量微服务的企业应用程序。

  • 改善团队自主性。

缺点

  • 需要额外的工作来开发和集成微服务服务端的契约测试,因为他们可能使用完全不同的测试工具。

  • 如果契约测试与真实服务情况不匹配,将可能导致生产故障。

何时使用需求驱动的契约测试

  • 在大型企业业务应用程序中,通常由不同的团队开发不同服务。

何时不宜使用消费端驱动的契约测试

  • 所有微服务由同一团队负责开发的小型简单的应用程序。

  • 如果服务端微服务是相对稳定的,并且不处在活跃的开发状态。

可用技术示例

  • Pact, Postman, Spring Cloud Contract

总结

在现代大规模企业软件开发中,微服务架构能够帮助开发扩展规模并带来很多长期收益。但是微服务架构并不是随处可用的银弹,如果应用在错误的应用程序类型,微服务架构将弊大于利。希望采用微服务架构的开发团队应该遵循最佳实践,并使用一系列可重用的、久经锤炼的设计模式。

微服务架构中至关重要的设计模式是独享数据库。实现这种设计模式具有挑战性,需要其他几种密切相关的设计模式(事件驱动、 CQRS、 Saga)来支持。在具有多个客户端(Web、 Mobile、 Desktop、 Smart Devices)的典型业务应用程序中,客户端和微服务之间的通信量可能是很大的,并且需要统一的安全控制,在这种情况面向前端的后端和 API 网关的设计非常有用。

此外,断路器模式可以大大地帮助应对这类应用程序的错误处理场景。迁移遗留的单体应用到微服务是极具挑战性的,而 Strangler 模式可以帮助做到这点。消费端驱动的契约测试是微服务集成测试的基础模式。另外外部化配置是任何现代化应用程序开发中的一种必备模式。

这个系列并不全面,在实际情况中您可能需要其他的设计模式,但这个系列能为您提供一个关于微服务架构设计模式的极好介绍。

欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 /  赠书福利

全栈前后端分离博客项目 2.0 版本完结啦, 演示链接http://116.62.199.48/ ,新项目正在酝酿中。全程手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。目前已更新了239小节,累计38w+字,讲解图:1645张,还在持续爆肝中.. 后续还会上新更多项目,目标是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,已有1200+小伙伴加入(早鸟价超低)

c4260c550bee5cf9c120bd56f07894b8.gif

5e01a985dbbbdad724e8207443676266.jpeg


d2dda7b039a6cba3f71029d561171e5e.gif



1. 我的私密学习小圈子~
2. 手动实现 Spring Boot 日志链路追踪,无需引入组件,日志定位更方便!
3. 分库分表后,数据库数据一致性问题如何解决?
4. MySQL 模糊查询再也不用like+%了

最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。
点“在看”支持小哈呀,谢谢啦
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weiwosuoai/article/details/137814396

智能推荐

海康威视网络摄像头开发流程(五)------- 直播页面测试_ezuikit 测试的url-程序员宅基地

文章浏览阅读3.8k次。1、将下载好的萤石js插件,添加到SoringBoot项目中。位置可参考下图所示。(容易出错的地方,在将js插件在html页面引入时,发生路径错误的问题)所以如果对页面中引入js的路径不清楚,可参考下图所示存放路径。2、将ezuikit.js引入到demo-live.html中。(可直接将如下代码复制到你创建的html页面中)<!DOCTYPE html><html lan..._ezuikit 测试的url

如何确定组态王与多动能RTU的通信方式_组态王ua-程序员宅基地

文章浏览阅读322次。第二步,在弹出的对话框选择,设备驱动—>PLC—>莫迪康—>ModbusRTU—>COM,根据配置软件选择的协议选期期,这里以此为例,然后点击“下一步”。第四步,把使用虚拟串口打勾(GPRS设备),根据需要选择要生成虚拟口,这里以选择KVCOM1为例,然后点击“下一步”设备ID即Modbus地址(1-255) 使用DTU时,为下485接口上的设备地址。第六步,Modbus的从机地址,与配置软件相同,这里以1为例,点击“下一步“第五步,Modbus的从机地址,与配置软件相同,这里以1为例,点击“下一步“_组态王ua

npm超详细安装(包括配置环境变量)!!!npm安装教程(node.js安装教程)_npm安装配置-程序员宅基地

文章浏览阅读9.4k次,点赞22次,收藏19次。安装npm相当于安装node.js,Node.js已自带npm,安装Node.js时会一起安装,npm的作用就是对Node.js依赖的包进行管理,也可以理解为用来安装/卸载Node.js需要装的东西_npm安装配置

火车头采集器AI伪原创【php源码】-程序员宅基地

文章浏览阅读748次,点赞21次,收藏26次。大家好,小编来为大家解答以下问题,python基础训练100题,python入门100例题,现在让我们一起来看看吧!宝子们还在新手村练级的时候,不单要吸入基础知识,夯实自己的理论基础,还要去实际操作练练手啊!由于文章篇幅限制,不可能将100道题全部呈现在此除了这些,下面还有我整理好的基础入门学习资料,视频和讲解文案都很齐全,用来入门绝对靠谱,需要的自提。保证100%免费这不,贴心的我爆肝给大家整理了这份今天给大家分享100道Python练习题。大家一定要给我三连啊~

Linux Ubuntu 安装 Sublime Text (无法使用 wget 命令,使用安装包下载)_ubuntu 安装sumlime text打不开-程序员宅基地

文章浏览阅读1k次。 为了在 Linux ( Ubuntu) 上安装sublime,一般大家都会选择常见的教程或是 sublime 官网教程,然而在国内这种方法可能失效。为此,需要用安装包安装。以下就是使用官网安装包安装的教程。打开 sublime 官网后,点击右上角 download, 或是直接访问点击打开链接,即可看到各个平台上的安装包。选择 Linux 64 位版并下载。下载后,打开终端,进入安装..._ubuntu 安装sumlime text打不开

CrossOver for Mac 2024无需安装 Windows 即可以在 Mac 上运行游戏 Mac运行exe程序和游戏 CrossOver虚拟机 crossover运行免安装游戏包-程序员宅基地

文章浏览阅读563次,点赞13次,收藏6次。CrossOver24是一款类虚拟机软件,专为macOS和Linux用户设计。它的核心技术是Wine,这是一种在Linux和macOS等非Windows操作系统上运行Windows应用程序的开源软件。通过CrossOver24,用户可以在不购买Windows授权或使用传统虚拟机的情况下,直接在Mac或Linux系统上运行Windows软件和游戏。该软件还提供了丰富的功能,如自动配置、无缝集成和实时传输等,以实现高效的跨平台操作体验。

随便推点

一个用聊天的方式让ChatGPT写的线程安全的环形List_为什么gpt一写list就卡-程序员宅基地

文章浏览阅读1.7k次。一个用聊天的方式让ChatGPT帮我写的线程安全的环形List_为什么gpt一写list就卡

Tomcat自带的设置编码Filter-程序员宅基地

文章浏览阅读336次。我们在前面的文章里曾写过Web应用中乱码产生的原因和处理方式,旧文回顾:深度揭秘乱码问题背后的原因及解决方式其中我们提到可以通过Filter的方式来设置请求和响应的encoding,来解..._filterconfig selectencoding

javascript中encodeURI和decodeURI方法使用介绍_js encodeur decodeurl-程序员宅基地

文章浏览阅读651次。转自:http://www.jb51.net/article/36480.htmencodeURI和decodeURI是成对来使用的,因为浏览器的地址栏有中文字符的话,可以会出现不可预期的错误,所以可以encodeURI把非英文字符转化为英文编码,decodeURI可以用来把字符还原回来_js encodeur decodeurl

Android开发——打包apk遇到The destination folder does not exist or is not writeable-程序员宅基地

文章浏览阅读1.9w次,点赞6次,收藏3次。前言在日常的Android开发当中,我们肯定要打包apk。但是今天我打包的时候遇到一个很奇怪的问题Android The destination folder does not exist or is not writeable,大意是目标文件夹不存在或不可写。出现问题的原因以及解决办法上面有说报错的中文大意是:目标文件夹不存在或不可写。其实问题就在我们的打包界面当中图中标红的Desti..._the destination folder does not exist or is not writeable

Eclipse配置高大上环境-程序员宅基地

文章浏览阅读94次。一、配置代码编辑区的样式 <1>打开Eclipse,Help —> Install NewSoftware,界面如下: <2>点击add...,按下图所示操作: name:随意填写,Location:http://eclipse-color-th..._ecplise高大上设置

Linux安装MySQL-5.6.24-1.linux_glibc2.5.x86_64.rpm-bundle.tar_linux mysql 安装 mysql-5.6.24-1.linux_glibc2.5.x86_6-程序员宅基地

文章浏览阅读2.8k次。一,下载mysql:http://dev.mysql.com/downloads/mysql/; 打开页面之后,在Select Platform:下选择linux Generic,如果没有出现Linux的选项,请换一个浏览器试试。我用的谷歌版本不可以,换一个别的浏览器就行了,如果还是不行,需要换一个翻墙的浏览器。 二,下载完后解压缩并放到安装文件夹下: 1、MySQL-client-5.6.2_linux mysql 安装 mysql-5.6.24-1.linux_glibc2.5.x86_64.rpm-bundle