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

rpc grpc

RPC

Remote Procedure Call,远程过程调用,是用来屏蔽分布式计算中的各种调用细节,使得调用远端的方法就像调用本地的一样。

客户端与服务端沟通的过程

  1. 客户端发送数据(以字节流的方式);编码
  2. 服务端接受并解析,根据约定知道要执行什么,然后把结果返回给客户。解码

RPC

  1. RPC就是将上述过程封装下,使其操作更加优化;
  2. 使用一些大家都认可的协议,使其规范化;
  3. 做成一些框架,直接或间接产生利益。

RPC 和 HTTP 区别

RPC 和 HTTP 不是对等的概念。

  • RPC 是一个完整的远程调用方案,它包括了:接口规范 + 序列化反序列化规范 + 通信协议等。
  • HTTP 只是一个通信协议,工作在 OSI 的第七层,不是一个完整的远程调用方案。

RPC是能够基于 HTTP 实现,也可以不基于,基于更下一层的 TCP/ UDP协议。

RPC 原理

  • 调用方为 client,被调用方为 server
    在这里插入图片描述
    ① 服务调用方(client)以本地调用方式调用服务;

② client stub 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;

③ client stub 找到服务地址,并将消息发送到服务端;

④ server 端接收到消息;

⑤ server stub 收到消息后进行解码;

⑥ server stub 根据解码结果调用本地的服务;

⑦ 本地服务执行并将结果返回给 server stub;

⑧ server stub 将返回结果打包成能够进行网络传输的消息体;

⑨ 按地址将消息发送至调用方;

⑩ client 端接收到消息;

⑪ client stub 收到消息并进行解码;

⑫ 调用方得到最终结果。

RPC 接口和传统的 http 接口的区别

传输协议

  • RPC:可以基于TCP协议,也可以基于HTTP协议。
  • HTTP:基于HTTP协议。

传输效率

  • RPC:使用自定义的TCP协议,可以让请求报文体积更小,或者使用HTTP2协议,也可以很好的减少报文的体积,提高传输效率。
  • HTTP:如果是基于HTTP1.1的协议,请求中会包含很多无用的内容,如果是基于HTTP2.0,那么简单的封装以下是可以作为一个RPC来使用的,这时标准RPC框架更多的是服务治理。

服务治理

  • RPC:能做到自动通知,不影响上游。
  • HTTP:需要事先通知,修改Nginx/HAProxy配置。

GRPC

gRPC 是一个高性能的、开源的、通用的 RPC 框架。

  • grpc 只是一个框架,是对rpc的封装,类似的框架还有thrift等。
  • 目标是只需要关心第1步和最后1步,中间的其他步骤统统封装起来,让使用者无需关心。

grpc 解决的 rpc 三大问题

协议约定

gRPC 的协议是 Protocol Buffers,是一种压缩率极高的序列化协议,Google 在 2008 年开源了 Protocol Buffers,支持多种编程语言,所以 gRPC 支持客户端与服务端可以用不同语言实现

传输协议

gRPC 的数据传输用的是 Netty Channel, Netty 是一个高效的基于异步 IO 的网络传输架构。Netty Channel 中,每个 gRPC 请求封装成 HTTP 2.0 的 Stream。

服务发现

gRPC 本身没有提供服务发现的机制,需要通过其他组件。

Protocol Buffs

Protocol Buffss 是谷歌开源的一套成熟的数据结构序列化机制。
在这里插入图片描述

  • 序列化:将数据结构或对象转换成二进制串的过程。
  • 反序列化:将在序列化过程中所产生的二进制串转换成数据结构或者对象的过程。

protobuf 是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。

优势

  1. 序列化后体积相比Json和XML很小,适合网络传输
  2. 支持跨平台多语畜
  3. 消息格式升级和兼容性还不错
  4. 序列化反序列化速度很快

grpc-study

在这里插入图片描述

proto文件编写

hello.proto:

// 这是说明使用的是proto3语法
syntax = "proto3";// 这部分的内容是关于最后生成的go文件是处在哪个目录哪个包中
// . 代表在当前目录生成
// service 代表了生成的go文件的包名是service
option go_package = ".;service";// 然后需要定义一个服务,在这个服务中需要有一个方法,这个方法可以接受客户端的参数,再返回服务端的响应
// 定义了一个service,称为SayHello,这个服务中有一个rpc方法,名为SayHello
// 这个方法会发送一个HelloRequest,然后返回一个HelloResponse
service SayHello {rpc SayHello(HelloRequest) returns (HelloResponse) {}
}// message关键字,可以理解为Golang中的结构体
// 这里比较特别的是变量后面的“赋值”。注意,这里并不是赋值,而是在定义这个变量在这个message中的位置。
message HelloRequest {string requestName = 1;
//  int64 age = 2;
}message HelloResponse {string responseMsg = 1;
}

执行命令

protoc --go_out=. hello.proto
protoc --go-grpc_out=. hello.proto

在这里插入图片描述

生成 hello_grpc.pb.go 文件和 hello.pb.go 文件。

proto文件介绍

message

  • protobuf 中定义一个消息类型式是通过关键字 message 字段指定的。
  • 消息就是需要传输的数据格式的定义。
  • message 关键字类似于 C++ 中的 class,JAVA 中的 class,go 中的 struct。
  • 在消息中承载的数据分别对应于每一个字段,其中每个字段都有一个名字和一种类型。
  • 一个 proto 文件中可以定义多个消息类型。

hello.proto

// message关键字,可以理解为Golang中的结构体
// 这里比较特别的是变量后面的“赋值”。
// 注意,这里并不是赋值,而是在定义这个变量在这个message中的位置。
message HelloRequest {string requestName = 1;
//  int64 age = 2;
}message HelloResponse {string responseMsg = 1;
}

字段规则

  • required:消息体中必填字段,不设置会导致编码异常。在 protobuf2 中使用,在 protobuf3 中被删去。
  • optional:消息体中可选字段。protobuf3 没有了required,optional 等说明关键字,都默认为optional 。
  • repeate:消息体中可重复字段,重复的值的顺序会被保留在go中重复的会被定义为切片。

hello.proto

message HelloRequest {string requestName = 1;int64 age = 2;repeated string name = 3;
}

执行 protoc --go_out=. hello.proto
hello.pb.go

type HelloRequest struct {state         protoimpl.MessageState `protogen:"open.v1"`RequestName   string                 `protobuf:"bytes,1,opt,name=requestName,proto3" json:"requestName,omitempty"`Age           int64                  `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"`Name          []string               `protobuf:"bytes,3,rep,name=name,proto3" json:"name,omitempty"`unknownFields protoimpl.UnknownFieldssizeCache     protoimpl.SizeCache
}

消息号

在消息体的定义中,每个字段都必须要有一个唯一的标识号,标识号是 [1,2^29-1] 范围内的一个整数

嵌套消息

可以在其他消息类型中定义、使用消息类型。

// Person 消息定义在 PersonInfo 消息内
message PersonInfo {message Person{string name = 1;int32 height = 2;repeated int32 weight = 3;
}
repeated Person info = 1;

如果要在它的父消息类型的外部重用这个消息类型,需要Personlnfo.Person的形式使用它。

message PersonMessage {message Person{PersonInfo.Person info = 1;
}

服务定义

如果想要将消息类型用在 RPC 系统中,可以在 .proto 文件中定义一个 RPC 服务接口,protocol buffer编译器将会根据所选择的不同语言生成服务接口代码及存根。

service searchservicef # rpc 服务函数名 (参数) 返回 (返回参数)rpc search(searchRequest) returns (searchResponse)
}

定义了一个RPC服务,该方法接受 SearchRequest 返回 SearchResponse 。

服务端编写

  • 创建 gRPC Server 对象,可以理解为它是 Server 端的抽象对象。
  • 将 server (其包含需要被调用的服务端接口) 注册到 gRPC Server 的内部注册中心。
    这样可以在接受到请求时,通过内部的服务发现,发现该服务端接口并转接进行逻辑处理。
  • 创建 Listen,监听 TCP 端口。
  • gRPC Server开始 lis.Accept,直到 Stop

hello-server\main.go

package mainimport ("context""fmt""google.golang.org/grpc"pb "grpc-study/hello-server/proto""net"
)// hello server
type server struct {pb.UnimplementedSayHelloServer
}func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {return &pb.HelloResponse{ResponseMsg: "hello " + req.RequestName}, nil
}func main() {// 开启端口listen, _ := net.Listen("tcp", ":9090")// 创建grpc服务grpcServer := grpc.NewServer()// 在grpc服务端中去注册我们自己编写的服务pb.RegisterSayHelloServer(grpcServer, &server{})// 启动服务err := grpcServer.Serve(listen)if err != nil {fmt.Printf("failed to serve: %v", err)}
}

客户端编写

  • 创建与给定目标 (服务端) 的连接交互。
  • 创建 server的客户端对象。
  • 发送 RPC 请求,等待同步响应,得到回调后返回响应结果。
  • 输出响应结果。

hello-clinent\main.go

package mainimport ("context""fmt""google.golang.org/grpc""google.golang.org/grpc/credentials/insecure"pb "grpc-study/hello-server/proto""log"
)func main() {// 连接到server端,此处禁用安全传输,没有加密和验证conn, err := grpc.Dial("127.0.0.1:9090", grpc.WithTransportCredentials(insecure.NewCredentials()))if err != nil {log.Fatalf("did not connect: %v", err)}defer conn.Close()// 建立连接clinent := pb.NewSayHelloClient(conn)// 执行rpc调用(这个方法在服务器端来实现并返回结果)resp, _ := clinent.SayHello(context.Background(), &pb.HelloRequest{RequestName: "Shigy"})fmt.Println(resp.GetResponseMsg())
}

运行结果

先运行服务端再运行客户端:

在这里插入图片描述

认证-安全传输

gRPC 是一个典型的 C/S 模型,需要开发客户端和服务端,客户端与服务端需要达成协议,使用某一个确认的传输协议来传输数据,gRPC 通常默认是使用 protobuf 来作为传输协议,当然也是可以使用其他自定义的。
在这里插入图片描述

客户端与服务端要通信之前,客户端如何知道自己的数据是发给哪一个明确的服务端呢?反过来,服务端是不是也需要有一种方式来弄个清楚自己的数据要返回给谁呢?
那么就不得不提 gRPC 的认证。
此处说到的认证,不是用户的身份认证,而是指多个 server 和多个 client 之间,如何识别对方是谁,并且可以安全的进行数据传输

  • SSL/TLS 认证方式 (采用 http2 协议)
  • 基于 Token 的认证方式 (基于安全连接)
  • 不采用任何措施的连接,这是不安全的连接 (默认采用 http1)
  • 自定义的身份认证

客户端和服务端之间调用,可以通过加入证书的方式,实现调用的安全性。

SSL/TLS认证方式

TLS (Transport Layer Security,安全传输层),TLS 是建立在传输层 TCP 协议之上的协议,服务于应用层,它的前身是 SSL (Secure Socket Layer 安全套接字层),它实现了将应用层的报文进行加密后再交由 TCP 进行传输的功能。

TLS 协议主要解决如下三个网络安全问题。

  1. 保密 (message privacy),保密通过加密 encryption 实现,所有信息都加密传输,第三方无法嗅探;
  2. 完整性 (message integrity),通过 MAC 校验机制,一旦被篡改,通信双方会立刻发现;
  3. 认证(mutual authentication),双方认证,双方都可以配备证书,防止身份被冒充;

生产环境可以购买证书(eg. 阿里云、腾讯)或者使用一些平台发放的免费证书(eg. 宝塔)

  • key:服务器上的私钥文件,用于对发送给客户端数据的加密,以及对从客户端接收到数据的解密。
  • csr:证书签名请求文件,用于提交给证书颁发机构(CA)对证书签名。
  • crt:由证书颁发机构(CA)签名后的证书,或者是开发者自签名的证书,包含证书持有人的信息,持有人的公钥,以及签署者的签名等信息。
  • pem:是基于 Base64 编码的证书格式,扩展名包括 PEM、CRT 和 CER 。

首先通过 openssl 生成证书和私钥。

  1. 下载便捷安装包 https://slproweb.com/products/Win32OpenSSL.html 一直下一步即可
  2. 配置环境变量(路径到bin)
  3. 命令行测试 openssl

生成证书

  • 新建目录 key,在该目录下执行以下命令:
    在这里插入图片描述
    在这里插入图片描述
  • 更改 openssl.cnf
  1. openssl.cfg 复制到 key 目录下
    在这里插入图片描述在这里插入图片描述

  2. 找到 [CA_default],打开 copy_extensions = copy (就是把前面的#去掉)
    在这里插入图片描述

  3. 找到 [ reg ],打开 reg_extensions = v3_req ...
    在这里插入图片描述

  4. 找到 [v3_reg],添加 subjectAltName =@alt_names
    在这里插入图片描述

  5. 添加新的标签 [ alt_names ],和标签字段 DNS.1 = *.kuangstudy.com
    在这里插入图片描述

  • key 目录下执行以下命令:
  1. 生成证书私钥 test.key
openssl genpkey -algorithm RSA -out test.key
  1. 通过私钥 test.key 生成证书请求文件 test.csr (注意cfg和cnf)
openssl req -new -nodes -key test.key -out test.csr -days 3650 -subj "/C=cn/OU=myorg/O=mycomp/CN=myname" -config ./openssl.cfg -extensions v3_req

test.csr 是上面生成的证书请求文件。ca.crt/server,key 是 CA证书文件和 key,用来对 test.csr 进行签名认证。这两个文件在第一部分生成。

  1. 生成 SAN证书 pem
openssl x509 -req -days 365 -in test.csr -out test.pem -CA server.crt -CAkey  server.key -CAcreateserial -extfile ./openssl.cfg -extensions v3_req

在这里插入图片描述

服务端

hello-server\main.go

package mainimport ("context""fmt""google.golang.org/grpc""google.golang.org/grpc/credentials"pb "grpc-study/hello-server/proto""net"
)// hello server
type server struct {pb.UnimplementedSayHelloServer
}func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {return &pb.HelloResponse{ResponseMsg: "hello " + req.RequestName}, nil
}func main() {// TSL认证// 两个参数分别足 cretFile ,keyFile// 自答名证书文件和私钥文件creds, _ := credentials.NewServerTLSFromFile("C:\\workspace4Goland\\grpc-study\\key\\test.pem", "C:\\workspace4Goland\\grpc-study\\key\\test.key")// 开启端口listen, _ := net.Listen("tcp", ":9090")// 创建grpc服务grpcServer := grpc.NewServer(grpc.Creds(creds))// 在grpc服务端中去注册我们自己编写的服务pb.RegisterSayHelloServer(grpcServer, &server{})// 启动服务err := grpcServer.Serve(listen)if err != nil {fmt.Printf("failed to serve: %v", err)}
}

客户端

hello-clinent\main.go

package mainimport ("context""fmt""google.golang.org/grpc""google.golang.org/grpc/credentials"pb "grpc-study/hello-server/proto""log"
)func main() {creds, _ := credentials.NewClientTLSFromFile("C:\\workspace4Goland\\grpc-study\\key\\test.pem", "*.kuangstudy.com")// 连接到server端,此处禁用安全传输,没有加密和验证conn, err := grpc.Dial("127.0.0.1:9090", grpc.WithTransportCredentials(creds))if err != nil {log.Fatalf("did not connect: %v", err)}defer conn.Close()// 建立连接clinent := pb.NewSayHelloClient(conn)// 执行rpc调用(这个方法在服务器端来实现并返回结果)resp, _ := clinent.SayHello(context.Background(), &pb.HelloRequest{RequestName: "Shigy"})fmt.Println(resp.GetResponseMsg())
}

Token认证

先看一个 gRPC 提供的一个接口,这个接口中有两个方法,接口位于 credentials 包下,这个接口需要客户端来实现

type PerRPCCredentials interface {GetRequestMetadata(ctx context.Context, uri ...string)(map[string]string, error)RequireTransportSecurity bool
}
  • 第一个方法作用是获取元数据信息,也就是客户端提供的key,value对,context 用于控制超时和取消,uri 是请求入口处的 uri
  • 第二个方法的作用是否需要基于 TLS 认证进行安全传输,如果返回值是 true,则必须加上 TLS 验证,返回值是 false 则不用

gRPC 将各种认证方式浓缩统一到一个凭证(credentials)上,可以单独使用一种凭证,比如只使用 TLS 凭证或者只使用自定义凭证,也可以多种凭证组合,gRPC 提供统一的 API 验证机制,使研发人员使用方便,这也是 gRPC 设计的巧妙之处。

相关文章:

rpc grpc

RPC Remote Procedure Call,远程过程调用,是用来屏蔽分布式计算中的各种调用细节,使得调用远端的方法就像调用本地的一样。 客户端与服务端沟通的过程 客户端发送数据(以字节流的方式);(编码)服务端接受…...

AI赋能铁道安全巡检探索智能巡检新时代,基于YOLOv7全系列【tiny/l/x】参数模型开发构建铁路轨道场景下轨道上人员行为异常检测预警系统

在交通强国的战略引领下,中国铁路网如巨龙般纵贯大江南北,将五湖四海紧密相连,极大地促进了人员出行与物流运输的便捷性。然而,随着铁路线路的不断扩展,管理层面的安全问题也日益凸显。历史上,多起与铁路相…...

Kubernetes安全:集群保护的最佳实践

随着容器化技术的广泛应用,Kubernetes已经成为企业IT基础设施的重要组成部分。然而,Kubernetes集群的复杂性也带来了独特的安全挑战。如何在动态变化的云原生环境中保障集群的安全性,成为每一位运维工程师和安全专家关注的焦点。本文将详细探…...

R+VIC模型融合实践技术应用及未来气候变化模型预测

在气候变化问题日益严重的今天,水文模型在防洪规划,未来预测等方面发挥着不可替代的重要作用。目前,无论是工程实践或是科学研究中都存在很多著名的水文模型如SWAT/HSPF/HEC-HMS等。虽然,这些软件有各自的优点;但是&am…...

前端开发:混合技术栈的应用

目录 前言 混合技术栈的优势 移动端开发嵌入H5 1、场景描述 2、实现方法 3、源码示例 OC项目嵌入Swift的使用 1、场景描述 2、实现方法 3、源码示例 HarmonyOS开发中嵌入WebView 1、权限配置 2、加载网页 结束语 前言 随着技术的不断进步,软件开发领域…...

Machine Learning: 十大基本机器学习算法

机器学习算法分类:监督学习、无监督学习、强化学习 基本的机器学习算法: 线性回归、支持向量机(SVM)、最近邻居(KNN)、逻辑回归、决策树、k平均、随机森林、朴素贝叶斯、降维、梯度增强。 机器学习算法大致可以分为三类: 监督学习算法 (Sup…...

react实现一个列表的拖拽排序(react实现拖拽)

需求场景: 我的项目里需要实现一个垂直列表的拖拽排序,效果图如下图: 技术调研: 借用antd Table实现: 我的项目里使用了antd,antd表格有一个示例还是挺像的,本来我想用Table实现&#xff0…...

通过mybatis的拦截器对SQL进行打标

1、背景 在我们开发的过程中,一般需要编写各种SQL语句,万一生产环境出现了慢查询,那么我们如何快速定位到底是程序中的那个SQL出现的问题呢? 2、解决方案 如果我们的数据访问层使用的是mybatis的话,那么我们可以通过…...

【MySQL】MySQL服务器——mysqld

1.MySQL服务器 是名为 mysqld 的数据库服务器程序,和“主机”(host)不一样是一个多线程的单进程管理对磁盘和内存中数据库的访问支持并发的客户端连接支持多个存储引擎,常见的存储引擎包括InnoDB、MyISAM、Memory、Archive支持事…...

JAVA面试_进阶部分_Java JVM:垃圾回收(GC 在什么时候,对什么东西,做了什么事情)

在什么时候: 首先需要知道,GC又分为minor GC 和 Full GC(major GC)。Java堆内存分为新生代和老年代,新生代 中又分为1个eden区和两个Survior区域。 一般情况下,新创建的对象都会被分配到eden区&#xff…...

【探秘海洋伤痕】海洋环境污染损害的警世启示

在地球这个蓝色星球上,广袤无垠的海洋孕育了无数生命,支撑着地球的生态平衡与人类的生存发展。然而,随着工业化和现代化的加速,海洋环境遭受的伤害日益严重,海洋环境污染损害成为了我们必须直面的严峻问题。本文将带您…...

过滤器(Filter)与拦截器(Interceptor)

在Java Web开发中,**拦截器(Interceptor)和过滤器(Filter)**都用于在请求处理过程中拦截和处理HTTP请求或响应,但它们有不同的应用场景和工作原理。下面将详细解释它们的区别,并提供代码演示。 …...

智慧城市运行管理服务平台建设方案

随着城市化的快速发展,城市运行管理面临着前所未有的挑战。智慧城市的概念应运而生,旨在通过信息技术手段提升城市管理效率和居民生活质量。智慧城市运行管理服务平台作为智慧城市建设的核心组成部分,其建设方案的科学性和前瞻性至关重要。 …...

Java是怎么解决并发问题的?

Happens-Before规则(前言) Happens-Before规则 是 Java 内存模型(JMM)中用于定义线程间操作可见性和有序性的一种规范。它的核心目的是:确保一个线程的某些操作结果对其他线程是可见的,并且这些操作在时间上的顺序不会被重排序破…...

使用 Chrome Flags 设置(适用于 HTTP 站点开发)

使用 Chrome Flags 设置(适用于 HTTP 站点开发) 在 Chrome 地址栏输入:chrome://flags/在搜索框输入 “Insecure origins” 或 “Allow invalid certificates”。找到 “Insecure origins treated as secure” 选项(或者 #allow-…...

解锁 AI 开发的无限可能:邀请您加入 coze-sharp 开源项目

大家好!今天我要向大家介绍一个充满潜力的开源项目——coze-sharp!这是一个基于 C# 开发的 Coze 客户端,旨在帮助开发者轻松接入 Coze AI 平台,打造智能应用。项目地址在这里:https://github.com/zhulige/coze-sharp&a…...

【Swift】面向协议编程之HelloWorld

定义一个协议(protocol),swift 中可以对protocol 进行扩展(extension)通过协议的扩展可以对函数有默认的实现 protocol Sleepable {func sleep() } protocol Eatable {func eat() } extension Eatable {func eat() {print("eat food")} }在类(class)或结…...

图神经网络学习笔记—纯 PyTorch 中的多 GPU 训练(专题十二)

对于许多大规模的真实数据集,可能需要在多个 GPU 上进行扩展训练。本教程将介绍如何通过 torch.nn.parallel.DistributedDataParallel 在 PyG 和 PyTorch 中设置多 GPU 训练管道,而无需任何其他第三方库(如 PyTorch Lightning)。请注意,此方法基于数据并行。这意味着每个 …...

Linux云计算SRE-第二十周

完成ELK综合案例里面的实验,搭建完整的环境 一、 1、安装nginx和filebeat,配置node0(10.0.0.100),node1(10.0.0.110),node2(10.0.0.120),采用filebeat收集nignx日志。 #node0、node1、node2采用以下相同方式收集ngin…...

springcloud gateway搭建及动态获取nacos注册的服务信息信息

前言 Spring Cloud Gateway 通过集成 Nacos 服务发现,可以动态获取注册到 Nacos 的微服务实例信息,并根据服务名(Service Name)自动生成路由规则或手动配置路由规则,实现请求的动态路由和负载均衡。 一个最简单的网关就…...

SSM基础专项复习6——Spring框架AOP(3)

系列文章 1、SSM基础专项复习1——SSM项目整合-CSDN博客 2、SSM基础专项复习2——Spring 框架(1)-CSDN博客 3、SSM基础专项复习3——Spring框架(2)-CSDN博客 4、SSM基础专项复习4——Maven项目管理工具(1&#xff…...

【嵌入式linux】网口和USB热插拔检测

在Linux常常需要对网口和USB等外设接口进行插拔检测,从而执行部分初始化操作。下面简要介绍Linux的Netlink机制,并在C程序中使用Linux的Netlink机制完成网口和USB口插拔检测。 Netlink 是 Linux 内核与用户空间进程通信的一种机制,主要用于内…...

C++(13)—类和对象(中) ③拷贝构造函数

文章目录 一、拷贝构造函数的基本概念1.1 什么是拷贝构造函数?1.2 拷贝构造函数的调用场景 二、拷贝构造函数的核心特性2.1 拷贝构造函数的参数2.2 默认拷贝构造函数 三、深拷贝与浅拷贝3.1 浅拷贝的问题 四、拷贝构造函数的实际应用4.1 何时需要显式定义拷贝构造函…...

【GPT入门】第17课 RAG向量检索分类、原理与优化

【GPT入门】第16课 RAG向量检索分类、原理与优化 1.向量检索概念1.1 文本检索的两类方式1.2 向量的定义1.3 文本向量(Text Embeddings)1.4 文本向量如何得到1.5 向量间相似度计算1.6 向量数据库功能对比1.7 open ai发布的两个向量模型2.向量数据库1.8 向量检索的优化3.检索后…...

Operator <=> (spaceship operator)

operator <>动机 在C20以前定义比较运算符&#xff1a;其他比较运算符基于<和实现 struct Type {int value;// 相等运算符friend bool operator(const Type& a, const Type& b) {return a.value b.value;}// 不等运算符friend bool operator!(const Type&a…...

队列的简单例题

题目如下 模拟队列 首先你要明白队列的话 只有队尾才能进行新增&#xff0c;也就是入队 只有队首才能出队&#xff0c;也就是删除 队首队尾指针一开始默认都是0 相当于队列中一开始是有一个元素的就是 0的位置 队首指针head0 队尾指针tail0 1.入队也就是队尾要先赋值&#xf…...

Calibre-Web-Automated:打造你的私人图书馆

有没有小伙伴在工作、学习或生活中喜欢保存一些书籍或PDF文件&#xff0c;结果过一段时间想找的时候却怎么也找不到&#xff0c;最后只能无奈放弃&#xff1f;你是否已经厌倦了手动管理电子书的繁琐&#xff1f;是否梦想拥有一个私人图书馆&#xff0c;随时随地都能轻松访问自己…...

第27周JavaSpringboot 前后端联调

电商前后端联调课程笔记 一、项目启动与环境搭建 1.1 项目启动 在学习电商项目的前后端联调之前&#xff0c;需要先掌握如何启动项目。项目启动是整个开发流程的基础&#xff0c;只有成功启动项目&#xff0c;才能进行后续的开发与调试工作。 1.1.1 环境安装 环境安装是项…...

【实战ES】实战 Elasticsearch:快速上手与深度实践-8.2.1AWS OpenSearch无服务器方案

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 8.2.1AWS OpenSearch 无服务器方案深度解析与实践指南1. Serverless架构的核心价值与行业趋势1.1 传统Elasticsearch集群的运维挑战1.2 Serverless技术演进路线技术特性对比…...

鸿蒙开发者社区资源的重要性

鸿蒙系统&#xff0c;作为华为公司自主研发的操作系统&#xff0c;旨在为各类智能设备提供统一的平台。它不仅支持手机、平板电脑等移动设备&#xff0c;还涵盖了物联网&#xff08;IoT&#xff09;设备和其他智能家居产品。鸿蒙系统的开发环境和工具链对于开发者来说至关重要&…...

【QT】事件系统入门——QEvent 基础与示例

一、事件介绍 事件是 应用程序内部或者外部产生的事情或者动作的统称 在 Qt 中使用一个对象来表示一个事件。所有的 Qt 事件均继承于抽象类 QEvent。事件是由系统或者 Qt 平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘&#xff0c;或者是窗口需要重新绘制的时候&…...

⚡️Jolt -- 通过JSON配置来处理复杂数据转换的工具

简介&#xff1a;一个能够通过JSON配置&#xff08;特定的语法&#xff09;来处理复杂数据转换的工具。 比如将API响应转换为内部系统所需的格式&#xff0c;或者处理来自不同来源的数据结构差异。例如&#xff0c;将嵌套的JSON结构扁平化&#xff0c;或者重命名字段&#xff0…...

2025-03-13 禅修-错误的做法

摘要: 2025-03-13 禅修-错误的做法 禅修-错误的做法 我们今天的课程是这个禅修防误。主要是有一些我们所明令禁止的。在整个禅修过程中&#xff0c;会对我们禅修出现一些弊端的这部分&#xff0c;我们会给大家介绍。第一&#xff0c;在禅修中要防止自由联想&#xff0c;防止幻…...

uni-app学习笔记——自定义模板

一、流程 1.这是一个硬性的流程&#xff0c;只要按照如此程序化就可以实现 二、步骤 1.第一步 2.第二步 3.第三步 4.每一次新建页面&#xff0c;都如第二步一样&#xff1b;可以选择自定义的模版&#xff08;vue3Setup——这是我自己的模版&#xff09;&#xff0c;第二步的…...

【医院绩效管理专题】8.医院绩效数据的收集与整理方法:洞察现状,引领未来

医院成本核算、绩效管理、运营统计、内部控制、管理会计专题索引 一、引言 在当今医疗行业竞争日益激烈的背景下,医院绩效管理已成为提升医疗服务质量、优化运营效率、增强综合竞争力的关键因素。而绩效数据的收集与整理作为绩效管理的基础环节,其科学性、准确性和完整性直…...

麒麟系统如何安装Anaconda

在银河麒麟操作系统&#xff08;Kylin OS&#xff09;中安装 Anaconda 的步骤相对简单&#xff0c;以下是基于搜索结果整理的详细安装指南&#xff1a; 步骤 1&#xff1a;下载 Anaconda 安装脚本 打开浏览器&#xff0c;访问 Anaconda 官方下载页面。选择适合 Linux 系统的安…...

Linux网络套接字编程——UDP服务器

Linux网络套接字编程——创建并绑定-CSDN博客 前面已经介绍了网络套接字的创建和绑定&#xff0c;这篇文章会通过UDP套接字实现一个UDP服务器。 先介绍将使用的接口。 recvfrom ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr,…...

deepseek+kimi做ppt教程记录

1.首先注册deepseek和kimi deepseek官网&#xff1a;https://chat.deepseek.com/ kimi官网&#xff1a;https://kimi.moonshot.cn/ 以下以一篇工作总结报告为例 2.使用deepseek生成ppt大纲 让deepseek生成kimi生成ppt所需要的内容时&#xff0c;需要注意提示词内容&#xff0c;…...

Cursor 终极使用指南:从零开始走向AI编程

Cursor 终极使用指南&#xff1a;从零开始走向AI编程 问什么是cursor? mindmaproot(Cursor核心功能)智能编码代码生成自动补全错误修复项目管理多窗口布局版本控制终端集成个性设置主题定制快捷键配置插件扩展AI协作对话编程知识检索文档生成前些天发现了一个巨牛的人工智能学…...

TiDB 观测性解读(一)丨索引观测:快速识别无用索引与低效索

导读 可观测性已经成为分布式系统成功运行的关键组成部分。如何借助多样、全面的数据&#xff0c;让架构师更简单、高效地定位问题、分析问题、解决问题&#xff0c;已经成为业内的一个技术焦点。本系列文章将深入解读 TiDB 的关键参数&#xff0c;帮助大家更好地观测系统的状…...

批量将 Excel 文档中的图片提取到文件夹

前面我们介绍过如何批量删除 Excel 文档中的所有图片或者指定的图片&#xff0c;其中就需要用到批量提取 Excel 文档中图片的操作。我们如何才能够将 Excel 文档中的图片快速的提取出来呢&#xff1f;其实单个 Excel 文档中的图片提取到文件夹中是有多种方法可以完成的&#xf…...

postgresql 数据库使用

目录 索引 查看索引 创建 删除索引 修改数据库时区 索引 查看索引 select * from pg_indexes where tablenamet_table_data; 或者 select * from pg_statio_all_indexes where relnamet_table_data; 创建 CREATE INDEX ix_table_data_time ON t_table_data (id, crea…...

怎样进行相关论文的调研——How to conduct research on relevant papers?

怎样进行相关论文的调研 写在前面1.打开Web of Science2.检索同类表达3.构建“检索式”什么是“检索式” 参考内容 写在前面 偶然间刷到一篇知乎文章&#xff0c;顺着文章的推荐看了钟澄老师的科研论和在B站上的教学视频&#xff0c;深入了解后发现读文章还有这么多讲究&#…...

蓝桥杯备赛-基础练习 day1

1、闰年判断 问题描述 给定一个年份&#xff0c;判断这一年是不是闰年。 当以下情况之一满足时&#xff0c;这一年是闰年:1.年份是4的倍数而不是100的倍数 2&#xff0e;年份是400的倍数。 其他的年份都不是闰年。 输入格式 输入包含一个…...

本地算力部署大模型详细流程(一)

1、版本选择 本地部署就是自己部署deepseek模型&#xff0c;使用本地的算力。 主要瓶颈&#xff1a;内存显存的大小。特点&#xff1a;此方案不用联网。适合&#xff1a;有数据隐私方面担忧的或者保密单位根本就不能上网的。 2、部署过程 比较流行的是使用ollama&#xff1a;ht…...

便利店商品推荐数字大屏:基于python和streamlit

基于python和streamlit实现的便利店商品推荐大屏&#xff0c;针对选择困难症消费者。 import streamlit as st import pandas as pd import numpy as np import altair as alt from datetime import datetime, timedelta import time# 模拟数据生成 def generate_data():np.ra…...

机器视觉工程师红外相机的选择:红外长波工业相机和短波红外工业相机玄机大总结

红外长波(LWIR)和短波(SWIR)工业相机在原理、应用场景和技术特点上有显著差异。以下是它们的对比分析: 1. 波长范围与成像原理 2. 技术特点 3. 典型应用场景 4. 优缺点对比 LWIR优势: 无需光照,适用于完全黑暗环境。 直接反映物体温度分布。 对烟雾、灰尘穿透能力强。…...

AI重构SEO关键词布局

内容概要 在搜索引擎优化&#xff08;SEO&#xff09;领域&#xff0c;AI技术的深度应用正在颠覆传统关键词布局逻辑。通过机器学习算法与语义分析模型&#xff0c;智能系统能够实时解析海量搜索数据&#xff0c;构建动态词库并精准捕捉用户意图。相较于依赖人工经验的关键词筛…...

c语言经典基础编程题

c语言经典基础编程题 一、输出输出1.1温度输出1.2排齐数据1.3进制转换 二、选择分支2.1求最大值2.2成绩评定2.3分段函数求值2.4 利润计算2.5判断闰年2.6二次方程根 三、循环结构3.1倒数求和3.2最大数3.3判断素数3.4判断完全数3.5打印菱形&#x1f680;&#x1f680;&#x1f68…...

【每日学点HarmonyOS Next知识】防截屏、作用域问题、观察器问题、对话框关闭、判断对象包含某个字段

1、HarmonyOS 防截屏功能如何实现&#xff1f; 防截屏功能如何实现 参考demo&#xff1a; aboutToDisappear(): void {let windowClass: window.Window | undefined undefined;window.getLastWindow(getContext(this)).then((win) > {this.window win }) window.getLas…...