SpringCloud极限速通版

news2024/9/19 14:34:06

1.SpringCloud概述

1.1 什么是微服务

1.1.1 单体架构

        业务所有功能都打包在一个war包或jar包,这种方式就是单体架构,单体架构的应用就是单体应用。这种架构开发简单,部署简单,一个项目包含所有功能;省去了多个项目之间交互和调用消耗,直接部署在一个服务器即可。

单体面临的问题:

  • 后端服务器压力大,负载高
  • 业务场景发展变复杂之后,单体应用越来越大,各个业务之间耦合度也会越来越高:某一个功能挂了 ,全挂了 。

解决方案:

        横向:添加服务器 -> 集群

        纵向:把整块业务划分为不同的模块 -> 分布式

1.1.2 集群和分布式架构

        集群:将一个完整的系统部署到多个服务器上,每个服务器都能提供系统的所有服务,多个服务器通过负载均衡调度完成任务,每个服务器称为节点

        分布式:将一个系统拆分为多个子系统,多个子系统部署到多个服务器上,多个服务器的子系统完成一个特点任务

集群和分布式的联系:

  • 从概念上:集群是多个计算机做相同的事,分布式是多个计算机做不同的事
  • 从功能上:集群每个点功能相同和互相替代,分布式的节点业务实现不同
  • 从关系上:在实践中,二者互相配合:分布式某一个节点是一个集群;分布式架构建立在集群上,二者通称分布式架构

1.1.3 微服务架构

        按照业务拆分的话,会有一些重复功能实现:因此我们可以把通用的,被多个上层服务调用的共享业务,提取成独立的基础服务,组成一个个微小的服务:微服务

    

简单来说:微服务是很小的服务,小到一个服务只对应一个单一的功能,只做一件事,这个服务可以单独部署运行

微服务之间使用Rest或者RPC通信        

分布式与微服务的区分

分布式:服务拆分,拆了就行

微服务:指非常微笑的服务,不能再拆分的服务,更细粒度的垂直拆分

微服务是一种经过良好架构设计的分布式架构方案;

1.2 什么是SpringCloud

SpringCloud是分布式微服务架构的一站式解决方案

注意版本一致

本文将以SpringCloudAlibaba为主进行讲解简单的入门及项目运用

2. SpringCloud运用

2.1 环境与工程搭建

win和linux都需要安装:JDK21+MySQL5.7

Linux安装jdk21:

wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm

yum -y install jdk-21_linux-x64_bin.rpm

java -version

2.2 服务拆分

将模拟实现一个demo级别的电商平台,先从服务拆分起手:

问题来了如何划分?一般遵循以下原则:

1.单一职责原则

指的是一个类应该专注于单一功能,不要存在多于一个导致类变更的原因

2.服务自治

自己可以独立自理,每一个服务都可以独立开发构建部署测试...

3.单向依赖

不能存在循环依赖、双向依赖:循环依赖 A调用B,B调用C,C调用A  ,双向依赖 A调用B,B调用A。

要注意的是:服务拆分不一定一定要遵循原则,具体情况具体划分以业务为主。

以商品订单为例:

把服务拆分为订单服务、商品服务

订单服务:提供订单ID,获取订单详细信息

商品服务:根据商品ID,返回商品详细信息

2.3 数据准备

订单表商品表

2.4 工程搭建

2.4.1 创建父子工程

创建Maven项目

2.4.2 订单、商品服务实现

简单的controller、service、mapper层实现即可

2.4.3 远程调用

我们想调用订单服务获取订单信息,订单信息中的商品ID在去调用商品服务,获取商品信息。

我们是用封装好的RestTemplate,通过http访问来实现远程调用。

public class OrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;

    public OrderInfo selectOrderById(Integer orderId){
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        ProductInfo productInfo = restTemplate.getForObject("http://order/selectProductById?productId=" + orderInfo.getProductId(), ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
    }
}
RestTemplate

Rest:表现层  资源  状态转移

资源:网络上的数据文本图片等

表现层:资源的表现形式 文本的表现形式是txt

状态转移:通过网络访问资源,对资源进行修改(引起资源状态的变化)

简单来说:Rest就是描述网络中client和server的一种交互形式,rest本身不是用,只是一种风格

Restful

满足Rest风格的接口就是Restful API

风格主要特征:

1.资源:资源可以是一个图片,对资源进行处理

2.统一接口:

RestTemplate由Spring提供,封装HTTP调用,并强制使用Resful风格,它会处理HTTP连接和关闭,只需要提供资源地址和参数即可

来看以上的代码出现的问题:

1、url是写死的,url出现变动需要手动修改

2、多机器部署如何处理

3、返回结果如何共用

....

SpringCloud将解决以上等等问题...

3.Eureka

注册中心三个角色:

服务注册:服务提供者启动时,向Registry注册自己的服务,并且向Registry定期发送心跳包汇报存活状态

服务发现:服务消费者从注册中心查询服务提供者的地址,并通过该地址去调用提供者的接口,服务发现一大重要作用:提供给服务消费者一个可用的服务列表

3.1 CAP理论

一致性

强一致性:主库从库无论何时,对外提供的服务都是一致的

弱一致性:随着时间的推移,最终达到一致性

可用性

对所有请求都有响应:这个请求可能是错误的也要响应

分区容错性

在网络分区的情况下,系统依然可用对外提供服务

举一个例子:

在银行中,所有的银行工作人员对客户,讲的利率都是一致的,这就是一致性

无论何时,银行人员对客户利率查询请求,都是有答案的,这个答案可能是旧的,这就是可用性

如果一个工作人员请假,银行依旧运行

P一定做到(分区容错性)

保证一致性的情况下,主从库同步期间不对外同步,因此无法保证可用性

保证可用性,数据同步的时候无法保证强一致性

只能二选一

3.2 常见的注册中心

1. zookeeper
Zookeeper的官方并没有说它是一个注册中心,但是国内Java体系,大部分的集群环境都是依赖Zookeeper来完成注册中心的功能.
2. Eureka
Eureka是Netflix开发的基于REST的服务发现框架,主要用于服务注册,管理,负载均衡和服务故障转移.官方声明在Eureka2.0版本停止维护,不建议使用.但是Eureka是SpringCloud服务注册/发现的默认实现,所以目前还是有很多公司在使用.
3. Nacos
Nacos是Spring Cloud Alibaba架构中重要的组件,除了服务注册,服务发现功能之外, Nacos还支持配置管理,流量管理,DNS,动态DNS等多种特性.
 

3.3 Eureka搭建注册中心

已淘汰,相关组件学习请看其他资料,下文有Nacos

3.负载均衡

负载均衡(LB)是高并发、高可用不可缺少的关键组件

当服务流量增大时,通常会采用增加机器的方式进行扩容,负载均衡就是在多个机器或其他资源中,按照一定的规则(不一定是平均)进行合理的分配

 负载均衡分为客户端负载均衡和服务端负载均衡,二者的区分顾名思义就是负载均衡器在哪里实现,常见的服务端负载均衡器Nginx,常见的客户端负载均衡器为SpringCloudLoadBalancer

3.1 SpringCloudBalancer

3.1.1 简单入门

添加注解、修改远程调用代码,把ip和端口号改成服务名

3.1.2 负载均衡策略

只支持轮询和随机选择:

轮询:服务器轮流的处理请求

随机选择:随机选择一个后端的服务器处理请求

自定义负载均衡策略

要注意:该自定义类不需要@Configuration注释,在组件扫描范围内

使用自定义负载均衡策略,name:该负载均衡器对哪个服务生效;config:该负载均衡策略用哪个策略来实现(图内是自己实现的自定义负载均衡策略)

 3.2 原理

LoadBalancer的实现,主要是LoadBalancerInterceptor

拿到url,从url拿到host获取服务名称,判断不能为空

第一步就是根据服务名称获取负载均衡策略(像上文提到的的自定义均衡策略注解中name属性),如果负载均衡策略为空就返回null,不为空就调用loadBalancerResponse.getServer方法

轮询的策略:

4. Nacos

在最初开源时, Nacos选择进⾏内部三个产品合并统⼀开源(Configserver ⾮持久注册中⼼,VIPServer 持久化注册中⼼,Diamond 配置中⼼). 定位为:⼀个更易于构建云原⽣应⽤的动态服务发现, 配置管理 和服务管理平台. 所以Nacos是⼀个注册中⼼组件, 但它⼜不仅仅是注册中⼼组件.

4.1 Nacos安装

Release 2.2.3 (May 25th, 2023) · alibaba/nacos · GitHub

下载之后解压:

Nacos启动默认是集群模式,自我学习需要修改

以文本编辑器打开start.cmd 进行修改

修改端口号是在conf下application.properties修改port

4.2 快速入门

4.2.1 环境搭建

父子项目都需要添加相对应的依赖,loadBalancer依赖也需加入。要注意的是SpringBoot和Nacos版本有要求。

配置文件

4.2.2 远程调用

4.2.3 服务下线与权重配置

Nacos在控制台上对某一个机器进行下线,IDEA上看这个机器实际还在运行,消费者发送请求(url,restTemplate)不会请求到已下线的机器;

Nacos控制台还可以配置节点的权重

不过要注意的是,如果加了LoadBalancer的话是没办法使用到Nacos权重的:

配置文件修改即可

4.2.4 同集群优先访问

在分布式架构中,一个应用会有多个实例,如何部署?

Nacos把同⼀个机房内的实例, 划分为⼀个集群. 所以同集群优先访问, 在⼀定程度上也可以理解为同机 房优先访问.

因此微服务访问时, 应尽量访问同机房的实例. 当本机房内实例不可⽤时, 才访问其他机房的实例

⽐如order-service 在上海机房, product-service 在北京和上海机房都有实例, 那我们希望可以优先访 问上海机房, 如果上海机房没有实例, 或者实例不可⽤, 再访问北京机房的实例. 通常情况下, 因为同⼀个 机房的机器属于⼀个局域⽹, 局域⽹访问速度更快⼀点!

需要开启Nacos的负载均衡策略


Nacos负载均衡总结

1.支持服务上下线

2.支持权重的配置(非严格)

3.同集群优先访问

2、3前提是需要开启Nacos负载均衡

4.3 健康检查

Nacos作为注册中心,需要感知服务的健康状态

Nacos有俩种健康检查机制

客户端主动上报机制

客户端主动以心跳上报机制告知服务器健康状态,默认心跳间隔5s

nacos会在超过15s未收到心跳后将实例设置为不健康状态,超过30s自动删除

服务器端反向探测机制

nacos主动探知客户端健康状态,默认间隔20s

健康检查失败后,标记为不健康,不会删除

但要注意的是这俩机制不能自主设置, 这俩机制与Nacos的服务实例类型有关 

Nacos服务实例类型

Nacos的服务实例(注册的节点)分为临时实例和⾮临时实例.

• 临时实例: 如果实例宕机超过⼀定时间, 会从服务列表剔除, 默认类型.

• ⾮临时实例: 如果实例宕机, 不会从服务列表剔除, 也可以叫永久实例

修改非临时:配置文件中修改即可

spring:
 cloud:
  nacos:
    discovery:
     ephemeral: false # 设置为⾮临时实例

总结:

4.4 环境隔离

 

配置文件中

spring.cloud.nacos.discovery.namespace:填写命名空间的ID

环境不同的服务是无法进行调用的

4.5 配置中心

除了注册中⼼和负载均衡之外, Nacos还是⼀个配置中⼼, 具备配置管理的功能

为什么需要配置中心?

当前项⽬的配置都在代码中, 会存在以下问题:

1. 配置⽂件修改时, 服务需要重新部署. 微服务架构中, ⼀个服务可能有成百个实例, 挨个部署⽐较⿇ 烦, 且容易出错.

2. 多⼈开发时, 配置⽂件可能需要经常修改, 使⽤同⼀个配置⽂件容易冲突 

流程

1.服务启动时, 从配置中⼼读取配置项的内容, 进⾏初始化.

2. 配置项修改时, 通知微服务, 实现配置的更新加载

使用

1、添加配置、引入依赖

2、修改配置文件

配置管理的命名空间 不是 服务管理(不同环境)的命名空间,二者并无关系只是叫法一样

添加依赖

<dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud 2020.*之后版本需要引⼊bootstrap-->
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

再创建一个配置文件bootstrap.yml

微服务启动前, 需要先获取nacos中配置, 并与application.yml配置合并. 在微服务运⾏之前, Nacos要求 必须使⽤ bootstrap.properties 配置⽂件来配置Nacos Server 地址

spring:
    application:
        name: 服务名称
 cloud:
     nacos:
         config:
             server-addr: IP地址

配置中心和注册中心是隔离的

配置中心详解

设置命名空间

修改bootstrap配置文件

spring.cloud.nacos.config.namespace=配置中心的命名空间ID

Data ID

官方文档

prefix 默认为 spring.application.name 的值, 也可以通过配置项 spring.cloud.nacos.config.prefix 来配置.

• spring.profiles.active 即为当前环境对应的 profile. 当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${fileextension}

• file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。

⽬前只⽀持 properties 和 yaml 类型.

默认为properties. 微服务启动时, 会从Nacos读取多个配置⽂件:

1. ${prefix}-${spring.profiles.active}.${file-extension} 如: product-servicedev.properties

2. ${prefix}.${file-extension} , 如: product-service.properties

3. ${prefix} 如product-service 

三个⽂件的优先级为: product-service-dev.properties > product-service.properties > productservice

5.服务部署

1. 修改数据库, Nacos等相关配置

2. 对两个服务进⾏打包

3. 上传jar到Linux服务器

4. 启动Nacos 启动前最好把data数据删除掉

5. 启动服务 nohup

Nacos与Eureka的区别

共同点: 

都⽀持服务注册服务拉取

区别:

1.功能 :Nacos除了服务发现和注册之外, 还提供了配置中⼼, 流量管理DNS服务等功能.

2. CAP理论

Eureka遵循AP原则, Nacos可以切换AP和CP模式,默认AP.

Nacos 根据配置识别CP或者AP模式.

如果注册Nacos的Client的节点是临时节点, 那么Nacos对这个 Client节点的效果就是AP, 反之是CP. AP和CP可以同时混合存在.

3. 服务发现

Eureka:基于拉模式. Eureka Client会定期从Server拉取服务信息, 有缓存, 默认每30秒拉取⼀次. Nacos:基于推送模式. 服务列表有变化时实时推送给订阅者, 服务端和客⼾端保持⼼跳连接. 

6. openFeign

前面我们使用RestTempalte会带来几个问题:url拼接复杂,代码可读性差,风格不统一

微服务之间通讯方式通常有俩种:RPC和HTTP

SpringCloud默认使用HTTP:RestTemplate和openFeign

RPC(Remote Procedure Call)远程过程调⽤,是⼀种通过⽹络从远程计算机上请求服务,⽽不需 要了解底层⽹络通信细节。RPC可以使⽤多种⽹络协议进⾏通信, 如HTTP、TCP、UDP等, 并且在 TCP/IP⽹络四层模型中跨越了传输层和应⽤层。简⾔之RPC就是像调⽤本地⽅法⼀样调⽤远程⽅法

6.1 介绍openFeign

OpenFeign 是⼀个声明式Web Service 客⼾端. 它让微服务之间的调⽤变得更简单, 类似controller 调⽤service, 只需要创建⼀个接⼝,然后添加注解即可使⽤OpenFeign 

可以简单理解为 Netflix Feign 是OpenFeign的祖先, 或者说OpenFeign 是Netflix Feign的升级版. OpenFeign 是Feign的⼀个更强⼤更灵活的实现

Spring Cloud Feign 是 Spring 对 Feign 的封装, 将 Feign 项⽬集成到 Spring Cloud ⽣态系统中.

受 Feign 更名影响,

Spring Cloud Feign 也有两个 starter

• spring-cloud-starter-feign

• spring-cloud-starter-openfeign (使用这个)

6.2 快速上手

Feign客户端

@FeignClient(value = "product-service", path = "/product")
public interface ProductApi {
 @RequestMapping("/{productId}")
 ProductInfo getProductById(@PathVariable("productId") Integer productId);
}

@FeignClient 注解作⽤在接⼝上, 参数说明:

• name/value:指定FeignClient的名称, 也就是微服务的名称, ⽤于服务发现, Feign底层会使⽤ Spring Cloud LoadBalance进⾏负载均衡. 也可以使⽤ url 属性指定⼀个具体的url.

• path: 定义当前FeignClient的统⼀前缀

6.3 参数传递

6.4 最佳实践

通过观察, 我们也能看出来, Feign的客⼾端与服务器端⾮常相似

继承

我们可以定义好⼀个接⼝, 服务提供⽅实现这个接⼝, 服务消费⽅编写Feign 接⼝的时候, 直接继承这个 接⼝

具体参考: Spring Cloud OpenFeign Features :: Spring Cloud Openfeign

分为几步操作:

在创建一个module:product-api模块

复制 ProductApi, ProductInfo 到product-api模块中

public interface ProductInterface {
 @RequestMapping("/{productId}")
 ProductInfo getProductById(@PathVariable("productId") Integer productId);
 @RequestMapping("/p1")
 String p1(@RequestParam("id") Integer id);
 @RequestMapping("/p2")
 String p2(@RequestParam("id")Integer id,@RequestParam("name")String name);
 @RequestMapping("/p3")
 String p3(@SpringQueryMap ProductInfo productInfo);
 @RequestMapping("/p4")
 String p4(@RequestBody ProductInfo productInfo);
}

目录结构:

maven将此模块打包进本地仓库中,供其他模块调用(加依赖即可调用)

服务提供⽅实现接⼝ ProductInterface

@RequestMapping("/product")
@RestController
public class ProductController implements ProductInterface {
 @Autowired
 private ProductService productService;
 @RequestMapping("/{productId}")
 public ProductInfo getProductById(@PathVariable("productId") Integer
productId){
 System.out.println("收到请求,Id:"+productId);
 return productService.selectProductById(productId);
 }
 @RequestMapping("/p1")
 public String p1(Integer id){
 return "p1接收到参数:"+id;
 }
 @RequestMapping("/p2")
 public String p2(Integer id,String name){
 return "p2接收到参数,id:"+id +",name:"+name;
 }
 @RequestMapping("/p3")
 public String p3(ProductInfo productInfo){
 return "接收到对象, productInfo:"+productInfo;
 }
 @RequestMapping("/p4")
 public String p4(@RequestBody ProductInfo productInfo){
 return "接收到对象, productInfo:"+productInfo;
 }
}

Feign客户端可以删除了

抽取

 简单来说创建一个module,把Feign客户端完整的复制过去,加入到Maven仓库,供其他服务使用

客户端(谁调用的)加注解

在启动类中加!!

@EnableFeignClients(basePackages = {"com.bite.api"})

也可以指定需要加载的Feign客⼾端

@EnableFeignClients(clients = {ProductApi.class})

服务部署

确认配置

打包

部署

7. 统一服务入口 Gateway

当前的所有微服务接口都是直接对外暴露的,可以直接通过外部访问,为了保证安全性。服务端实现的微服务接⼝通常都带有⼀定的权限校验机制. 由于使⽤了微服务, 原本⼀个应⽤的的多个 模块拆分成了多个应⽤, 我们不得不实现多次校验逻辑。

如果是多个服务都需要校验一下权限,那也太麻烦了:Gateway应运而生

7.1 什么是API网关

API⽹关(简称⽹关)也是⼀个服务, 通常是后端服务的唯⼀⼊⼝. 它的定义类似设计模式中的Facade模式 (⻔⾯模式, 也称外观模式). 它就类似整个微服务架构的⻔⾯, 所有的外部客⼾端访问, 都需要经过它来进 ⾏调度和过滤

核心功能

权限校验:网关没过,后面的服务访问不到

动态路由:⼀切请求先经过⽹关, 但⽹关不处理业务, ⽽是根据某种规则, 把请求转发到某个微服务

负载均衡:当路由的⽬标服务有多个时, 还需要做负载均衡     

限流:请求流量过⾼时, 按照⽹关中配置微服务能够接受的流量进⾏放⾏, 避免服务压⼒过⼤

7.2 快速入门

创建一个服务

引入依赖   网关服务添加配置

eg:

uri:目标服务地址

predicates:路由条件(满足后面的条件,会把这个请求转发到uri的地址上)

7.3 Route Predicate Factories

predicate是java8提供的函数式编程接口,接收一个参数并返回一个布尔值用于条件过滤。

Route Predicate Factories (路由断⾔⼯⼚, 也称为路由谓词⼯⼚, 此处谓词表⽰⼀个函数), 在Spring Cloud Gateway中, Predicate提供了路由规则的匹配机制

我们配置文件中写的断言规则是字符串,这些字符串会被RoutePredicateFactory读取并处理,转变为路由判断条件。

更多的条件详见:Route Predicate Factories :: Spring Cloud Gateway

当有多个路由条件的时候,他们的关系是and

7.4 Gateway Filter Factories(网关过滤工厂)

Predicate是决定了请求由哪一个路由处理,Filter则是在请求处理前后加一些逻辑

分俩种类型Post和Pre(根据作用时间划分的)

从作用范围上:

GatewayFilter(应用到单个路由上或一组路由上)和GlobalFilter(应用到所有的路由上,对所有的请求都生效)

7.4.1 GatewayFilter

例子:

GatewayFilter Factories :: Spring Cloud Gateway

默认过滤器

针对全部的路由生效:spring.cloud.gateway.default-filters这个属性加一个filter列表

7.4.2 GlobalFilter

作用与GatewayFilter相同,只不过的是GlobalFilter是应用所有路由请求

Global Filters :: Spring Cloud Gateway

配置文件进行添加

spring.cloud.gateway:

7.5 过滤器执行顺序

请求路由后,global和gateway Filter合并到一个过滤器链中,并进行排序,依次执行过滤器

每个过滤器都有一个int类型的order值,其值越小优先级越高;

当order值一致时,执行顺序是Derfault > Gateway > Global

7.6 自定义过滤器

7.6.1 自定义GatewayFilter

需要实现GatewayFilterFactory,SpringBoot默认实现的是AbstractGatewayFilterFactory

主体类:

@Slf4j
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomConfig> implements Ordered {
    public CustomGatewayFilterFactory() {
        super(CustomConfig.class);
    }

    @Override
    public GatewayFilter apply(CustomConfig config) {
        return new GatewayFilter() {
            /**
             * ServerWebExchange: HTTP 请求-响应交互契约, 提供了对HTTP请求和响应的访问
             * GatewayFilterChain: 过滤器链
             * Mono: Reactor的核心类, 数据流发布者,Mono最多只能触发一个事件.可以把Mono用在异步完成任务时,发出通知
             * chain.filter(exchange)  执行请求
             * Mono.fromRunnable()  创建一个包含Runnable元素的数据流
             */
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                //Pre类型   执行请求   Post类型
                log.info("Pre Filter, config:{} ",config);  //Pre类型过滤器代码逻辑
                return chain.filter(exchange).then(Mono.fromRunnable(()->{
                    log.info("Post Filter....");  //Post类型过滤器代码逻辑
                }));
            }
        };
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

配置类

import lombok.Data;

@Data
public class CustomConfig {
    private String name;
}

使用配置文件

7.6.2 自定义GlobalFilter

@Slf4j
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("Pre Global Filter");
        return chain.filter(exchange).then(Mono.fromRunnable(()->{
            log.info("Post Global Filter...");
        }));
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

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

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

相关文章

图片上传成功却无法显示:静态资源路径配置问题解析

1、故事的背景 最近&#xff0c;有个学弟做了一个简单的后台管理页面。于是他开始巴拉巴拉撘框架&#xff0c;写代码&#xff0c;一顿操作猛如虎&#xff0c;终于将一个简单的壳子搭建完毕。但是在实现功能&#xff1a;点击头像弹出上传图片进行头像替换的时候&#xff0c;卡壳…

力扣高频SQL 50 题(基础版)第一题

文章目录 力扣高频SQL 50 题&#xff08;基础版&#xff09;第一题1757.可回收且低脂的产品题目说明思路分析实现过程准备数据&#xff1a;实现方式&#xff1a;结果截图&#xff1a; 力扣高频SQL 50 题&#xff08;基础版&#xff09;第一题 1757.可回收且低脂的产品 题目说…

昇思25天学习打卡营第14天 | SSD目标检测

探索SSD目标检测算法 在深入学习SSD&#xff08;Single Shot MultiBox Detector&#xff09;目标检测算法的过程中&#xff0c;我对现代计算机视觉中的目标检测技术有了更加深入的理解。SSD作为一种有效的单阶段目标检测算法&#xff0c;它在准确性和检测速度之间取得了良好的…

HAL库源码移植与使用之RTC时钟

实时时钟(Real Time Clock&#xff0c;RTC)&#xff0c;本质是一个计数器&#xff0c;计数频率常为秒&#xff0c;专门用来记录时间。 普通定时器无法掉电运行&#xff01;但RTC可由VBAT备用电源供电&#xff0c;断电不断时 这里讲F1系列的RTC 可以产生三个中断信号&#xff…

分类损失函数 (一) torch.nn.CrossEntropyLoss()

1、交叉熵 是一种用于衡量两个概率分布之间的距离或相似性的度量方法。机器学习中&#xff0c;交叉熵常用于损失函数&#xff0c;用于评估模型的预测结果和实际标签的差异。公式&#xff1a; y&#xff1a;真是标签的概率分布&#xff0c;y&#xff1a;模型预测的概率分布 …

FPGA实验3:D触发器设计

一、实验目的及要求 熟悉Quartus II 的 VHDL 文本设计简单时序电路的方法&#xff1b; 掌握时序电路的描述方法、波形仿真和测试&#xff0c;特别是时钟信号的特性。 二、实验原理 运用Quartus II 集成环境下的VHDL文本设计方法设计简单时序电路——D触发器&#xff0c;依据…

【Godot4.2】GodotXML插件 - 解析和生成XML

概述 近期在研究基于Godot的XML和SVG解析&#xff0c;并且在昨天&#xff08;2024年7月20日&#xff09;编写了一个简易的SVG文件解析器。 在群友的提示下&#xff0c;知道早就存在GodotXML这样的解析器。所以今天就来测试使用并准备研究学习源代码了。和以往一样&#xff0c…

康康近期的慢SQL(oracle vs 达梦)

近期执行的sql&#xff0c;哪些比较慢&#xff1f; 或者健康检查时搂一眼状态 oracle&#xff1a; --最近3天内的慢sql set lines 200 pages 100 col txt for a65 col sql_id for a13 select a.sql_id,a.cnt,a.pctload,b.sql_text txt from (select * from (select sql_id,co…

MySQL0.MSI方式安装

本机运行环境&#xff1a;Windows10 1.下载 进入MySQL官方下载页面&#xff1a;https://downloads.mysql.com/archives/installer/ 红色箭头&#xff1a;点击选择下载的版本 黄色箭头&#xff1a;点击下载MSI安装包 此次下载选择MySQL8.0.37的MSI安装包 2.安装 下载完毕后…

微信小程序开发:基础架构与配置文件

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

SecureCRT (mac or windows)解决中文显示乱码

中文乱码问题的方法主要包括设置SecureCRT的编码为UTF-8以及设置LANG环境变量为zh_CN.UTF-8。‌ 1.设置SecureCRT的编码为UTF-8&#xff1a;‌ 打开SecureCRT&#xff0c;‌进入Options -> Global Options -> Default Session -> Edit Default Settings-> Appear…

数据结构day3

一、思维导图 二、顺序表实现学生管理系统 //头文件 #ifndef TEST_H #define TEST_H #define MAX_SIZE 100//定义学生类型 typedef struct {char name[20]; //姓名int age; //年龄double score; //分数 }datatype;//定义班级类型 typedef struct {datatype student[MAX…

Linux fork、进程的退出和等待详解

初识fork函数 它从已存在进程中创建一个新进程。新进程为子进程&#xff0c;而原进程为父进程。 #include <unistd.h> pid_t fork(void); 返回值&#xff1a;子进程中返回0&#xff0c;父进程返回子进程id&#xff0c;出错返回-1 最简单的fork使用示例 #include<stdi…

初阶数据结构的实现2 双向链表

1.双向链表 1.1 概念与结构 1.2实现双向链表 1.2.1定义程序目标 #define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include<stdio.h> #include<assert.h> #include<stdlib.h> #include<stdbool.h> typedef int LTDateType; //定义双向链表结构 typ…

list(链表)容器的规则及list的高级排序案例

1.list的基本概念&#xff1a; 功能&#xff1a;将数据进行链式存储 list&#xff08;链表&#xff09;是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接实现的 链表是由一系列节点组成&#xff0c;节点的组成包含存储数据元素的…

秋招提前批:抢占求职先机的绝佳机遇(25届提前批名单公布)

秋招&#xff0c;对于即将毕业的大学生来说&#xff0c;是一场至关重要的求职盛宴。每年的秋季&#xff0c;各大企业纷纷抛出橄榄枝&#xff0c;为应届毕业生提供了众多宝贵的就业机会。然而&#xff0c;在求职的漫漫征途中&#xff0c;秋招是一场关键的战役。而秋招提前批&…

二百四十五、海豚调度器——用DolphinScheduler调度执行复杂的HiveSQL(HQL包含多种海豚无法正确识别的符号)

一、目的 在Hive中完成复杂JSON&#xff0c;既有对象还有数组而且数组中包含数组的解析后&#xff0c;原本以为没啥问题了&#xff0c;结果在DolphinScheduler中调度又出现了大问题&#xff0c;搞了一天、试了很多种方法、死了无数脑细胞&#xff0c;才解决了这个问题&#xf…

fastjson1.2.24 反序列化漏洞复现

fastjson简介 Fastjson 是一个 Java 库&#xff0c;可以将 Java 对象转换为 JSON 格式&#xff0c;当然它也可以将 JSON 字符串转换为 Java 对象。 Fastjson 可以操作任何 Java 对象&#xff0c;即使是一些预先存在的没有源码的对象。 这里json与java对象之间的转换&#xff0…

【GaussDB关键技术原理|高可用】DCF双集群容灾

GaussDB关键技术原理&#xff1a;高性能篇&#xff0c;从GaussDB数据库性能优化系统概述、查询处理综述、高性能关键技术等方面为大家进行了解读&#xff0c;并对高斯数据库性能优化做了总结。本篇将分享GaussDB高可用方面的相关知识&#xff0c;详细介绍GaussDB的DCF与双集群容…