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

旧服务改造及微服务架构演进

旧服务改造及微服务架构演进

    • 微服务架构演进
      • 1.微服务架构
      • 2.微服务架构的特点
      • 3.单体架构与微服务架构之间的对比
      • 4.微服务架构演进历程
    • 旧服务改造
      • 1. 微服务拆分的一些通用原则
      • 2.微服务拆分策略
        • (1)功能维度拆分策略
        • (2)非功能维度拆分策略
      • 3.旧服务改造演示
        • (1)Spring Cloud Alibaba技术栈选型
        • (2)接入Nacos注册中心
        • (3)接入nacos配置中心
        • (4)接入openfeign实现服务之间的通信
    • 总结

微服务架构演进

1.微服务架构

微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用 HTTP 资源 API)。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。 --摘录总结自文章微服务架构讲解有兴趣可以去查看原文。
在这里插入图片描述

2.微服务架构的特点

微服务架构是一种将单体应用程序拆分成多个小型、独立的服务的架构风格,每个服务都可以独立开发、部署和扩展。其具有以下特点:

  • 低耦合高内聚

​ 微服务之间通过轻量级的通信机制进行交互,如 RESTful API、消息队列等,它们之间的依赖关系非常松散。一个微服务的内部实现细节对其他微服务是透明的,当一个微服务发生变化时,只要其接口不变,就不会对其他微服务产生影响。而每个微服务都专注于完成一项特定的业务功能,将相关的业务逻辑和数据处理都封装在内部,具有高度的内聚性。

  • 易拓展和易维护

​ 由于每个微服务的功能相对单一、代码规模较小,结构也相对简单,开发人员能够更快速地理解和掌握其业务逻辑和代码逻辑,降低了维护的难度。当业务需求发生变化或需要添加新功能时,可以很容易地通过增加新的微服务或对现有微服务进行扩展来实现,能够快速响应业务的变化,满足不断增长的业务需求。

  • 跨语言开发

由于各个微服务之间通过轻量级的通信机制进行交互,那么就不要求各个微服务编写语言需要一致,只需要遵守对应的通信规则,在需要别的微服务信息能够正确获取即可。

  • 独立部署和弹性扩容

​ 每个微服务都可以独立进行部署,无需依赖其他服务的部署过程。这意味着当某个微服务需要更新或修改时,只需单独部署该服务,而不会影响到其他微服务的正常运行,大大提高了部署的效率和灵活性。并且我们可以根据每个微服务的实际负载情况,独立地进行水平扩展或收缩。比如,在电商促销活动期间,订单处理微服务可以自动增加实例数量以应对高并发,而商品展示微服务如果负载没有明显变化,则无需进行扩展。

3.单体架构与微服务架构之间的对比

在这里插入图片描述

4.微服务架构演进历程

第一代微服务架构

在第一代微服务架构中,以 RPC 通信为代表,首要解决的是微服务之间的通信问题。技术框架代表如阿里 Dubbo,跨语言平台的框架 Thrift、gRPC…在这个阶段,我们网关逻辑、服务注册与发现逻辑、负载均衡等等都需要我们自己实现,由于我们分成多个服务开发,那么我们在每个服务上都要实现上面这些功能,这样就需要大量的代码逻辑需要实现,所以这个阶段我们主要解决了服务之间通信的问题。

在这里插入图片描述

第二代微服务架构

在第二代微服务架构中,更多就是将一些相同逻辑,如服务的自动注册和发现,服务之间的通信以及容错机制模块化,将他们封装为不同的SDK或者插件或者服务框架,让我们在使用过程中只需要引入相关依赖,配置一些属性就能够使用,并且将这些非业务逻辑与业务逻辑分离开,这也是我们现阶段主流的微服务架构。这个阶段比较有代表性的框架如 Dubbo、Spring Cloud,只需要少量代码和注解,即可集成各种所需的服务治理能力。但随着服务框架内功能日益繁多,复用不同开发语言的基础功能就会十分苦难,比如去调用go、python有点困难,这也意味着微服务的开发人员被迫绑定在某种特定语言之下,从而违背了微服务敏捷迭代的原则。还有个最重要的问题,就是版本冲突的问题,比如我们开发中必须注意springcloud、springcloud alibaba springboot之间的版本,不然的话可能版本不兼容导致各种各样的异常。

在这里插入图片描述

第三代微服务架构

随着云原生时代的到来,第三代微服务架构也随之推出,在这个阶段出现了服务网格的概念。原来被模块化到服务框架的微服务基础能力,从一个 SDK 演进成为一个独立的进程 - Sidecar(边车)。开发人员只要关注业务逻辑的开发,由边车进程开始接管微服务应用之间的流量,承载第二代微服务架构中服务框架的功能,包括如服务发现、调用容错以及服务治理能力,具体如权重路由、灰度路由、流量重放等。这个变化使得第二代架构中多语言支持问题得到了彻底解决,服务A跟服务B之间的语言可以使用不同的语言,因为服务之间的通信由边车实现。

这个阶段比较有代表性的框架如 Linkerd、Istio 等,可以着重了解一下Istio ,这里不着重讲解,可以去 官网查看,未来是云原生的时代,建议大家多去了解一下这方面。

在这里插入图片描述

第四代微服务架构

第四代微服务架构是目前业界提出的多运行时微服务架构,利用最近的 FaaS 和 AWS 的 Lambda 等无服务器技术来进一步简化微服务的开发和交付。

在第四代微服务架构中,微服务由一个应用进一步简化为微逻辑(Micrologic),变成短暂的功能的集合。就是我们业务中的API也即是controller层的方法变成一个服务进行开发。这新型的架构也对边车模式提出了更高的要求,更多可复用的分布式能力从应用中剥离,并下沉到边车中,例如状态管理、资源绑定、链路追踪、事务管理等。同时,开发侧开始提倡面向 localhost 编程的理念,并提供标准 API 屏蔽底层资源、服务、基础设施之间的差异,以进一步降低微服务的开发难度。

目前比较有代表性的框架如 Dapr,万物皆API。

在这里插入图片描述

旧服务改造

1. 微服务拆分的一些通用原则

单一服务功能高内聚低耦合:每个服务只完成自己职责内的任务,对于不是自己职责的功能交给其它服务来完成

闭包原则:当我们需要改变一个微服务的时候,所有依赖都在这个微服务的组件内,不需要修改其他微服务

服务自治、接口隔离原则:尽量消除对其他服务的强依赖,这样可以降低沟通成本,提升服务稳定性。服务通过标准的接口隔离,隐藏内部实现细节。这使得服务可以独立开发、测试、部署、运行,以服务为单位持续交付。

持续演进原则:在服务拆分的初期,你其实很难确定服务究竟要拆成什么样。应逐步划分,持续演进,避免服务数量的爆炸性增长。

**拆分的过程尽量避免影响产品的日常功能迭代:**也就是说要一边做产品功能迭代,一边完成服务化拆分。比如优先剥离比较独立的边界服务(如短信服务等),从非核心的服务出发减少拆分对现有业务的影响。同时当两个服务存在依赖关系时优先拆分被依赖的服务。

服务接口的定义要具备可扩展性:比如微服务的接口因为升级把之前的三个参数改成了四个,上线后导致调用方大量报错,推荐做法服务接口的参数类型最好是封装类,这样如果增加参数就不必变更接口的签名

避免环形依赖与双向依赖:尽量不要有服务之间的环形依赖或双向依赖,原因是存在这种情况说明我们的功能边界没有化分清楚或者有通用的功能没有下沉下来。

在这里插入图片描述

**阶段性合并:**随着你对业务领域理解的逐渐深入或者业务本身逻辑发生了比较大的变化,亦或者之前的拆分没有考虑的很清楚,导致拆分后的服务边界变得越来越混乱,这时就要重新梳理领域边界,不断纠正拆分的合理性。

**自动化驱动:**部署和运维的成本会随着服务的增多呈指数级增长,每个服务都需要部署、监控、日志分析等运维工作,成本会显著提升。因此,在服务划分之前,应该首先构建自动化的工具及环境。开发人员应该以自动化为驱动力,简化服务在创建、开发、测试、部署、运维上的重复性工作,通过工具实现更可靠的操作,避免微服务数量增多带来的开发、管理复杂度问题。

2.微服务拆分策略

(1)功能维度拆分策略

大的原则是基于业务复杂度拆分服务: 业务复杂度足够高,应该基于领域驱动拆分服务。业务复杂度较低,选择基于数据驱动拆分服务

  • 基于数据驱动拆分服务: 从需求以及数据库角度触发,自下而上的架构设计方法,通过分析需求,确定整体数据结构,根据表之间的关系拆分服务。

​ 拆分步骤: 需求分析,抽象数据结构,划分服务,确定调用关系和业务流程验证。

  • 基于领域驱动拆分服务: 从业务模块开始划分,明确自己业务需求可以划分为几个微服务。自上而下的架构设计方法,通过对需求不断探讨,借鉴其他类似产品业务功能,确定关键业务场景,逐步确定边界上下文。领域驱动更强调业务实现效果,认为自下而上的设计可能会导致技术人员不能更好地理解业务方向,进而偏离业务目标。

​ 拆分步骤:通过模型和领域专家建立统一语言,业务分析,寻找聚合,确定服务调用关系,业务流程验证和持续优化。

​ 以电商的场景为例,交易链路划分的限界上下文如下图左半部分,根据一个限界上下文可以设计一个微服务,拆解出来的微服务如下 图右侧部分。

在这里插入图片描述

  • 还有一种常见拆分场景,从已有单体架构中逐步拆分服务。

拆分步骤: 前后端分离,提取公共基础服务(如授权服务,分布式ID服务),不断从老系统抽取服务,垂直划分优先,适当水平切分

以上几种拆分方式不是多选一,而是可以根据实际情况自由排列组合。同时拆分不仅仅是架构上的调整,也意味着要在组织结构上做出相应的适应性优化,以确保拆分后的服务由相对独立的团队负责维护。

(2)非功能维度拆分策略

主要考虑六点包括扩展性、复用性、高性能、高可用、安全性、异构性

扩展性

区分系统中变与不变的部分,不变的部分一般是成熟的、通用的服务功能,变的部分一般是改动比较多、满足业务迭代扩展性需要的功能,我们可以将不变的部分拆分出来,作为共用的服务,将变的部分独立出来满足个性化扩展需要

同时根据二八原则,系统中经常变动的部分大约只占 20%,而剩下的 80% 基本不变或极少变化,这样的拆分也解决了发布频率过多而影响成熟服务稳定性的问题。

复用性

不同的业务里或服务里经常会出现重复的功能拆分出来形成独立的服务。

高性能

将性能要求高或者性能压力大的模块拆分出来,避免性能压力大的服务影响其它服务。

我们也可以基于读写分离来拆分,比如电商的商品信息,在 App 端主要是商品详情有大量的读取操作,但是写入端商家中心访问量确很少。因此可以对流量较大或较为核心的服务做读写分离,拆分为两个服务发布,一个负责读,另外一个负责写。

数据一致性是另一个基于性能维度拆分需要考虑的点,对于强一致的数据,属于强耦合,尽量放在同一个服务中(但是有时会因为各种原因需要进行拆分,那就需要有响应的机制进行保证),弱一致性通常可以拆分为不同的服务。

高可用

将可靠性要求高的核心服务和可靠性要求低的非核心服务拆分开来,然后重点保证核心服务的高可用。

安全性

不同的服务可能对信息安全有不同的要求,因此把需要高度安全的服务拆分出来,进行区别部署,比如设置特定的 DMZ 区域对服务进行分区部署,可以更有针对性地满足信息安全的要求,也可以降低对防火墙等安全设备吞吐量、并发性等方面的要求,降低成本,提高效率。

异构性

对于对开发语言种类有要求的业务场景,可以用不同的语言将其功能独立出来实现一个独立服务。

3.旧服务改造演示

这里拿我之前的一个项目演示,感兴趣的可以去gitee查看项目代码
在这里插入图片描述

shouyiLibrary-auth-server 认证微服务

shouyiLibrary-cart 购物车微服务

shouyiLibrary-common 通用微服务

shouyiLibrary-coupon 优惠劵微服务

shouyiLibrary-gateway 网关微服务

shouyiLibrary-member 会员微服务

shouyiLibrary-order 订单微服务

shouyiLibrary-product 商品微服务

shouyiLibrary-search 检索微服务

shouyiLibrary-seckill 秒杀微服务

shouyiLibrary-third-party 第三方微服务

shouyiLibrary-ware 库存微服务

这里我会以shouyiLibrary-member来演示如何接入微服务Spring Cloud&Spring Cloud Alibaba技术栈。

(1)Spring Cloud Alibaba技术栈选型

Spring Cloud Alibaba官网:https://github.com/alibaba/spring-cloud-alibaba/wiki

SpringCloud的几大痛点:

  • SpringCloud部分组件停止维护和更新,给开发带来不便;
  • SpringCloud部分环境搭建复杂,没有完善的可视化界面,我们需要大量的二次开发和定制
  • SpringCloud配置复杂,难以上手,部分配置差别难以区分和合理应用

SpringCloud Alibaba的优势:

  • 阿里使用过的组件经历了考验,性能强悍,设计合理,现在开源出来大家用成套的产品搭配完善的可视化界面给开发运维带来极大的便利
  • 搭建简单,学习曲线低。

所以我们优先选择Spring Cloud Alibaba提供的微服务组件

按照Spring Cloud Alibaba官方推荐版本选择对应的Spring Cloud、Spring Cloud Alibaba、springboot的版本版本对照说明

在这里插入图片描述

(2)接入Nacos注册中心

在这里插入图片描述

微服务之间通信首先需要知道各个微服务之间的ip以及端口信息,这就需要我们将微服务的一些信息注册到某个地方,让其他微服务能够知道自己服务的地址,能够正确的调用,所以我们就需要一个注册中心来实现服务的注册与发现,这里我们使用nacos作为我们的注册中心。

第一步:引入依赖

<!--springcloud-alibab-naco服务注册与发现-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

第二步:在yml中填写注册中心地址以及信息

spring:application:name: shouyiLibrary-member #服务名cloud:nacos:discovery:server-addr: 127.0.0.1:8848  #注册中心地址

第三步,在启动类上加上服务发现注解

@EnableDiscoveryClient

此时我们启动程序加nacos,如果能够在nacos上看到服务的信息,就表示服务的注册与发现成功

在这里插入图片描述

(3)接入nacos配置中心

随着微服务数量的增多,如果部署到生产环境中,修改配置特别的麻烦,比如我们想要改一个端口,结果需要下线,修改,再上线,可以看到这种非常的麻烦而且效率非常低,而且在我们配置文件中存在许多重复的配置,如日志等等,此时我们就希望有一个集中管理配置的地方,最好还能实现热部署,此时我们就需要引入配置中心,这里我们使用nacos作为我们的配置中心。

第一步:引入依赖

<!--        nacos配置管理依赖-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

第二步:在yml中填写注册中心地址以及信息

spring:application:name: shouyiLibrary-member #服务名cloud:nacos:server-addr: 127.0.0.1:8848config: #配置文件相关配置namespace: dev01group: shouyiLibrary-memberfile-extension: yamlrefresh-enabled: true#最终会到我们的注册中心找到 shouyiLibrary-member.yaml#共享配置shared-configs:- data-id: swagger-${spring.profiles.active}.yamlgroup: shouyiLibrary--commonrefresh: true- data-id: logging-${spring.profiles.active}.yamlgroup: shouyiLibrary--commonrefresh: true- data-id: freemarker-config-dev.yamlgroup: shouyiLibrary--commonrefresh: true- data-id: feign-${spring.profiles.active}.yamlgroup: shouyiLibrary--commonrefresh: trueprofiles:active: dev   #环境名

我们就可以将我们服务的配置信息移到nacos上,这样启动微服务就会到nacos上找我们的配置信息。

在这里插入图片描述

(4)接入openfeign实现服务之间的通信

接下来就是解决微服务之间通信的问题,不多说直接开始。

第一步:引入依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

第二步:在启动类上说明远程调用类的位置,

@EnableFeignClients(basePackages = "com.uliky.shouyiLibrary.member.feign")

第三步:在com.uliky.shouyiLibrary.member.feign创建类,并在类上添加FeignClient注解,并声明该微服务在nacos上的服务名,最后将该服务中需要的方法原封不动拷贝过来即可完成调用。

@FeignClient("shouyiLibrary-order")
public interface OrderFeignService {/*** 分页查询当前登录用户的所有订单信息* @param params* @return*/@PostMapping("/order/order/listWithItem")R listWithItem(@RequestBody Map<String, Object> params);}

扩展场景:实现 RequestInterceptor,添加请求头参数用于传递 memberId

我们有可能会遇到一些方法需要在请求头中拿到一个字段,如id用来去数据库中查询,这个时候我们就需要实现 RequestInterceptor来在发送请求之前,往请求头上插入数据,如:

public class HeaderInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if(null != attributes){HttpServletRequest request = attributes.getRequest();log.info("从 Request 中解析请求头");template.header("memberId",request.getHeader("memberId"));}}
}
# FeignConfig.java 中添加拦截器配置
@Bean
public RequestInterceptor requestInterceptor() {return new HeaderInterceptor();
}

(5)接入gateway网关

第一步:引入依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

第二步:在配置文件中配置路由规则

注意,gateway网关也需要注册到nacos中

spring:cloud:gateway:routes:   #路由规则- id: product_route  #给路由起名字,可以随意取uri: lb://gulimall-product //转发到哪个微服务上,lb:表示负载均衡predicates:- Path=/api/product/**,/hello	//路由规则,/api/product/开头的请求,多个路由规则由","隔开filters:- RewritePath=/api/(?<segment>.*),/$\{segment}	//过滤,对接收的请求格式进行处理,再发到后端服务器。- id: coupon_routeuri: lb://gulimall-couponpredicates:- Path=/api/coupon/**,/hellofilters:- RewritePath=/api/(?<segment>.*),/$\{segment}

到此微服务就改造的差不多了,但是这只是最基本的服务改造,还需要根据你的业务需求引入其他的微服务组件,比如负载均衡、熔断机制等等,分布式事务等等,大致都跟上述差不多,所以这里就不再演示。

总结

本篇博客内容主要讲解了微服务架构的演进以及旧服务改造,讲述了微服务架构的优势以及未来微服务发展趋势,大家可以通过查阅资料进行相关的学习,抓住未来云原生的机遇,最后希望大家能够留下点赞、关注、收藏,让我能够继续发表更多文章。

相关文章:

旧服务改造及微服务架构演进

旧服务改造及微服务架构演进 微服务架构演进1.微服务架构2.微服务架构的特点3.单体架构与微服务架构之间的对比4.微服务架构演进历程 旧服务改造1. 微服务拆分的一些通用原则2.微服务拆分策略&#xff08;1&#xff09;功能维度拆分策略&#xff08;2&#xff09;非功能维度拆分…...

数据结构复习 (顺序查找,对半查找,斐波那契查找,插值查找,分块查找)

查找&#xff08;检索&#xff09;&#xff1a; 定义&#xff1a;从给定的数据中找到对应的K 1&#xff0c;顺序查找&#xff1a; O(n)的从前向后的遍历 2&#xff0c;对半查找&#xff0c;要求有序 从中间开始查找&#xff0c;每次检查中间的是否正确&#xff0c;不正确就…...

根据docker file 编译镜像

比如给到一个Dockerfile 第一步编译镜像 cd /path/to/Dockerfiledocker build -t <DOCKER_IMAGE_NAME> . build 命令编译镜像 -t 镜像名字 . 指dockerfile 所在目录 如果遇到报错 [] Building 0.3s (3/3) FINISHED …...

C语言:调试的概念和调试器的选择

所谓调试&#xff08;Dubug&#xff09;&#xff0c;就是跟踪程序的运行过程&#xff0c;从而发现程序的逻辑错误&#xff08;思路错误&#xff09;&#xff0c;或者隐藏的缺陷&#xff08;Bug&#xff09;。 在调试的过程中&#xff0c;我们可以监控程序的每一个细节&#xff…...

Vulnhub靶场(Earth)

项目地址 https://download.vulnhub.com/theplanets/Earth.ova.torrent 搭建靶机 官网下载.ova文件双击vm打开导入 获取靶机IP kail终端输入 arp-scan -l 获取靶机 IP 192.168.131.184 信息收集 端口扫描 sudo nmap -sC -sV -p- 192.168.131.184 可以看到开启22端口&…...

rsync命令常用同步方案

rsync是一个高效的文件同步工具&#xff0c;广泛应用于本地和远程备份、镜像及同步任务。它通过增量同步、压缩传输以及远程协议&#xff08;如SSH&#xff09;等技术&#xff0c;显著提高了文件传输的效率。本文将介绍rsync命令的常用参数、工作原理、常见同步方案&#xff0c…...

【Ubuntu】 Ubuntu22.04搭建NFS服务

安装NFS服务端 sudo apt install nfs-kernel-server 安装NFS客户端 sudo apt install nfs-common 配置/etc/exports sudo vim /etc/exports 第一个字段&#xff1a;/home/lm/code/nfswork共享的目录 第二个字段&#xff1a;指定哪些用户可以访问 ​ * 表示所有用户都可以访…...

Python自学 - 递归函数

1 Python自学 - 递归函数 递归函数是一种在函数体内调用自己的函数&#xff0c;就像“左脚踩着右脚&#xff0c;再右脚踩着左脚… 嗯&#xff0c;你就可以上天了&#xff01;”。递归函数虽然不能上天&#xff0c;但在处理某些场景时非常好用&#xff0c; 一种典型的场景就是遍…...

后端开发入门超完整速成路线(算法篇)

引言 后端开发是软件开发中不可或缺的一部分&#xff0c;它涉及到服务器、数据库、API等核心组件的构建和维护。对于初学者来说&#xff0c;掌握算法和数据结构是进入后端开发领域的基础。本文将为你提供一个超完整的算法学习路线&#xff0c;帮助你快速入门&#xff0c;并在文…...

51单片机——共阴数码管实验

数码管中有8位数字&#xff0c;从右往左分别为LED1、LED2、...、LED8&#xff0c;如下图所示 如何实现点亮单个数字&#xff0c;用下图中的ABC来实现 P2.2管脚控制A&#xff0c;P2.3管脚控制B&#xff0c;P2.4管脚控制C //定义数码管位选管脚 sbit LSAP2^2; sbit LSBP2^3; s…...

使用Clion在ubuntu上进行交叉编译,并在Linux上远程编译五子棋

目录 1.工具以及概念介绍 &#xff08;1&#xff09;Clion软件简介 &#xff08;2&#xff09;交叉编译 &#xff08;3&#xff09;远程编译 2.操作原理 3.详细操作步骤 &#xff08;1&#xff09;配置Clion与虚拟机ubuntu的ssh连接 CLion远程开发Ubuntu&#xff0c;并显…...

高并发写利器-组提交,我的Spring组件实战

高并发写优化理论 对于高并发的读QPS优化手段较多&#xff0c;最经济简单的方式是上缓存。但是对于高并发写TPS该如何提升&#xff1f;业界常用的有分库分表、异步写入等技术手段。但是分库分表对于业务的改造十分巨大&#xff0c;涉及迁移数据的麻烦工作&#xff0c;不会作为…...

Stable Diffusion的简单介绍

Stable Diffusion 是一款免费、开源的 AI 图像生成器&#xff0c;由 Stability AI 公司于 2022 年 8 月推出1。以下是关于它的详细介绍&#xff1a; 目录 工作原理 特点 应用场景 主要版本 工作原理 Stable Diffusion 属于潜在扩散模型&#xff0c;主要由三部分组成&…...

R语言的数据结构

R语言的数据结构 R语言是专门为统计计算和数据分析而设计的一种编程语言&#xff0c;因其强大的数据处理能力而受到广泛欢迎。在R中&#xff0c;数据结构是理解和有效使用R语言的基础。本文将详细介绍R语言中的主要数据结构&#xff0c;包括向量、矩阵、数据框、列表、因子等&…...

go项目zero框架中用gentool解决指定MYSQL表生成结构体被覆盖的解决方案

在使用 GoZero 框架进行项目开发时&#xff0c;gentool 是一个非常方便的工具&#xff0c;它可以根据数据库表结构自动生成 Go 语言结构体和其他相关文件。然而&#xff0c;在使用 gentool 生成结构体时&#xff0c;可能会遇到一个问题&#xff1a;如果多次运行 gentool&#x…...

限时特惠,香港服务器,低至53元/年

家人们谁懂啊&#xff01;香港服务器这价格简直逆天了&#xff0c;居然比内地的还便宜&#xff01;就拿阿里云来说&#xff0c;人家最低配置的服务器&#xff0c;价格都很难做到这么亲民。 最低配的就不说了&#xff0c;2 核 4G 的配置&#xff0c;应对日常业务稳稳当当&#x…...

【GUI-pyqt5】QObject类

1. QObject模块详解 1.1 描述 所有Qt对象的父类 1.2 功能和作用 1.2.1 对象名称和属性 1.2.1.1 API API功能备注 setObjectName("唯一名称") 给一个Qt对象设置一个名称 一般这个名称是唯一的&#xff0c;当做对象ID来使用 objectName() 获取一个对象名称 - set…...

第2章:SQL基础

第2章&#xff1a;SQL基础 2.1 SQL语言介绍 2.1.1 SQL发展历史 SQL的起源SQL标准的演变不同数据库的SQL实现 2.1.2 SQL语言分类 数据定义语言 (DDL):用于定义和修改数据库的结构&#xff0c;包括数据库、表、索引、视图等对象的创建、修改和删除。数据操作语言 (DML):用于…...

Azkaban其一,介绍、体系架构和安装

目录 一、简介 二、Azkaban的体系结构 三、Azkaban的安装步骤 1、上传&#xff0c;解压 2、生成mysql的元数据 3、配置web-server 4、配置exec-server 5、修改所有的.sh 的执行权限 一、简介 遇到了什么问题才会使用Azkaban ?比如&#xff1a; 想启动hadoop集群先启动…...

Seata 使用教程:全面解锁分布式事务管理

Seata 使用教程:全面解锁分布式事务管理 在当今分布式系统蓬勃发展的时代,微服务架构被广泛应用,随之而来的是分布式事务管理的难题。Seata 作为一款开源的分布式事务解决方案,为保障分布式系统的数据一致性提供了强有力的支持。本文将详细讲解 Seata 的使用方法,深入剖析…...

《learn_the_architecture_-_aarch64_exception_model》学习笔记

1.当发生异常时&#xff0c;异常级别可以增加或保持不变&#xff0c;永远无法通过异常来转移到较低的权限级别。从异常返回时&#xff0c;异常级别可能会降低或保持不变&#xff0c;永远无法通过从异常返回来移动到更高的权限级别。EL0级不进行异常处理&#xff0c;异常必须在比…...

密码学原理技术-第十一章-Hash Functions

文章目录 总结Why we need hash functionsDigital Signature with a Hash FunctionBasic Protocol for Digital Signatures with a Hash FunctionPrincipal input–output behavior of hash functions Security propertiesThe three security requirements of hash functionsWh…...

Golang 入门基础知识

快速入门 go 语言笔记&#xff0c;参考了各种大佬的 blog 。 一、下载安装 国内站点 &#xff1a;https://golang.google.cn IDE &#xff1a; Goland &#xff08;2020.12月以后破解有些困难 见 zhile.io&#xff0c; 无法试用的话可以搜一个注册码&#xff0c;失效的也可以&…...

SQL把字符串按逗号分割成记录

在 SQL 中&#xff0c;可以通过以下方法将字符串按逗号分割&#xff0c;并将每个分割的值作为单独的记录插入到结果集中。以下是针对不同数据库系统的实现方法&#xff1a; 1. 使用 STRING_SPLIT&#xff08;SQL Server 2016&#xff09; STRING_SPLIT 是 SQL Server 提供的内置…...

HTML——26.像素单位

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>像素</title></head><body><!--像素&#xff1a;1.指设备屏幕上的一个点&#xff0c;单位px&#xff0c;如led屏上的小灯朱2.当屏幕分辨率固定时&…...

TIM的输出比较(PWM)

OC&#xff08;Output Compare&#xff09;输出比较 输出比较可以通过比较CNT与CCR寄存器值的关系&#xff0c;来对输出电平进行置1、置0或翻转的操作&#xff0c;用于输出一定频率和占空比的PWM波形 每个高级定时器和通用定时器都拥有4个输出比较通道 初始化 1.开启RCC RCC_…...

李宏毅机器学习笔记-Transformer

目录 1. Seq2seq 2. encoder Transformer 中的 Block 结构 3. Decoder 4.Encoder和Decoder间的信息传递 5.Training 6.Tips 1. Seq2seq Transformer 是一个seq2seq的model。Seq2seq指的是input是一个序列&#xff0c;输出也是一个序列&#xff0c;输出的长度是由机器自己…...

【机器学习:三、常见的代价函数】

代价函数的选择与任务类型&#xff08;回归、分类等&#xff09;以及模型的具体目标密切相关。 回归任务中的代价函数 均方误差&#xff08;Mean Squared Error, MSE&#xff09; 公式: J ( θ ) 1 m ∑ i 1 m ( y i − y ^ i ) 2 J(\theta)\frac{1}{m}\sum_{i1}^m(y_i-\…...

React 数据是怎样传递的

写在前面 在 React 应用程序中&#xff0c;数据传递是非常重要的。它允许我们在组件之间共享信息和状态&#xff0c;从而构建出复杂的用户界面。本文将深入探讨 React 中的数据传递机制&#xff0c;包括 props、state 和 context API。我们还将通过实际例子来演示如何在项目中…...

Python入门教程 —— 高阶函数和装饰器

1.递归函数 什么是递归函数 如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数。 递归函数的作用 举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n 解决办法1:使用循环来完成 def cal(num):result,i = 1,1while i <= num:result *= ii…...

RSA密码的安全性分析(简化版本)

RSA的安全性是基于分解大整数的困难性假定&#xff0c;之所以认为是假定是因为至今还未能证明大整数就是NP问题&#xff0c;也许有尚未发现的多项式时间分解算法。随着人类计算能力的不断提高&#xff0c;原来被认为是不可能分解的大数已经被成功分解。对于大整数的威胁除了人类…...

解决Vue中设置el-select的高度不生效问题

el-select是Element UI框架中的一个选择器组件&#xff0c;它允许用户从多个选项中选择一个或多个项目。但这里确存在一个小坑&#xff0c;我们可以看到直接修改el-select的高度是无法生效的 <template><div id"login"><el-select v-model"role…...

解决openpyxl操纵带公式的excel或者csv之后,pandas无法读取数值的问题

1 功能特点 openpyxl&#xff1a; 这是一个专门用于操作Excel文件&#xff08;.xlsx/.xlsm&#xff09;的库。它提供了丰富的功能来读取、写入和修改Excel文件的各个元素&#xff0c;如单元格、行、列、工作表等。例如&#xff0c;可以通过openpyxl轻松地创建一个新的Excel工作…...

高等数学学习笔记 ☞ 无穷小比较与等价无穷小替换

1. 无穷小比较 1. 本质&#xff1a;就是函数的极限趋于0时的速度&#xff0c;谁快谁慢的问题。 2. 定义&#xff1a;若是在同一自变量的变化过程中的无穷小&#xff0c;且&#xff0c;则&#xff1a; ①&#xff1a;若&#xff0c;则称是比的高阶无穷小&#xff0c;记作&…...

计算队列中的‘捣乱分子’对数:一种量化无序程度的方法

计算队列中的‘捣乱分子’对数:一种量化无序程度的方法 前言解题思路关键点实现代码时间复杂度分析前言 在日常生活中,我们经常会遇到需要排队的场景,比如买票、候车、就餐等。在理想的排队情况下,人们会按照某种顺序(如先到先服务)整齐地排成一列。然而,总有一些人不遵…...

如何在不丢失数据的情况下从 IOS 14 回滚到 IOS 13

您是否后悔在 iPhone、iPad 或 iPod touch 上安装 iOS 14&#xff1f;如果你这样做&#xff0c;你并不孤单。许多升级到 iOS 14 beta 的 iPhone、iPad 和 iPod touch 用户不再适应它。 如果您在正式发布日期之前升级到 iOS 14 以享受其功能&#xff0c;但您不再适应 iOS 14&am…...

提升汽车金融租赁系统的效率与风险管理策略探讨

内容概要 在汽车金融租赁系统这个复杂的生态中&#xff0c;提升整体效率是每个企业都渴望达成的目标。首先&#xff0c;优化业务流程是实现高效运行的基础。通过分析目前的流程&#xff0c;找出冗余环节并进行简化&#xff0c;能够帮助企业缩短审批时间&#xff0c;提高客户满…...

Git 入门(一)

git 工作流如下&#xff1a; 命令如下&#xff1a; clone&#xff08;克隆&#xff09;: 从远程仓库中克隆代码到本地仓库checkout &#xff08;检出&#xff09;:从本地仓库中检出一个仓库分支然后进行修订add&#xff08;添加&#xff09;: 在提交前先将代码提交到暂存区com…...

pyinstaller冻结打包多进程程序的bug:无限创建进程直至系统崩溃

前面写过两篇相关的文章&#xff1a; PyQt应用程序打包Python自动按键 这两篇文章都没有提到下面的这个重要问题&#xff1a; 采用Pyinstaller冻结打包多进程程序时&#xff0c;必须非常小心。这个技术线在Windows上会有一个非常严重的Bug。直接运行打包后的程序会造成无限创…...

OSI模型的网络层中产生拥塞的主要原因?

&#xff08; 1 &#xff09;缓冲区容量有限&#xff1b;&#xff08; 1.5 分&#xff09; &#xff08; 2 &#xff09;传输线路的带宽有限&#xff1b;&#xff08; 1.5 分&#xff09; &#xff08; 3 &#xff09;网络结点的处理能力有限&#xff1b;&#xff08; 1 分…...

服务器开发 的设计模式(Design Patterns)核心知识

服务器开发的设计模式&#xff08;Design Patterns&#xff09;核心知识 在现代软件开发中&#xff0c;设计模式是一组为解决特定问题而重用的解决方案。它们是经过时间考验的最佳实践&#xff0c;为开发人员提供了一种有效的解决方案来应对常见的软件设计问题。特别是在服务器…...

智能工厂的设计软件 应用场景的一个例子: 为AI聊天工具添加一个知识系统 之20 再次重建 之5 项目文件三大部 整“拼”项目文档总述

本文要点 ]本项目的项目文件中的三个Part终于“拼”出来的&#xff08;个别用词可能还需斟酌&#xff0c;但样子、格式和意思 差不多): Part1【凡间-AI众生】 人性化&去中心化-个体人生观 语言有关&#xff08;语言交流-经验常识实践 信条 行为主义 随机数-本质偶然的 想…...

Lucas-Kanade光流法详解

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 光流&#xff08;Optical Flow&#xff09;描述的是图像序列中各像素点随时间的运动情况&#xff0c;是计算机视觉中的基本问题之一。光流问题涉及尝试找出一幅图像中的许多点在第二幅图像中移动的…...

基于YOLO5的机械臂视觉抓取实现

前言&#xff1a; 机器人视觉系统标定是保证机器人精确运动和控制的关键环节之一。通过对机器人的运动学进行分析&#xff0c;可以精确计算出机器人末端执行器的位姿信息&#xff0c;从而实现对目标的精准定位和控制。相机标定是计算机视觉和图像处理中的重要步骤&#xff0c;标…...

Git 仓库与文件管理笔记

Git 的三种仓库概念 本地仓库 (Local Repository) 位于本地 .git 文件夹中通过 git init 或 git clone 创建存储完整的项目历史和分支信息 远程仓库 (Remote Repository) 位于 GitHub、GitLab 等平台服务器使用 git remote -v 查看所有远程仓库默认远程仓库名通常为 origin 工…...

Qt 5.14.2 学习记录 —— 오 信号与槽机制(2)

文章目录 1、信号与槽的参数2、为什么要有信号槽机制&#xff1f;3、断开并重新连接4、槽函数lambda写法 1、信号与槽的参数 信号和槽可以带参数&#xff0c;当信号带有参数时&#xff0c;槽的参数必须和信号的一致&#xff0c;此时发送信号就可以给信号函数传递实参&#xff…...

043_小驰私房菜_MTK Camera,Hal层将camera型号写到property属性中

【问题背景】 app层需要知道当前设备的摄像头型号,然后做一些差异化处理。底下如何上报这个摄像头型号? 【分析】 在kernel和hal层,都是有地方能获取到当前摄像头的型号,就看在哪里添加方便。获取到摄像头硬件型号后,将其写入到property属性, 然后app就可以通过读取该…...

Java线程

目录 一、线程入门 二、线程同步 三、死锁 四、线程的方法 五、线程的流程图 六、线程池 一、线程入门 1.进程&#xff1a;每一个软件都是一个进程。 2.线程&#xff1a;进程是由多个线程组成的。 3.进程和线程的关系&#xff1a;一个进程是对应一个或者是多个线程的。…...

JMeter 的 If Controller:开启性能测试的智能大门

嘿&#xff0c;宝子们&#xff01;今天咱们就来聊聊 JMeter 里超级厉害的 If Controller&#xff0c;它就像是一把神奇的钥匙&#xff0c;能帮我们打开灵活测试的大门&#xff0c;让你的测试计划变得更加智能和高效。 一、If Controller 初印象 想象一下&#xff0c;你正在指…...

node内置模块之---os 模块

os 模块的作用 os 模块是 Node.js 的一个核心模块&#xff0c;提供了与操作系统交互的一些功能。它使得 Node.js 应用可以访问操作系统的底层信息&#xff0c;并执行一些系统级的操作&#xff0c;比如文件系统操作、环境变量、进程管理等。 os 模块的相关api 文件系统路径操…...