第1章大型互联网公司的基础架构——1.5 服务发现
讲到这里,我们已经对一个客户端请求进入业务HTTP服务的过程有了较为详细的了解。业务HTTP服务在处理请求的过程中免不了与其他下游服务通信——可能会调用其他业务服务,可能需要访问数据库,可能会向消息中间件投递消息等,所以业务HTTP服务必须知道下游服务部署的可用地址。这就是本节要介绍的服务发现问题。
这里不是特指HTTP服务,在当前流行的微服务架构下,任何服务都涉及与其他服务通信的问题。要求每个服务的研发人员主动维护下游服务地址是不现实的,我们需要为每个服务提供可以自动发现下游服务地址列表的能力,这就是服务发现。服务发现组件是微服务架构下最重要的基础组件之一。
1.5.1 注册与发现
服务发现的技术原理并不复杂,一般通过提供一个服务注册中心来实现。这个服务注册中心主要负责两件事情:
- 管理每个服务的地址列表(注册)
- 将某服务的地址告知调用者(发现)。
让我们通过一个例子来阐明服务注册中心的工作流程。调用者A需要调用服务B来完成某请求,服务发现过程如图1-18所示。
服务发现过程描述如下:
- 服务B的各个服务实例启动后,将自己的地址信息注册到服务注册中心,由服务注册中心将其存储起来。
- 调用者A向服务注册中心查询服务B的地址。
- 服务注册中心将其存储的服务B已注册的实例地址列表返回给调用者A。
- 调用者A得到地址列表,可向服务B的任意一个实例地址发起远程调用。
调用者A除了可以主动查询服务地址,还可以采取订阅推送的方式与服务注册中心通信:
- 调用者A在进程启动时就与服务注册中心通信,订阅关于服务B的地址数据;
- 如果服务注册中心有服务B的地址数据,或者服务B的地址发生了变更,那么它会主动将最新地址列表推送给调用者A,如图1-19所示。
目前业界有很多可选择的服务注册中心组件,比如Spring Cloud的Eureka、CNCF旗下的CoreDNS等。
1.5.2 可用地址管理
服务注册中心可以使用MySQL等数据库来保存已注册的服务地址列表,存储选型相对自由。这不是这一节的重点,本节要讨论的重点是每个地址是否可用。调用者的调用目的地既然由服务注册中心决定,那么服务注册中心提供的地址应该是访问可达的,否则调用者将无法成功完成服务调用。那么,服务注册中心如何保证已注册的服务地址列表总是可用的呢?
由于服务的创建、销毁、升级、扩容/缩容都会造成服务地址列表的变更,所以服务的每个实例在启动时都需要向服务注册中心注册自己的地址,并在退出时注销地址。只有这样,才能使得服务注册中心一直在维护最新的服务地址列表。
不过,这还不够,我们还没有考虑异常情况。比如某服务实例突然挂掉,它还没来得及向服务注册中心注销地址,这就使得服务注册中心向调用者下发了不可用的服务地址,调用者调用请求被拒绝。所以,服务注册中心应该有对已注册的服务地址的探活能力。
地址探活一般有两种思路:
- 第一种思路是主动探活。服务注册中心周期性地向每个已注册的服务地址发起探测请求,如果某地址探测成功,则认为这个地址是可用的;否则,认为这个地址已经失效,服务注册中心主动摘除这个地址。这种思路只适用于服务较少、实例较少的小型互联网产品后台,对于用户量级较大的产品(动辄有上千个服务,个别访问量大的核心服务可能会部署上万个实例,所有服务的 实例总数有几百万个)来说,服务注册中心主动探活实例地址的效率非常低。
- 第二种思路是心跳探活。服务注册中心为每个已注册的服务地址记录一个最近心跳时间,服务实例启动后,每隔一段时间(如30s)就向服务注册中心发送一个心跳包,服务注册中心收到心跳包后更新对应服务地址的最近心跳时间。服务注册中心会启动定时器来检查每个服务地址的最近心跳时间相比于当前时间已经过了多久,如果其超过了某个阈值 (如150s),那么就可以认为这个服务实例已经不可用了,服务注册中心将其地址摘除,如图1-20所示。
服务注册中心基于服务实例心跳探活来摘除不可用的地址,可以在很大程度上保证地址列表可用。不过,在某些场景下摘除地址也存在潜在风险,这里举两个例子。
- 一个例子是服务注册中心的地址摘除逻辑有Bug,导致某服务的地址被意外全部摘除。从整个产品后台来看,这个服务等于凭空消失了,最终与其关联的全部业务场景均产生故障。
- 另一个例子是假设点赞服务有5个实例,每个实例可承受的最大QPS为1000,当前后台点赞服务的总QPS为3000,即每个实例承受的QPS为600。在某一时刻,S1、S2、S3这三个实例与服务注册中心发送心跳包的网络链路发生了长时间中断,服务注册中心认为这三个实例发生故障,于是将其对应的地址摘除。点赞服务的调用者收到的最新地址列表是[S4, S5],于是所有调用请求都转向这两个实例,导致每个实例实际承受了1500的QPS,最终这两个实例被压垮,整个点赞服务不可用了,如图1-21所示。
这两个例子都是因为服务注册中心过度摘除地址而带来了风险,所以这里建议为服务注册中心摘除地址增加简单的保护策略:在某服务的地址列表中,如果已摘除的地址数超过某个阈值(如30%),那么服务注册中心就停止摘除地址,并向服务负责人报警以寻求人工处理,防止出现不可控的故障。
1.5.3 地址变更推送
当服务的地址列表发生变更时,为了让调用者尽快感知到这件事情,服务注册中心需要主动推送最新地址列表给调用者。推送数据可能遇到的一个问题是“推送风暴”——如果某服务有100个调用者,每个调用者又有1000个实例,那么每当这个服务的地址列表发生变更时,就要给100000个节点推送数据;如果有多个服务的地址列表发生变更,则推送的节点会更多,这会严重占用网络带宽。那么,如何解决这个问题呢?
- 首先,建议推送的数据是“新增了哪些地址” “哪些地址已废弃”的增量数据形式,而不是全量地址列表,这能在一定程度上节约推送数据的网络带宽。
- 其次,服务注册中心本身也是一个服务,如果公司的服务注册中心有条件部署大量的实例,那么推送风暴问题也就被轻易解决了,毕竟分摊到每个服务注册中心实例的推送的节点不会很多。
- 最后,可以采用推拉结合的方式:服务注册中心最多给N个调用者节点推送地址变更信息,其他节点周期性地(如1min)从服务注册中心拉取最新地址列表。
由于服务发现组件的存在,调用者只需要关心要调用谁,而不需要关心被调用者的地址——调用者可以随时升级、扩容,不用担心调用者找不到。作为微服务架构下最核心的组件之一,服务发现真正为微服务带来了弹性。
总结
服务注册中心的主要职责?
- 管理每个服务的地址列表(注册)
- 将某服务的地址告知调用者(发现)
调用者如何从服务注册中心获取服务实例地址?
- 主动查询服务实例地址
- 采用订阅-推送方式
服务注册中心如何保证已注册的服务地址列表总是可用的呢?
- 服务的每个实例在启动时都需要向服务注册中心注册自己的地址,并在退出时注销地址。(正常情况)
- 服务注册中心应该有对已注册的服务地址的探活能力。(异常情况)
地址探活的方法?
- 主动探活。服务注册中心周期性地向每个已注册的服务地址发起探测请求,如果某地址探测成功,则认为这个地址是可用的;否则,认为这个地址已经失效,服务注册中心主动摘除这个地址。
- 心跳探活。服务注册中心为每个已注册的服务地址记录一个最近心跳时间,服务实例启动后,每隔一段时间(如30s)就向服务注册中心发送一个心跳包,服务注册中心收到心跳包后更新对应服务地址的最近心跳时间。服务注册中心会启动定时器来检查每个服务地址的最近心跳时间相比于当前时间已经过了多久,如果其超过了某个阈值 (如150s),那么就可以认为这个服务实例已经不可用了,服务注册中心将其地址摘除。
当服务的地址列表发生变更时,服务注册中心需要主动推送最新地址列表给调用者。推送数据可能遇到什么问题?
- 推送风暴
如何解决推送风暴问题?
- 首先,建议推送的数据是“新增了哪些地址” “哪些地址已废弃”的增量数据形式,而不是全量地址列表,这能在一定程度上节约推送数据的网络带宽。
- 其次,服务注册中心本身也是一个服务,如果公司的服务注册中心有条件部署大量的实例,那么推送风暴问题也就被轻易解决了,毕竟分摊到每个服务注册中心实例的推送的节点不会很多。
- 最后,可以采用推拉结合的方式:服务注册中心最多给N个调用者节点推送地址变更信息,其他节点周期性地(如1min)从服务注册中心拉取最新地址列表。
相关文章:
第1章大型互联网公司的基础架构——1.5 服务发现
讲到这里,我们已经对一个客户端请求进入业务HTTP服务的过程有了较为详细的了解。业务HTTP服务在处理请求的过程中免不了与其他下游服务通信——可能会调用其他业务服务,可能需要访问数据库,可能会向消息中间件投递消息等,所以业务…...
uniapp PDF 预览和下载
创建 index.vue <template><view><view class"box"><view class"item" ><view class"title"><span></span><text>文件</text></view><view class"list" v-for"(…...
ubuntu服务器部署
关闭欢迎消息 服务器安装好 ubuntu 系统后,进行终端登录,会显示出很多的欢迎消息 通过在用户的根目录下执行 touch .hushlogin 命令,再次登录终端就不会出现欢迎消息 修改hostname显示 修改 /etc/hostname 文件内容为主机名,保…...
Deepseek 本地部署
准备环境 设备:家用笔记本电脑,8核/16G/1Tb SSD/无独显 系统:windows10 软件环境(非源码部署不需要):conda 4.8.5、python3.7、git2.13 步骤 下载安装Ollama 下载地址:OllamaGet up and r…...
[Linux][问题处理]修改密码报You must wait longer to change your password
一、问题描述 在Linux控制台中修改密码,键入旧密码,设置并确认新密码后,却提示You must wait longer to change your password(您必须等待更长时间才能更改密码) 二、原因 当前修改时间 < Minimum number of da…...
《刚刚问世》系列初窥篇-Java+Playwright自动化测试-22- 操作鼠标拖拽 - 下篇(详细教程)
1.简介 上一篇中,宏哥说的宏哥在最后提到网站的反爬虫机制,那么宏哥在自己本地做一个网页,没有那个反爬虫的机制,谷歌浏览器是不是就可以验证成功了,宏哥就想验证一下自己想法,其次有人私信宏哥说是有那种…...
SpringBoot3使用Swagger3
版本 springboot3.4.2 JAVA 17 一、引入Swagger3依赖 <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.0.4</version> </dependency> 二、快速启…...
HCIA综合项目之多技术的综合应用实验
十五 HCIA综合实验 15.1 IP规划 #内网分配网段192.168.1.0 24#内网包括骨干链路和两个用户网段,素以需要划分三个,借两位就够用了192.168.1.0 26--骨干192.168.1.64 26---R1下网络192.168.1.128 26---R2下网络192.168.1.192 26--备用192.168.1.64 26--…...
燕千云ITSM已支持DeepSeek对接!AI能力持续升级
春节期间,DeepSeek火爆全网,引发热议,作为国产AI大模型的黑马,DeepSeek凭借独特的训练方法、先进的模型架构和强大的联网推理能力,正不断拓展AI技术的应用边界。其“快思考”能力,可在极短时间内完成复杂决…...
Windows 自动主题:Windows AutoTheme
Windows 自动主题:Windows AutoTheme 链接:https://pan.xunlei.com/s/VOJ2ZG5t8QjL7_fGVIBgyxJQA1?pwdgbie# 自动切换:根据日出、日落时间自动切换 Windows 主题模式。高效轻量:使用 Rust 提供高效的系统调用,保证运…...
自定义Spring Cloud Gateway过滤器:记录慢请求
在构建微服务架构时,API网关是一个关键组件,它负责路由、负载均衡、安全验证等多种功能。Spring Cloud Gateway提供了强大的扩展能力,允许开发者通过自定义过滤器来增强其功能。本文将详细介绍如何实现一个自定义过滤器,用于记录响…...
python 浅拷贝和深拷贝
浅拷贝(Shallow Copy)语法示例代码 1示例代码 2 深拷贝(Deep Copy)语法示例代码 浅拷贝与深拷贝的区别示例:浅拷贝与深拷贝的对比 浅拷贝:只复制外层容器,内层嵌套对象仍然是共享的,…...
uni-app 学习(一)
一、环境搭建和运行 (一)创建项目 直接进行创建 (二)项目结构理解 pages 是页面 静态资源 打包文件,看我们想输出成什么格式 app.vue 页面的入口文件 main.js 是项目的入口文件 存放对打包文件的配置 pages 存放整…...
unity学习37:新版的动画器:动画状态机 Animator
目录 1 给游戏物体添加,新版的动画器 Animator 2 关于 Animator 3 创建 动画器的控制器 Animator Controller 4 打开动画编辑器 Animator 5 动画编辑器 还是Animation 5.1 创建新的动画 5.2 创建第2个动画 5.3 测试2个动画均可用 6 再次打开动画编辑器 A…...
FFmpeg+SDL实现简易视频播放器
参考链接 https://blog.csdn.net/qq_26611129/article/details/98732561 https://www.cnblogs.com/Azion/p/17756274.html https://avmedia.0voice.com/?id49050 https://blog.csdn.net/qq_44825209/article/details/133760652 https://www.cnblogs.com/Azion/p/17525955.htm…...
Vue3实现优雅的前端版本更新提示
背景 在前端项目开发中,当我们发布了新版本后,需要及时通知用户刷新页面以获取最新代码。本文将介绍一种优雅的实现方案。 实现原理 在项目根目录维护一个version.json文件,记录当前版本号前端定期请求version.json检查版本对比本地存储的版本号,如有更新则提示用户 核心代…...
vim常用快捷键
正常模式 在打开文件进入 Vim 后,默认处于正常模式,该模式下的快捷键主要用于光标移动、文本操作等。 光标移动 基本移动:h(左移)、j(下移)、k(上移)、l(右移…...
P1226 【模板】快速幂
P1226 【模板】快速幂 题目描述 给你三个整数 a , b , p a,b,p a,b,p,求 a b m o d p a^b \bmod p abmodp。 输入格式 输入只有一行三个整数,分别代表 a , b , p a,b,p a,b,p。 输出格式 输出一行一个字符串 a^b mod ps,其中 a , b…...
【gRPC-gateway】是否有拦截器的情况添加健康检查的细节,与多路复用runtime.NewServeMux和gRPC区别讲解,与跨域功能,go案例
健康检查详解 什么是健康检查? 健康检查(Health Checking)是一种机制,用于监控服务的状态,确保服务在运行时是健康的、可用的。通过健康检查,系统可以自动检测服务是否正常工作,并在出现问题时…...
vue开发时,用localStorage常用方法及存储数组方法。
localStorage 可以让你在浏览器中存储键值对,并且在页面关闭后数据依然保留。localStorage 中存储的数据会一直保存在客户端,直到被手动删除或者清除浏览器缓存。 localStorage 中存储的数据在同一浏览器的不同窗口之间是共享的,而 sessionSt…...
HashMap详解+简单手写实现(哈希表)
1. 什么是 HashMap? HashMap是Java集合框架中的一种数据结构,它实现了Map接口,用于存储键值对(Key-Value Pair)。HashMap允许null键和null值,并且不保证元素的顺序。 --- 2. HashMap 的工作原理 2.1 内…...
解决Did not find dashscope_api_key问题——jupyter设置环境变量
jupyter中使用通义千文langchain 报错 Value error, Did not find dashscope_api_key, please add an environment variable DASHSCOPE_API_KEY which contains it, or pass dashscope_api_key as a named parameter.我本来以为这样就是已经加上了: #导入相关包 i…...
尚硅谷爬虫note003
一、函数 1. 函数的定义 def 函数名(): 代码 2.函数的调用 函数名() 3. 定义参数(不调用函数不执行) def sum(a,b) #形参 c a b print(c&…...
算法兵法全略(译文)
目录 始计篇 谋攻篇 军形篇 兵势篇 虚实篇 军争篇 九变篇 行军篇 地形篇 九地篇 火攻篇 用间篇 始计篇 算法,在当今时代,犹如国家关键的战略武器,也是处理各类事务的核心枢纽。算法的世界神秘且变化万千,不够贤能聪慧…...
NO.17十六届蓝桥杯备战|do-while循环|break和continue语句|三道练习(C++)
do-while循环 do-while语法形式 在循环语句中 do while 语句的使⽤最少,它的语法如下: //形式1 do 语句; while( 表达式 );//形式2 do { 语句1; 语句2; ... } while( 表达式 );while 和 for 这两种循环都是先判断,条件如果…...
【广州大学主办,发表有保障 | IEEE出版,稳定EI检索,往届见刊后快至1个月检索】第二届电气技术与自动化工程国际学术会议 (ETAE 2025)
第二届电气技术与自动化工程国际学术会议 (ETAE 2025) The 2nd International Conference on Electrical Technology and Automation Engineering 大会官网:http://www.icetae.com/【更多详情】 会议时间:2025年4月25-27日 会议地点:…...
Spring Cache 详细讲解
Spring Cache 是 Spring 框架提供的缓存抽象层,通过统一的 API 和注解简化缓存操作,支持多种缓存实现(如 Redis、EhCache、Caffeine 等)。其核心目标是减少重复计算,提升系统性能,同时保持代码简洁性。 1. …...
CPT205 计算机图形学 OpenGL 3D实践(CW2)
文章目录 1. 介绍2. 设计3. 准备阶段4. 角色构建5. 场景构建6. 交互部分6.1 键盘交互6.2 鼠标交互6.3 鼠标点击出多级菜单进行交互 7. 缺点与问题7.1 程序bug7.2 游戏乐趣不足7.3 画面不够好看 8. 完整代码 1. 介绍 前面已经分享过了关于CPT205的CW1的2D作业,这次C…...
Netty的基本架构详解
EventLoopGroup基本认识 我们需要了解的 EventLoopGroup, Netty对EventLoopGroup做了很多的扩展实现,下图是他的家族图谱: 我们上一节课使用的案例,使用的是NioEventLoopGroup,他是NIO的实现,可以看出来他是Multithre…...
2025前端面试题超全面解析(附答案与深度扩展)
文章目录 一、HTML篇(扩展版)1. **HTML5语义化标签的实际应用场景**2. **Web Components实战:如何封装一个自定义按钮组件?**3. **Web Worker的用途与限制** 二、CSS篇(扩展版)1. **CSS盒模型详解ÿ…...
自己搭建可以和deepseek对话的WEB应用
第一步 下载安装anaconda,地址:https://repo.anaconda.com/ 第二步 打开anaconda客户端,打开conda命令行窗口 第三步 创建一个open-webui专属的python专属的虚拟环境,并且指定python具体的版本 conda create --name open…...
Linux系统运行模式和链接
一、系统运行模式 centos6 0 关机模式 1 单用户模式 2 字符模式,无网络连接 3 字符模式 4 预留 5 图形模式 6 重启模式 查看系统当前处于的运行模式 切换为图形模式 init 5 centos7 字符模式 multi-user…...
.NET 9.0 的 Blazor Web App 项目,进度条 <progress> 组件使用注意事项
一、执行过程中,要刷新 进度条 的显示,需要 延时、释放,否则进度条不 实时 更新,最后一下到 100% // 延时,释放给前端:【必须】,否则进度条不 实时 更新,最后一下到 100await Task.D…...
头歌实验--面向对象程序设计
目录 实验五 类的继承与派生 第1关:简易商品系统 任务描述 答案代码 第2关:公司支出计算 任务描述 答案代码 第3关:棱柱体问题 任务描述 答案代码 实验五 类的继承与派生 第1关:简易商品系统 任务描述 答案代码 #incl…...
IoTDB 断电后无法启动 DataNode,日志提示 Meet error while starting up
问题 IoTDB 1.3.2 版本,断电后 IoTDB 的 DataNode 无法启动,日志如下: 2024-12-16 14:45:41,350 [main] ERROR o.a.i.db.service.DataNode:562 - Meet error while starting up. org.apache.iotdb.commons.exception.StartupException: Fo…...
2024华为OD机试真题-最大报酬(C++)-E卷B卷-100分
2024华为OD机试最新题库-(C卷+D卷+E卷)-(JAVA、Python、C++) 目录 题目描述 输入描述 输出描述 示例一 解题思路 考点 代码 c++ 题目描述 小明每周上班都会拿到自己的工作清单,工作清单内包含n项工作, 每项工作都有对应的耗时时间(单位h)和报酬, 工作的总报酬为…...
jenkins war Windows安装
Windows安装Jenkins 需求1.下载jenkins.war2.编写快速运行脚本3.启动Jenkins4.Jenkins使用 需求 1.支持在Windows下便捷运行Jenkins; 2.支持自定义启动参数; 3.有快速运行的脚步样板。 1.下载jenkins.war Jenkins下载地址:https://get.j…...
HCIA项目实践--RIP相关原理知识面试问题总结回答
9.4 RIP 9.4.1 补充概念 什么是邻居? 邻居指的是在网络拓扑结构中与某一节点(如路由器)直接相连的其他节点。它们之间可以直接进行通信和数据交互,能互相交换路由信息等,以实现网络中的数据转发和路径选择等功能。&am…...
用大模型学大模型04-模型与网络
目前已经学完深度学习的数学基础,开始学习各种 模型和网络阶段,给出一个从简单到入门的,层层递进的学习路线。并给出学习每种模型需要的前置知识。增加注意力机制,bert, 大模型,gpt, transformer, MOE等流行…...
浏览器扩展实现网址自动替换
作为一个开发爱好者,不能顺畅访问github是很痛苦的,这种状况不知道何时能彻底解决。 目前也有很多方案可以对应这种囧况,我此前知道有一个网站kkgithub,基本上把github的静态内容都搬了过来,我们如果需要访问某个githu…...
适配器模式详解(Java)
一、引言 1.1 定义与类型 适配器模式是一种结构型设计模式,主要目的是将一个类的接口转换为客户期望的另一个接口。这种模式使得原本因为接口不匹配而不能一起工作的类可以一起工作,从而提高了类的复用性。适配器模式分为类适配器和对象适配器两种类型。类适配器使用继承关…...
C语言表驱动法
最近了解到一种C语言的写法,故记录下来,内容来自deepseek。 表驱动法 表驱动法(Table-Driven Approach)是一种编程技术,通过使用表格(数组、结构体数组、哈希表等)来存储数据或逻辑࿰…...
【鸿蒙Next】优秀鸿蒙博客集锦
鸿蒙基础开发:多文件压缩上传及断点续传_鸿蒙 断点续传-CSDN博客...
Django REST Framework:如何获取序列化后的ID
Django REST Framework:如何获取序列化后的ID 😄 嗨,小伙伴们!今天我们来聊一聊Django REST Framework(简称DRF)中一个非常常见的操作:如何获取序列化后的ID。对于那些刚入门的朋友们ÿ…...
deep seek
1.介绍:DeepSeek是一款由国内人工智能公司研发的大型语言模型,拥有强大的自然语言处理能力,能够理解并回答问题,还能辅助写代码、整理资料和解决复杂的数学问题。免费开源,媲美ChatGPT 最近最火爆的AI对话程序。 www.deepseek.com…...
前端设计模式介绍及案例(单例模式、代理模式、工厂模式、装饰者模式、观察者模式)
概要 本文主要介绍了前端设计模式的定义、分类以及常用设计模式的具体案例。 前言 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦…...
开源堡垒机 JumpServer 社区版实战教程:基于 Ubuntu 22.04 离线安装 JumpServer 社区版 v4.4.1
文章目录 开源堡垒机 JumpServer 社区版实战教程:基于 Ubuntu 22.04 离线安装 JumpServer 社区版 v4.4.1一、环境要求1.1 操作系统1.1.1 Ubuntu1.1.2 CentOS 1.2 数据库1.2.1 JumpServer 需要使用的数据库1.2.2 创建数据库 SQL 参考1.2.2.1 PostgreSQL1.2.2.2 MySQL…...
电源测试和测量系统的创新遥感方法可以消除哪些潜在问题
传统的遥感方法 远程感测是一种行之有效的方法,通过消除连接电缆中压降的影响来调节负载点的直流功率。这在测试和测量应用中尤其重要,在这些应用中,电源电压在一系列负载条件下的准确性和一致性通常对于获得准确且可重复的测试结果至关重要…...
10、《Thymeleaf模板引擎:动态页面开发全攻略》
Thymeleaf模板引擎:动态页面开发全攻略 一、Thymeleaf核心价值解析 天然HTML亲和力:Thymeleaf允许直接使用.html文件作为模板,支持浏览器直接预览静态原型,同时通过属性标签(如th:text)实现动态渲染&…...
Day1 25/2/14 FRI
【一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解(马士兵)】https://www.bilibili.com/video/BV13g41157hK?p3&v…...