当前位置: 首页 > news >正文

架构核心技术之微服务架构

小熊学Java:https://www.javaxiaobear.cn/,文末有免费资源

本文我们来学习微服务的架构设计

主要包括如下内容。

  • 单体系统的困难:编译部署困难、数据库连接耗尽、服务复用困难、新增业务困难。

  • 微服务框架:Dubbo 和 Spring Cloud,微服务的架构策略。

  • 微服务模式:事件溯源、查询与命令职责分离 CQRS、断路器、超时。

  • 微服务最佳实践。

单体系统的困难

在微服务出现之前,互联网应用系统主要是单体系统,也就是说一个网站的整个系统由一个应用构成。如果是 Java,就打包成一个 war 包,一个 war 包包含整个应用系统,系统更新的时候,即使只是更新其中极小的一部分,也要重新打包整个 war 包,发布整个系统。

这样的单体系统面临的挑战主要是什么呢?

编译、部署困难

随着网站的业务不断发展,系统会变得越来越庞大,最后变成一个巨无霸的系统。

   在我曾经工作过的公司,单个应用可能有几个 G 大,这对于网站开发工程师来说,开发编译和部署都是非常困难的。在开发的过程中,即使只改了庞大系统中的一行代码,也必须把完整的网站系统重新打包,才能做测试。这会经历漫长的编译过程:出去抽一支烟回来一看,在编译;又去喝了一杯水回来,还在编译;再去趟厕所,回来还在编译。好不容易编译结束了,如果某个配置项错误导致编译失败,又得重来一次,浪费大半天的时间。这样的单体系统对于开发部署和测试都是非常困难的。

代码分支管理困难

因为单体应用非常庞大,所以代码模块也是由多个团队共同维护的。但最后还是要编译成一个单体应用,统一发布。这就要求把各个团队的代码 merge 在一起,这个过程很容易发生代码冲突。而 merge 的时候又是网站要进行发布的时候,发布过程本来就复杂,再加上代码 merge 带来的问题,各种情况纠缠在一起,极易出错。所以,在单体应用时代每一次网站发布都需要搞到深更半夜。

数据库连接耗尽

对于一个巨型的应用而言。因为有大量的用户进行访问,所以必须把应用部署到大规模的服务器集群上。然后每个应用都需要与数据库建立连接,大量的应用服务器连接到数据库,会对数据库的连接产生巨大的压力,某些情况下甚至会耗尽数据库的连接。

新增业务困难

巨无霸单体应用的另一个挑战是新增业务困难。因为所有的业务都耦合在一个单一的大系统里,通常随着时间的发展,这个系统会变得非常的复杂,里面的各种结构也非常乱,想要维护这样一个系统是非常困难和复杂的。很多工程师入职公司半年,都还不能熟悉业务,因为业务太过庞大和复杂,经常会出各种错误。所以就会出现这种现象:熟悉系统的老员们工忙得要死,加班加点干活,不熟悉系统的新员工们一帮忙就出乱,跟着加班加点干活。整个公司热火朝天地干活,但最后还是常常出故障,新的功能迟迟不能上线。

发布困难

因为一个 war 包包含了所有的代码,进行新版本发布的时候,发布代码跟自己的开发的代码一点关系没有,但是因为 war 包包含了自己的代码,为了以防万一,也不得不跟着发布值班。结果真正更新代码功能的只有几个人,而整个部门都要跟着加班。常常出现,到了深夜,有代码更新的同事汗流浃背进行代码冲突处理和修复发布 bug,没有代码更新的同事陪着聊天、打瞌睡、打游戏,这种情况。

微服务架构

解决上述问题的主要手段是将一个单体的巨无霸系统,根据模块以及复用的粒度进行拆分,拆分成多个可以独立部署的分布式服务。应用通过远程访问调用的方式,使用这些服务,构成一个系统。但是由于它的核心服务是在其他的服务器上分布部署的,本身的业务逻辑可以变得比较简单,这样就把一个巨无霸系统单体应用拆成了若干个可复用的服务,利用较少的逻辑代码就可以组成一个应用系统。

SOA 架构

这样的设计思路其实并不是在互联网时代才出现的。在早期的时候,就有人提出了 SOA 面向服务的体系架构。如下图所示,在面向服务的体系架构里面,服务的提供者向注册中心注册自己的服务,而服务的使用者向注册中心去发现服务。发现服务以后,根据服务注册中心提供的访问接口和访问路径对服务发起请求,由服务的提供者完成请求返回结果给调用者。现在的微服务或者分布式服务,其实也是 SOA 架构的一种实现。但是在早期的 SOA 架构实践中,服务的注册与服务的调用都非常复杂,服务调用效率也比较低。

微服务架构

后来在互联网时代的微服务中,人们简化了 SOA 架构中的调用规范和服务规范,形成了我们现在所熟悉的分布式微服务架构。

如下图,所谓的微服务架构就是将一个单体的巨无霸系统拆分成一组可复用的服务,基于这些服务构成的应用系统。图中左边是早期的单体应用系统架构,里面的各个模块互相调用、耦合,所有的系统和模块打包在一起,最后组成一个庞大的巨无霸系统。右边是微服务架构,根据服务的粒度和可复用的级别,对服务进行拆分,以独立部署服务的方式,对外提供服务调用。而应用系统也按照用途和场景的不同,依赖这些可复用的服务,进行逻辑组合,构建成自己的业务系统。

通过这样一种方式,系统变得比较简单,复用级别也比较高,同时也解决了前面提出的单体巨无霸的几个重要问题。因为每一个服务或是应用系统,代码都比较简单,所以编译和部署、开发和测试,都比较简单和快速。而且这些服务都是独立维护和部署的,它的代码分支也是独立的,不会和其他的代码分支一起进行管理,减少了代码冲突的可能性。发布的时候,也是每个服务独立发布,只要做好服务的版本控制和接口兼容,应用系统不需要跟随服务一起更新发布。

在微服务体系中,连接数据库的是具体的服务,应用系统不需要自己去连接数据库,只需要调用组合服务,对服务进行编排。所以对数据库的连接也相对比以前更少一些。最主要的是当需要开发新业务的时候,使用这种方式不需要对原有的单体系统进行各种重构和代码修改,只需要开发一个新的业务系统,组合调用现有的微服务,就可以组合出来一个新的产品功能,可以快速开发新产品。

Dubbo

目前一些典型的微服务框架本身的架构是如何设计的?

先看 Dubbo 架构。Dubbo 是阿里开源的,比较早也比较有影响力的一个分布式微服务框架。如下图所示,在 Dubbo 架构中,最核心的模块有 3 个部分,一个是服务的提供者,一个是服务的消费者,还有一个是服务的注册中心。

服务的提供者顾名思义就是微服务的具体提供者,通过微服务容器对外提供服务。而服务的消费者就是应用系统或是其他的微服务。

应用系统通过组合多个微服务,构成自己的业务逻辑,实现自己的产品功能。具体过程是服务的提供者程序在 Dubbo 的服务容器中启动,服务管理容器向服务注册中心进行注册,声明服务提供者所要提供的接口参数和规范,并且注册自己所在服务器的 IP 地址和端口,如下图所示。

而服务的消费者如果想要调用某个服务,只需依赖服务提供者的接口进行编程。而服务接口通过 Dubbo 框架的代理访问机制,调用 Dubbo 的服务框架客户端,服务框架客户端会根据服务接口声明,去注册中心查找对应的服务提供者启动在哪些服务器上,并且将这个服务器列表返回给客户端。客户端根据某种负载均衡策略,选择某一个服务器通过远程通讯模块发送具体的服务调用请求。

服务调用请求,通过 Dubbo 底层自己的远程通讯模块,也就是 RPC 调用方式,将请求发送到服务的提供者服务器,服务提供者服务器收到请求以后,将该请求发送给服务提供者程序,完成服务的执行,并将服务执行处理结果通过远程调用通讯模块 RPC 返回给服务消费者客户端,服务消费者客户端将结果返回给服务调用程序,从而完成远程服务的调用,获得服务处理的结果。

Dubbo 使用 Java 进行开发,并且通过服务接口的方式对消费者提供服务,所以它的服务调用方式比较简单,可以透明地进行远程微服务调用。服务消费者程序,可以无感知地进行远程微服务调用,对开发者相对比较友好。

Spring Cloud

另一种目前比较热门的微服务框架是 Spring Cloud。Spring Cloud 微服务框架组件跟 Dubbo 类似,也是由服务的消费者、服务的提供者和注册中心组成。如下图所示,Spring cloud 的服务提供者通过 Spring Boot 启动,然后向服务注册中心 Eureka Server 进行注册,而服务的消费者通过一个 Zuul 网关访问 Eureka Server 进行服务的发现,获得自己想要调用的远程服务对应的服务地址。获得地址以后,通过 HTTP 的方式向远程的服务提供者发起调用请求。服务提供者完成服务处理后,将处理结果通过 HTTP 返回。从而实现了远程的微服务调用。

Spring Cloud 还包含了一组服务调用监控组件,主要是 Hystrix,通过 Hystrix 可以监控服务调用,还在此基础上实现了熔断、降级、超时管理等一系列高可用策略。

微服务架构策略

对微服务架构而言,技术现在其实比较成熟。使用什么样的技术去实现一个微服务,本身并没有太多的困难。构建一个微服务架构最困难的还是服务治理,也就是业务划分。策略要点如图所示。

一个微服务包含的功能有哪些?服务的边界是什么?服务之间的依赖关系如何?这些关键的问题决定了服务的复用程度,维护的难易程度,开发的便利程度。所以设计微服务架构的时候,首先要关注的是业务,业务要先行,理顺业务模块之间的边界和依赖,做好服务治理和调用依赖管理。

微服务技术是微服务架构的手段,而不是目的。微服务最主要的目的还是实现服务治理——如何划分和管理服务。首先要有独立的功能模块,然后才有分布式的服务。也就是说在软件设计的时候,软件功能模块之间的依赖关系就要清晰、合理、规范、便于维护、便于扩展,便于实现新的功能。服务之间的依赖关系要清晰、参数要简单、耦合关系要少。设计好这样的模块化结构以后,将这些设计好的模块,拆分成独立的微服务进行部署和调用,就可以构建一个良好的微服务系统。如果模块本身就是混乱的、耦合严重的、边界不清晰的、关系复杂的,那么,把它们拆分成独立的微服务进行部署,只会使事情变得更加复杂。

所以进行微服务架构设计之初,就要先做好业务模块的设计和规划。同时,对于那些业务耦合比较严重、逻辑复杂多变的系统,进行微服务重构的时候,也要特别谨慎。如果做不好模块的划分和耦合管理。那么,宁可晚一点进行微服务架构重构,也不要仓促上马,以免最后带来巨大的损失。要使用微服务架构的时候,一定要搞清楚实施微服务的目的究竟是什么,是为了业务复用,是为了开发边界清晰,是为了分布式集群提升性能,还是仅仅想要使用微服务?目的一定要清楚。

跟其他技术不同,微服务具有强业务属性,业务如果本身结构混乱,目标不清晰,仓促使用微服务,可能会使整个系统变得更加复杂和难以控制。所以在使用微服务前,最重要的是要先明确自己的需求:我们到底想用微服务达到什么样的目的?需求清晰了,再去考虑具体的方案和技术。这也是使用大多数技术的时候应有的方法和思路。

如下图所示,最重要的是需求。在日常工作中,我们要根据需求去考虑具体的价值,再根据价值构建我们的设计原则,根据原则寻找最佳实践,最后根据实践去选择最合适的工具。按这样的方式去选择技术做架构设计才是比较成熟和高效的。如果相反,先找到一个工具,然后用工具硬往上套需求,只会导致技术也没用好,业务也没做好,所有人都疲惫不堪,事情变得一团糟,最后还可能反过来怪技术没用。

微服务的使用模式

下面来看可供参考的几种微服务的使用模式。

事件溯源

第一是事件溯源,因为微服务的调用过程会比较复杂,调用链路可能会比较长。如果某个微服务调用出错,如何进行管理和监控?使用事件溯源这种模式是一种解决办法。

所谓的事件溯源是指将用户的请求处理过程,每一次的状态变化都记录到事件日志中,并按照时间序列进行持久化的存储,也就是说,把所有的变更操作都按日志的方式,按时间化序列进行记录。

使用事件溯源的好处有如下两点。

  • 可以精确地复现用户的状态变化。

用户执行了哪些操作,使它成为现在这样一种状况,然后通过事件溯源的方式,追溯以往的操作和动作,从而进行复核和审计。当用户投诉的时候,当状态不一致的时候,可以通过事件溯源中的日志进行审计和查找。

  • 可以有效监控用户的状态变化,并在此基础上实现分布式的事务。

我们传统的事务使用数据库事务进行实现,可以将多个数据库操作统一提交,或者统一回滚,保持数据的一致性,但是在分布式状况下,对数据的操作是分布在多个独立部署的服务进行处理。这个时候就无法使用数据库的事务进行管理。

那么,如何在这种情况下实行分布式系统的事务?

事件溯源是一种办法。因为事件溯源将所有的数据变更都按日志的方式记录起来,所以如果日志不完整,我们就知道事务不完整,可以对事务进行重组或者补偿操作,从而使数据变得一致。

命令与查询职责隔离(CQRS)

这种模式在服务接口层面将查询操作(也就是读操作)和命令操作(也就是写操作)隔离开来,在服务层实现读写分离。

使用 CQRS 模式,主要的好处是可以有更清晰的领域模型,根据操作的方式不同,使用不同的领域模型。还可以分别进行读写优化,从而实现更好的性能。

我们知道在读操作中主要使用的优化方式是缓存操作。那么,我们可以将接口层面的查询操作即读操作,尽量多地通过缓存来返回。而写操作也就是命令操作,主要的性能优化方式是使用消息队列。那么,我们可以将数据的更新操作,尽量通过消息队列,通过异步化的方式进行处理,以改善性能。

因为使用 CQRS 查询和命令分离的方式,我们可以在接口层面上使用不同的优化手段。查询操作不会修改数据库,那么所有来自于查询接口的服务,可以统一连接到只读数据库中,防止误操作破坏数据,可以更好地保护数据,同时使用 CQRS,还可以更好地实现刚才的事件溯源机制。因为查询操作是无须进行事件溯源的,所有的事件溯源都可以统一设置在命令服务接口上。

断路器

使用微服务的时候,你还需要关注一个事情:服务的不可用。

当某个服务实例出现故障的时候,它的响应延迟或者失败率增加的时候,继续调用这个服务实例会导致请求者阻塞。请求阻塞以后会导致资源消耗增加,最后可能会导致请求者也失败和崩溃,进而出现服务的级联崩溃,也就是服务请求者的请求者也失败,最后会导致整个系统全部失败,即雪崩现象。

在这种情况下,可以使用断路器对故障服务进行隔离。断路器有三种状态:关闭、打开、半开。当服务出现故障的时候,通过断路器阻断对故障服务实例的调用,避免它的故障扩散开来。在 Spring Cloud 中可以使用 Hystrix 实现断路器。

超时

还有一件需要关注的事情是:微服务调用的超时机制如何设置。

如果使用统一的超时设置,那么当下游调用者超时的时候,上游调用者一定也已经超时了,因为服务调用是阻塞的。所以,下游调用的超时一定会反应在上游调用者上。因此在设置超时的时候,要设置上游调用者的超时时间大于下游调用者的超时时间之和,相同的超时设置是没有意义的,如下图所示。

总结回顾

首先,之所以要使用微服务,是因为传统的单体巨无霸系统带来的挑战和困难,包括编译和部署的困难、连接的困难、打包代码冲突的困难,以及复用的困难、新增业务的困难。

而具体的微服务框架基本上都是由三个核心部分组成的:服务的提供者、服务的调用者和服务的注册中心。服务的提供者向注册中心注册自己的服务,而服务的调用者通过注册中心发现服务,并进行远程调用。

另外,很多微服务架构中还包括一个监控者的角色,通过监控者进行服务的管理和流量的控制。

使用微服务最重要的是做好业务的模块化设计,模块之间要低耦合,高聚合,模块之间的依赖关系要清晰简单。只有这样的模块化设计,才能够构建出良好的微服务架构。如果系统本身就是一团遭,强行将它们拆分在不同的微服务里,只会使系统变得更加混乱。

使用微服务的时候,有几个重要的使用模式,需要关注:一个是事件溯源,一个是命令与查询隔离,还有一个是断路器以及关于超时如何进行设置。

福利资源

海量数据高并发场景,构建Go+ES8企业级搜索微服务:https://www.aliyundrive.com/s/ib2BeM5W3Du

相关文章:

架构核心技术之微服务架构

小熊学Java:https://www.javaxiaobear.cn/,文末有免费资源 本文我们来学习微服务的架构设计 主要包括如下内容。 单体系统的困难:编译部署困难、数据库连接耗尽、服务复用困难、新增业务困难。 微服务框架:Dubbo 和 Spring Clou…...

SQL Server2022版+SSMS安装教程(保姆级)

SQL Server2022版SSMS安装教程(保姆级) 一,安装SQL Server数据库 1.下载安装包 (1)百度网盘下载安装包 链接:https://pan.baidu.com/s/1A-WRVES4EGv8EVArGNF2QQ?pwd6uvs 提取码:6uvs &…...

go语言基础---8

Http请求报文格式分析 package mainimport ("fmt""net" )func main() {//监听listener, err : net.Listen("tcp", ":8000")if err ! nil {fmt.Println("listener err", err)return}defer listener.Close()//阻塞等待用户的…...

Oracle的 dblink 学习笔记

文章目录 一、基础环境二、适用场景三、过程和方法四、参考资料 版权声明:本文为CSDN博主「杨群」的原创文章,遵循 CC 4.0 BY-SA版权协议,于2023年9月10日首发于CSDN,转载请附上原文出处链接及本声明。 原文链接:http…...

任意文件上传

1.任意文件上传概述 1.1 漏洞成因 服务器配置不当,开启了PUT 方法。 Web 应用开放了文件上传功能,没有对上传的文件做足够的限制和过滤。在程序开发部署时,没有考虑以下因素,导致限制被绕过: 代码特性 组件漏洞&am…...

【Unity3D】UI Toolkit自定义元素

1 前言 UI Toolkit 支持通过继承 VisualElement 实现自定义元素,便于通过脚本控制元素。另外,UI Toolkit 也支持将一个容器及其所有子元素作为一个模板,便于通过脚本复制模板。 如果读者对 UI Toolkit 不是太了解,可以参考以下内容…...

layui手机端使用laydate时间选择器被输入法遮挡的解决方案

在HTML中,你可以使用input元素的readonly属性来禁止用户输入,但是这将完全禁用输入,而不仅仅是禁止弹出输入法。如果你想允许用户在特定条件下输入,你可以使用JavaScript来动态地切换readonly属性。 readonly属性 增加readonly属…...

MVSNet CVPR-2018 学习总结笔记 译文 深度学习三维重建

文章目录 2 MVSNet CVPR-20182.0 主要特点2.1 过程2.2 MVSNet主要贡献2.3 论文简介2.3.1 深度特征提取2.3.2 构造匹配代价2.3.3 代价累计2.3.4 深度估计2.3.5 深度图优化2.4 MVSNet(pytorch版本)2 MVSNet CVPR-2018 MVSNet (pytorch版) 代码注释版 下载 (注释非常详细,代码…...

Kafka/Spark-01消费topic到写出到topic

1 Kafka的工具类 1.1 从kafka消费数据的方法 消费者代码 def getKafkaDStream(ssc : StreamingContext , topic: String , groupId:String ) {consumerConfigs.put(ConsumerConfig.GROUP_ID_CONFIG , groupId)val kafkaDStream: InputDStream[ConsumerRecord[String, Strin…...

【算法与数据结构】98、LeetCode验证二叉搜索树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;注意不要落入下面你的陷阱&#xff0c;笔者本来想左节点键值<中间节点键值<右节点键值即可&…...

关于GitHub Desktop中的“Open in Git Bash”无法使用的问题

问题描述 在GitHub Desktop中选择Repository--Open in Git Bash&#xff08;如图1&#xff09;&#xff0c;出现如图2所示结果。 图1 图2 解决办法&#xff08;Windows10&#xff09; 这个问题是由于Git的环境变量没有得到正确配置所导致的&#xff0c;所以需要正确设置环境变量…...

使用DeepSpeed加速大型模型训练(二)

使用DeepSpeed加速大型模型训练 在这篇文章中&#xff0c;我们将了解如何利用Accelerate库来训练大型模型&#xff0c;从而使用户能够利用DeeSpeed的 ZeRO 功能。 简介 尝试训练大型模型时是否厌倦了内存不足 (OOM) 错误&#xff1f;我们已经为您提供了保障。大型模型性能非…...

ASP.net web应用 GridView控件常用方法

GridView 控件是 ASP.NET Web Forms 中常用的数据展示控件之一。它提供了一个网格形式的表格&#xff0c;用于显示和编辑数据。GridView 控件对于包含大量数据、需要进行分页、排序和筛选的情况非常有用。 GridView 控件的主要特性包括&#xff1a; 数据绑定&#xff1a;GridV…...

MATLAB入门一基础知识

MATLAB入门一基础知识 此篇为课程学习笔记 链接: link 什么是MATLAB 平时所说的MATLAB既是一款软件又是一种编程语言&#xff0c;只是这种高级解释性语言是在配套的软件下进行开发的 MATLAB的一个特性 MATLAB的一个特性&#xff0c;如果一条语句以英文分号‘;’结尾&…...

SpringMVC实现文件上传和下载功能

文件下载 ResponseEntity用于控制器方法的返回值类型&#xff0c;该控制器方法的返回值就是响应到浏览器的响应报文。具体步骤如下&#xff1a; 获取下载文件的位置&#xff1b;创建流&#xff0c;读取文件&#xff1b;设置响应信息&#xff0c;包括响应头&#xff0c;响应体以…...

CHS零壹视频恢复程序OCR使用方法

目前CHS零壹视频恢复程序监控版、专业版、高级版已经支持了OCR&#xff0c;OCR是一种光学识别系统&#xff0c;通俗说就和扫描仪带的OCR软件一样的原理&#xff1a; 分析照片->OCR获取字符串->整理字符串->输出 使用方法如下&#xff08;以CHS零壹视频恢复程序监控版…...

云备份——服务端客户端联合测试

一&#xff0c;准备工作 服务端清空备份文件信息、备份文件夹、压缩文件夹 客户端清空备份文件夹 二&#xff0c;开始测试 服务端配置文件 先启动服务端和客户端 向客户端指定文件夹放入稍微大点的文件&#xff0c;方便后续测试断点重传 2.1 上传功能测试 客户端自动上传成功…...

L2 数据仓库和Hive环境配置

1.数据仓库架构 数据仓库DW主要是一个用于存储&#xff0c;分析&#xff0c;报告的数据系统。数据仓库的目的是面向分析的集成化数据环境&#xff0c;分析结果为企业提供决策支持。-DW不产生和消耗数据 结构数据&#xff1a;数据库中数据&#xff0c;CSV文件 直接导入DW非结构…...

【iOS】MVC

文章目录 前言一、MVC各层职责1.1、controller层1.2、model层1.3、view层 二、总结三、优缺点3.1、优点3.2、缺点 四、代码示例 前言 MVC模式的目的是实现一种动态的程序设计&#xff0c;使后续对程序的修改和扩展简化&#xff0c;并且使程序某一部分的重复利用成为可能。除此…...

JavaScript-----jQuery

目录 前言&#xff1a; 1. jQuery介绍 2. 工厂函数 - $() jQuery通过选择器获取元素&#xff0c;$("选择器") 过滤选择器&#xff0c;需要结合其他选择器使用。 3.操作元素内容 4. 操作标签属性 5. 操作标签样式 6. 元素的创建,添加,删除 7.数据与对象遍历…...

Stream流

Stream操作流 在Java 8中&#xff0c;得益于Lambda所带来的函数式编程&#xff0c;引入了一个全新的Stream概念&#xff0c;用于解决已有集合类库既有的弊端。 1.1 集合的迭代 几乎所有的集合&#xff08;如 Collection 接口或 Map 接口等&#xff09;都支持直接或间接的迭代…...

javaee spring 声明式事务管理方式2 注解方式

spring配置文件 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns:context"http://www.springframewo…...

基于SpringBoot+微信小程序的智慧医疗线上预约问诊小程序

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 近年来&#xff0c;随…...

注意力机制讲解与代码解析

一、SEBlock(通道注意力机制) 先在H*W维度进行压缩&#xff0c;全局平均池化将每个通道平均为一个值。 &#xff08;B, C, H, W&#xff09;---- (B, C, 1, 1) 利用各channel维度的相关性计算权重 (B, C, 1, 1) --- (B, C//K, 1, 1) --- (B, C, 1, 1) --- sigmoid 与原特征相…...

微调 TrOCR – 训练 TrOCR 识别弯曲文本

TrOCR(基于 Transformer 的光学字符识别)模型是性能最佳的 OCR 模型之一。在我们之前的文章中,我们分析了它们在单行打印和手写文本上的表现。然而,与任何其他深度学习模型一样,它们也有其局限性。TrOCR 在处理开箱即用的弯曲文本时表现不佳。本文将通过在弯曲文本数据集上…...

Jetsonnano B01 笔记7:Mediapipe与人脸手势识别

今日继续我的Jetsonnano学习之路&#xff0c;今日学习安装使用的是&#xff1a;MediaPipe 一款开源的多媒体机器学习模型应用框架。可在移动设备、工作站和服务 器上跨平台运行&#xff0c;并支持移动 GPU 加速。 介绍与程序搬运官方&#xff0c;只是自己的学习记录笔记&am…...

vue学习之v-if/v-else/v-else-if

v-else/v-else-if 创建 demo7.html,内容如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Docum…...

ansible的安装和简单的块使用

目录 一、概述 二、安装 1、选择源 2、安装ansible 3、模块查看 三、实验 1、拓扑​编辑 2、设置组、ping模块 3、hostname模块 4、file模块 ​编辑 5、stat模块 6、copy模块&#xff08;本地拷贝到远程&#xff09; 7、fetch模块与copy模块类似&#xff0c;但作用…...

Android 状态栏显示运营商名称

Android 原生设计中在锁屏界面会显示运营商名称&#xff0c;用户界面中&#xff0c;大概是基于 icon 数量长度显示考虑&#xff0c;对运营商名称不作显示。但是国内基本都加上运营商名称。对图标显示长度优化基本都是&#xff1a;缩小运营商字体、限制字数长度、信号图标压缩上…...

10.Xaml ListBox控件

1.运行界面 2.运行源码 a.Xaml 源码 <Grid Name="Grid1"><!--IsSelected="True" 表示选中--><ListBox x:Name="listBo...

企业网站制作心得/外链信息

分层好处&#xff1a; 1&#xff0c;复杂问题简单化&#xff1a;将复杂的任务分解成多层来完成&#xff0c;每一层只处理简单的任务&#xff0c;方便定位问题 2&#xff0c;减少重复开发&#xff1a;规范数据分层&#xff0c;通过中间层数据&#xff0c;能够减少极大的重复计算…...

北京最牛计算机培训机构/搜索引擎营销优化

若有收获&#xff0c;点个在看、转发朋友圈&#xff0c;让更多朋友一起学习&#xff01; 本文内容 为什么需要用代理 jdk动态代理玩法详解 cglib代理常见的各种玩法详解 代理spring中用到的挺多的&#xff0c;比如上篇文章中的lookup-method和replaced-method&#xff0c;以及…...

domain 网站建设/创建网址快捷方式

转载于:https://www.cnblogs.com/LiLihongqiang/p/5721842.html...

翔云白云手机网站建设/男生最喜欢的浏览器

非常感谢我们的撰稿人斯蒂芬&#xff0c;最近他分享了自己的两段描述性的评论&#xff0c;这些评论事关他的山进909X2收音机所暴露出的问题。我已将这两段评论编辑在一起并罗列如下&#xff1a;“我从山进欧洲公司购买了ATS-909X2收音机&#xff0c;我彻底失望了。我知道自己的…...

怎样建设VR网站/挖掘关键词工具

1 &#xff0c;安装 vmware &#xff1a; 基本就是下一步 2 &#xff0c;解开衣服 &#xff1a; 双击打开输入许可证继续 - 完成 3 &#xff0c;新建虚拟机 &#xff1a; 创建新的虚拟机 - 自定义 - 下一步 - 下一步稍后安装操作系统 - 下一步 - linux - centOS64 位 - 下…...

延安网站建设公司电话/现在推广引流什么平台比较火

android-ui该项目已经停止维护&#xff0c;请移步到这里帮助快速开发android&#xff0c;项目集成6.0权限申请&#xff0c;常用dialog&#xff0c;本地图片选择等...项目部分引用第三方开源库&#xff0c;感谢开源项目正在不断有空更新&#xff0c; 别急&#xff0c;先star吧..…...