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

【gRPC学习】使用go学习gRPC

个人博客:Sekyoro的博客小屋
个人网站:Proanimer的个人网站
RPC是远程调用,而google实现了grpc比较方便地实现了远程调用,gRPC是一个现代的开源远程过程调用(RPC)框架

概念介绍

在gRPC中,客户端应用程序可以直接调用另一台计算机上的服务器应用程序上的方法,就好像它是本地对象一样。

远程过程调用是一个分布式计算的客户端-服务器(Client/Server)的例子,它简单而又广受欢迎。
远程过程调用总是由客户端对服务器发出一个执行若干过程请求,并用客户端提供的参数。执行结果将返回给客户端。
由于存在各式各样的变体和细节差异,对应地派生了各式远程过程调用协议,而且它们并不互相兼容。

为了允许不同的客户端均能访问服务器,许多标准化的 RPC 系统应运而生了。其中大部分采用接口描述语言(Interface Description Language,IDL),方便跨平台的远程过程调用

与许多RPC系统一样,gRPC基于定义服务的思想,指定可以通过其参数和返回类型远程调用的方法。在服务器端,服务器实现了这个接口,并运行gRPC服务器来处理客户端调用。在客户端,客户端有一个stub(在某些语言中称为客户端),它提供与服务器相同的方法。

它具有许多特性

  1. 强大的IDL特性
    RPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议,性能出众,得到了广泛的应用。
  2. 支持多种语言
    支持C++、Java、Go、Python、Ruby、C#、Node.js、Android Java、Objective-C、PHP等编程语言。
  3. 基于HTTP/2标准设计

在这里插入图片描述

默认情况下,gRPC使用Protocol Buffers,这是谷歌成熟的开源机制,用于序列化结构化数据(尽管它可以与JSON等其他数据格式一起使用)

与REST差异

RPC 的消息传输可以通过 TCP、UDP 或者 HTTP等,所以有时候我们称之为 RPC over TCP、 RPC over HTTP。

RPC 通过 HTTP 传输消息的时候和 RESTful的架构是类似的,但是也有不同。

  • gRPC使用HTTP/2,而REST使用HTTP1.1
  • gRPC使用协议缓冲区数据格式,而不是REST API中通常使用的标准JSON数据格式
  • 使用gRPC,可以利用HTTP/2功能,如服务器端流式传输、客户端流式传输,甚至双向流式传输

首先 RPC 的客户端和服务器端师紧耦合的,客户端需要知道调用的过程的名字,过程的参数以及它们的类型、顺序等。一旦服务器更改了过程的实现,客户端的实现很容易出问题。RESTful基于 http的语义操作资源,参数的顺序一般没有关系,也很容易的通过代理转换链接和资源位置,从这一点上来说,RESTful 更灵活。

其次,它们操作的对象不一样。 RPC 操作的是方法和过程,它要操作的是方法对象。 RESTful 操作的是资源(resource),而不是方法。

第三,RESTful执行的是对资源的操作,增加、查找、修改和删除等,主要是CURD,所以如果你要实现一个特定目的的操作,比如为名字姓张的学生的数学成绩都加上10这样的操作,
RESTful的API设计起来就不是那么直观或者有意义。在这种情况下, RPC的实现更有意义,它可以实现一个直接的方法方法供客户端调用

RPC over TCP可以通过长连接减少连接的建立所产生的花费,在调用次数非常巨大的时候(这是目前互联网公司经常遇到的情况,大并发的情况下),这个花费影响是非常巨大的。
当然 RESTful 也可以通过 keep-alive 实现长连接, 但是它最大的一个问题是它的request-response模型是阻塞的 (http1.0和 http1.1, http 2.0没这个问题),
发送一个请求后只有等到response返回才能发送第二个请求 (有些http server实现了pipeling的功能,但不是标配), RPC的实现没有这个限制。

其他RPC框架

目前的 RPC 框架大致有两种不同的侧重方向,一种偏重于服务治理,另一种偏重于跨语言调用

服务治理型的 RPC 框架有Alibabs Dubbo、Motan 等,这类的 RPC 框架的特点是功能丰富,提供高性能的远程调用以及服务发现和治理功能,适用于大型服务的微服务化拆分以及管理,对于特定语言(Java)的项目可以十分友好的透明化接入。但缺点是语言耦合度较高,跨语言支持难度较大。

跨语言调用型的 RPC 框架有 Thrift、gRPC、Hessian、Finagle 等,这一类的 RPC 框架重点关注于服务的跨语言调用,能够支持大部分的语言进行语言无关的调用,非常适合于为不同语言提供通用远程服务的场景。但这类框架没有服务发现相关机制,实际使用时一般需要代理层进行请求转发和负载均衡策略控制。

thrift是Apache的一个跨语言的高性能的服务框架,也得到了广泛的应用。它的功能类似 gRPC, 支持跨语言,不支持服务治理。

rpcx 是一个分布式的Go语言的 RPC 框架,支持Zookepper、etcd、consul多种服务发现方式,多种服务路由方式, 是目前性能最好的 RPC 框架之一

使用protobuf

定义要在proto文件中序列化的数据的结构:这是一个扩展名为.proto的普通文本文件。协议缓冲区数据被构造为消息,其中每个消息都是一个包含一系列名值对(称为字段)的信息的小逻辑记录。

message Person {string name = 1;int32 id = 2;bool has_ponycopter = 3;
}

指定了数据结构,就可以使用协议缓冲区编译器protoc从proto定义中生成首选语言的数据访问类.

它们为每个字段提供了简单的访问器,如name()和set_name(),以及将整个结构序列化到原始字节/从原始字节解析整个结构的方法。

因此,例如,如果选择的语言是C++,那么在上面的示例中运行编译器将生成一个名为Person的类。然后,您可以在应用程序中使用此类来填充、序列化和检索Person协议缓冲区消息。

gRPC使用protoc和一个特殊的gRPC插件从proto文件中生成代码:可以获得生成的gRPC客户端和服务器代码,以及用于填充、序列化和检索消息类型的常规协议缓冲区代码。(截至目前protobuf最新版本是v3)

gRPC in Go

下载protoc

虽然不是强制性的,但gRPC应用程序通常利用proto buffer进行服务定义和数据序列化。

Releases · protocolbuffers/protobuf (github.com)

protoc用于编译.proto文件,其中包含服务和消息定义,Linux或Mac直接使用对应包管理器下载即可

apt install -y protobuf-compiler
protoc --version  # Ensure compiler version is 3+

Windows在github上下载二进制包Releases · protocolbuffers/protobuf (github.com)

protocol compiler的Go插件

下载protoc-go-gen
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28

下载zip的文件

git clone -b v1.60.1 --depth 1 https://github.com/grpc/grpc-go
proto文件

下面定义了服务

// Interface exported by the server.
service RouteGuide {// A simple RPC.//// Obtains the feature at a given position.//// A feature with an empty name is returned if there's no feature at the given// position.rpc GetFeature(Point) returns (Feature) {}// A server-to-client streaming RPC.//// Obtains the Features available within the given Rectangle.  Results are// streamed rather than returned at once (e.g. in a response message with a// repeated field), as the rectangle may cover a large area and contain a// huge number of features.rpc ListFeatures(Rectangle) returns (stream Feature) {}// A client-to-server streaming RPC.//// Accepts a stream of Points on a route being traversed, returning a// RouteSummary when traversal is completed.rpc RecordRoute(stream Point) returns (RouteSummary) {}// A Bidirectional streaming RPC.//// Accepts a stream of RouteNotes sent while a route is being traversed,// while receiving other RouteNotes (e.g. from other users).rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}

其中涉及到一些参数message表示传递数据.

// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {int32 latitude = 1;int32 longitude = 2;
}// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {// One corner of the rectangle.Point lo = 1;// The other corner of the rectangle.Point hi = 2;
}// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {// The name of the feature.string name = 1;// The point where the feature is detected.Point location = 2;
}// A RouteNote is a message sent while at a given point.
message RouteNote {// The location from which the message is sent.Point location = 1;// The message to be sent.string message = 2;
}// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {// The number of points received.int32 point_count = 1;// The number of known features passed while traversing the route.int32 feature_count = 2;// The distance covered in metres.int32 distance = 3;// The duration of the traversal in seconds.int32 elapsed_time = 4;
}

生成的两个文件包括message实现和用于server,client的代码

在pb.go文件中对于每个message实现了其type,比如对于Rectangle

type Rectangle struct {state         protoimpl.MessageStatesizeCache     protoimpl.SizeCacheunknownFields protoimpl.UnknownFields// One corner of the rectangle.Lo *Point `protobuf:"bytes,1,opt,name=lo,proto3" json:"lo,omitempty"`// The other corner of the rectangle.Hi *Point `protobuf:"bytes,2,opt,name=hi,proto3" json:"hi,omitempty"`
}
func (x *Rectangle) Reset() {*x = Rectangle{}if protoimpl.UnsafeEnabled {mi := &file_routeguide_route_guide_proto_msgTypes[1]ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))ms.StoreMessageInfo(mi)}
}func (x *Rectangle) String() string {return protoimpl.X.MessageStringOf(x)
}func (*Rectangle) ProtoMessage() {}func (x *Rectangle) ProtoReflect() protoreflect.Message {mi := &file_routeguide_route_guide_proto_msgTypes[1]if protoimpl.UnsafeEnabled && x != nil {ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))if ms.LoadMessageInfo() == nil {ms.StoreMessageInfo(mi)}return ms}return mi.MessageOf(x)
}// Deprecated: Use Rectangle.ProtoReflect.Descriptor instead.
func (*Rectangle) Descriptor() ([]byte, []int) {return file_routeguide_route_guide_proto_rawDescGZIP(), []int{1}
}func (x *Rectangle) GetLo() *Point {if x != nil {return x.Lo}return nil
}func (x *Rectangle) GetHi() *Point {if x != nil {return x.Hi}return nil
}

对于Client来说,定义接口.首先使用grpc库中的grpc.ClientConnInterface作为routeGuideClient的成员.

type routeGuideClient struct {cc grpc.ClientConnInterface
}

给结构体routeGuideClient实现多个方法,并定义接口

type RouteGuideClient interface {// A simple RPC.//// Obtains the feature at a given position.//// A feature with an empty name is returned if there's no feature at the given// position.GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error)// A server-to-client streaming RPC.//// Obtains the Features available within the given Rectangle.  Results are// streamed rather than returned at once (e.g. in a response message with a// repeated field), as the rectangle may cover a large area and contain a// huge number of features.ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error)// A client-to-server streaming RPC.//// Accepts a stream of Points on a route being traversed, returning a// RouteSummary when traversal is completed.RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error)// A Bidirectional streaming RPC.//// Accepts a stream of RouteNotes sent while a route is being traversed,// while receiving other RouteNotes (e.g. from other users).RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error)
}

然后通过NewRouteGuideClient返回结构体

func NewRouteGuideClient(cc grpc.ClientConnInterface) RouteGuideClient {return &routeGuideClient{cc}
}

实现结构体的方法

func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) {out := new(Feature)err := c.cc.Invoke(ctx, RouteGuide_GetFeature_FullMethodName, in, out, opts...)if err != nil {return nil, err}return out, nil
}func (c *routeGuideClient) ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) {stream, err := c.cc.NewStream(ctx, &RouteGuide_ServiceDesc.Streams[0], RouteGuide_ListFeatures_FullMethodName, opts...)if err != nil {return nil, err}x := &routeGuideListFeaturesClient{stream}if err := x.ClientStream.SendMsg(in); err != nil {return nil, err}if err := x.ClientStream.CloseSend(); err != nil {return nil, err}return x, nil
}

如果涉及stream还有新的结构,定义结构体,方法和接口


type RouteGuide_ListFeaturesClient interface {Recv() (*Feature, error)grpc.ClientStream
}type routeGuideListFeaturesClient struct {grpc.ClientStream
}func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) {m := new(Feature)if err := x.ClientStream.RecvMsg(m); err != nil {return nil, err}return m, nil
}

对于server类似,定义接口

type RouteGuideServer interface {// A simple RPC.//// Obtains the feature at a given position.//// A feature with an empty name is returned if there's no feature at the given// position.GetFeature(context.Context, *Point) (*Feature, error)// A server-to-client streaming RPC.//// Obtains the Features available within the given Rectangle.  Results are// streamed rather than returned at once (e.g. in a response message with a// repeated field), as the rectangle may cover a large area and contain a// huge number of features.ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error// A client-to-server streaming RPC.//// Accepts a stream of Points on a route being traversed, returning a// RouteSummary when traversal is completed.RecordRoute(RouteGuide_RecordRouteServer) error// A Bidirectional streaming RPC.//// Accepts a stream of RouteNotes sent while a route is being traversed,// while receiving other RouteNotes (e.g. from other users).RouteChat(RouteGuide_RouteChatServer) errormustEmbedUnimplementedRouteGuideServer()
}
实现server和client

当使用protoc生成文件之后,就可以写server和client了.

server

定义结构体,注意定义时加上pb.UnimplementedRouteGuideServer这样避免有些方法没有实现.

type routeGuideServer struct {pb.UnimplementedRouteGuideServersavedFeatures []*pb.Feature // read-only after initializedmu         sync.Mutex // protects routeNotesrouteNotes map[string][]*pb.RouteNote
}

实现接口满足的方法.

func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error)
func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) 
func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) 
func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer)

然后使用tcp链接新建grpc服务

func main() {flag.Parse()lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))if err != nil {log.Fatalf("failed to listen: %v", err)}var opts []grpc.ServerOptionif *tls {if *certFile == "" {*certFile = data.Path("x509/server_cert.pem")}if *keyFile == "" {*keyFile = data.Path("x509/server_key.pem")}creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)if err != nil {log.Fatalf("Failed to generate credentials: %v", err)}opts = []grpc.ServerOption{grpc.Creds(creds)}}grpcServer := grpc.NewServer(opts...)pb.RegisterRouteGuideServer(grpcServer, newServer())grpcServer.Serve(lis)
}

上面使用pb.RegisterRouteGuideServer注册服务,参数分别是grpc服务和newServer返回的结构体

client
func printFeature(client pb.RouteGuideClient, point *pb.Point) {log.Printf("Getting feature for point (%d, %d)", point.Latitude, point.Longitude)ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()feature, err := client.GetFeature(ctx, point)if err != nil {log.Fatalf("client.GetFeature failed: %v", err)}log.Println(feature)
}

利用context创建ctx和cancel,利用client := pb.NewRouteGuideClient(conn)创建client调用方法.

NewRouteGuideClient返回对应的client接口

func NewRouteGuideClient(cc grpc.ClientConnInterface) RouteGuideClient {return &routeGuideClient{cc}
}

gRPC面临的挑战

虽然gRPC确实允许您使用这些较新的技术,但gRPC服务的原型设计更具挑战性,因为无法使用Postman HTTP客户端等工具来轻松地与您公开的gRPC服务交互。你确实有一些选择可以实现这一点,但这并不是一种在本地就可以获得的东西。

有一些选项可以使用诸如特使之类的工具来反转代理标准JSON请求,并将其转码为正确的数据格式,但这是一个额外的依赖项,对于简单的项目来说,设置它可能很困难。

参考资料

  1. Documentation | gRPC
  2. Go gRPC Beginners Tutorial | TutorialEdge.net
  3. [Go RPC开发简介 - 官方RPC库 - 《Go RPC开发指南 中文文档]》 - 书栈网 · BookStack
  4. RESTful API 最佳实践 - 阮一峰的网络日志 (ruanyifeng.com)
  5. Basics tutorial | Go | gRPC
  6. What is gRPC? | gRPC

如有疑问,欢迎各位交流!

服务器配置
宝塔:宝塔服务器面板,一键全能部署及管理
云服务器:阿里云服务器
Vultr服务器
GPU服务器:Vast.ai

相关文章:

【gRPC学习】使用go学习gRPC

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 RPC是远程调用,而google实现了grpc比较方便地实现了远程调用,gRPC是一个现代的开源远程过程调用(RPC)框架 概念介绍 在gRPC中,客户端应用程序可以直接调用另一台计算机上的服务器应用程序上的方法&#…...

C语言中常用的字符串函数(strlen、sizeof、sscanf、sprintf、strcpy)

C语言中常用的字符串函数 文章目录 C语言中常用的字符串函数1 strlen函数2 sizeof函数2.1 sizeof介绍2.2 sizeof用法 3 sscanf函数3.1 sscanf介绍3.2 sscanf用法3.3 sscanf高级用法 4 sprintf函数4.1 背景4.2 sprintf用法 5 strcpy函数5.1 strcpy介绍5.1 strcpy用法 1 strlen函…...

域名解析服务器:连接你与互联网的桥梁

域名解析服务器:连接你与互联网的桥梁 大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,我们将探讨一个网络世界中至关重要却鲜为人知的角…...

理论物理在天线设计和射频电路设计中的应用

理论物理的基本原理可以应用于电路中的电磁场分析和电磁波传播问题,例如天线设计和射频电路设计。通过应用麦克斯韦方程组和电磁波传播理论,可以优化电路的性能,提高天线的辐射效率和射频电路的传输效率。麦克斯韦方程组是描述电磁场行为的基…...

MySql01:初识

1.mysql数据库2.配置环境变量3. 列的类型和属性,索引,注释3.1 类型3.2 属性3.3 主键(主键索引)3.4 注释 4.结构化查询语句分类:5.列类型--表列类型设置 1.mysql数据库 数据库: ​ 数据仓库,存储数据,以前我…...

Python——运算符

num 1 num 1 print("num1:", num) num - 1 print("num-1:", num) num * 4 print("num*4:", num) num / 4 print("num/4:", num) num 3 num % 2 print("num%2:", num) num ** 2 print("num**2:", num) 运行结果…...

赋能软件开发:生成式AI在优化编程工作流中的应用与前景

随着人工智能(AI)技术的快速发展,特别是生成式AI模型如GPT-3/4的出现,软件开发行业正经历一场变革,这些模型通过提供代码生成、自动化测试和错误检测等功能,极大地提高了开发效率和软件质量。 本文旨在深入…...

通过盲对抗性扰动实时击败基于DNN的流量分析系统

文章信息 论文题目:Defeating DNN-Based Traffic Analysis Systems in Real-Time With Blind Adversarial Perturbations 期刊(会议):30th USENIX Security Symposium 时间:2021 级别:CCF A 文章链接&…...

【Project】TPC-Online Module (manuscript_2024-01-07)

PRD正文 一、概述 本模块实现隧道点云数据的线上汇总和可视化。用户可以通过注册和登录功能进行身份验证,然后上传原始隧道点云数据和经过处理的数据到后台服务器。该模块提供数据查询、筛选和可视化等操作,同时支持对指定里程的分段显示和点云颜色更改…...

通过cpolar在公网访问本地网站

通过cpolar可以轻松将本地网址映射到公网进行访问,下面简要介绍一下实现步骤。 目录 一、cpolar下载 二、安装 三、使用 3.1 登录 3.2 创建隧道 一、cpolar下载 cpolar官网地址:cpolar - secure introspectable tunnels to localhost 通过QQ邮箱…...

Prokka: ubuntu安装的时候出现错误

[14:10:57] Running: cat /app/prokka_result/ref_file/ref_file.HAMAP.hmm.tmp.77.faa | parallel --gnu --plain -j 2 --block 108208 --recstart ‘>’ --pipe hmmscan --noali --notextw --acc -E 1e-09 --cpu 1 /opt/prokka/db/hmm/HAMAP.hmm /dev/stdin > /app/pro…...

安全防御之密码技术

密码学是信息安全的基础技术之一,是达到信息系统安全等级保护要求的核心技术支持,在身份验证、访问控制、文件加密、数据加密和安全传输中都得到广泛应用。其核心目标是保证信息的机密性、完整性和可用性。 密码学包括加密和解密两个部分。一般过程是&am…...

一文读懂「多模态大模型」

​ 学习资源 5-多模态大模型一统NLP和CV 1.多模态大模型的基本原理 2.常见的多模态大模型 https://www.bilibili.com/video/BV1NN41177Zp?p5&vd_sourcef27f081fc77389ca006fcebf41bede2d 3.多模态大模型如_哔哩哔哩_bilibili 强强联手!科大讯飞和中科院终于把【…...

深入PostgreSQL:高级函数用法探索

写在开头 在 PostgreSQL 中,函数是数据库开发和管理中强大而灵活的工具。通过深入了解高级函数用法,我们可以更有效地利用 PostgreSQL 的功能。在本文中,我们将探讨一些看起来比较高级的 PostgreSQL 函数用法,包括窗口函数、自定义聚合函数、JSONB 类型函数、全文搜索、PL…...

huggingface实战bert-base-chinese模型(训练+预测)

文章目录 前言一、bert模型词汇映射说明二、bert模型输入解读1、input_ids说明2、attention_mask说明3、token_type_ids说明4、模型输入与vocab映射内容二、huggingface模型数据加载1、数据格式查看2、数据dataset处理3、tokenizer处理dataset数据三、huggingface训练bert分类模…...

CCS安装和导入项目及编译教程

1. CCS安装# 在 TI官网 下载离线版(offline)。 Code Composer Studio Downloads 页面上有license 信息:这么看来是免费的,爱了爱了 Licensing: CCSv7 and later are Technology Software Publicly Available (TSPA) compliant.…...

在React里面使用mobx状态管理详细步骤

1、安装MobX和MobX React: 在你的项目目录下运行以下命令安装MobX和MobX React: npm install mobx mobx-react2、创建MobX Store: 创建一个用于管理状态的MobX Store。这个Store应该包含你希望全局管理的状态和相关的操作。以下是一个简单…...

1.6PTA集练7-5~7-24、7-1、7-2,堆的操作,部落冲突(二分查找)

7-5 大師と仙人との奇遇 分数 20 #include<iostream> #include<queue> using namespace std; int n; long long ans0,num; priority_queue<long long,vector<long long>,greater<long long>>q;//记录之前买的,用小顶堆&#xff0c;最上面就是最…...

uniapp向上拉加载,下拉刷新

目录 大佬1大佬2 大佬1 大佬地址&#xff1a;https://blog.csdn.net/wendy_qx/article/details/135077822 大佬2 大佬2&#xff1a;https://blog.csdn.net/chen__hui/article/details/122497140...

目标检测脚本之mmpose json转yolo txt格式

目标检测脚本之mmpose json转yolo txt格式 一、需求分析 在使用yolopose及yolov8-pose 网络进行人体姿态检测任务时&#xff0c;有时需要标注一些特定场景的中的人型目标数据&#xff0c;用来扩充训练集&#xff0c;提升自己训练模型的效果。因为单纯的人工标注耗时费力&…...

大数据技术在民生资金专项审计中的应用

一、应用背景 目前,针对审计行业,关于大数据技术的相关研究与应用一般包括大数据智能采集数据技术、大数据智能分析技术、大数据可视化分析技术以及大数据多数据源综合分析技术。其中,大数据智能采集数据技术是通过网络爬虫或者WebService接口实现跨部门在线数据交互;大数…...

视觉SLAM十四讲|【四】误差Jacobian推导

视觉SLAM十四讲|【四】误差Jacobian推导 预积分误差递推公式 ω 1 2 ( ( ω b k n k g − b k g ) ( w b k 1 n k 1 g − b k 1 g ) ) \omega \frac{1}{2}((\omega_b^kn_k^g-b_k^g)(w_b^{k1}n_{k1}^g-b_{k1}^g)) ω21​((ωbk​nkg​−bkg​)(wbk1​nk1g​−bk1g​)) …...

「实战应用」如何用DHTMLX Gantt构建类似JIRA式的项目路线图(一)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 在web项目中使用DHTMLX Gantt时&#xff0c;开发人员经常需要满足与UI外观相关的各种需求。因此他们必须确定JavaScript甘特图库的…...

【习题】应用程序框架

判断题 1. 一个应用只能有一个UIAbility。错误(False) 正确(True)错误(False) 2. 创建的Empty Ability模板工程&#xff0c;初始会生成一个UIAbility文件。正确(True) 正确(True)错误(False) 3. 每调用一次router.pushUrl()方法&#xff0c;页面路由栈数量均会加1。错误(Fal…...

java基于ssm的线上选课系统的设计与实现论文

摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对学生选课信息管理的提升&#x…...

汽车雷达:实时SAR成像的实现

摘要: 众所周知,点云成像是目前实现汽车雷达感知最流行的方案,尤其是采用多级联实现的4D点云成像雷达,这是目前最有希望实现产品落地的技术方案之一。 今天重点分享关于汽车雷达SAR成像相关技术内容,这也证实了4D点云成像雷达并不一定就是汽车雷达成像唯一的方案,在业内…...

《C++语言程序设计(第5版)》(清华大学出版社,郑莉 董渊编著)习题——第2章 C++语言简单程序设计

2-15 编写一个程序&#xff0c;运行时提示输入一个数字&#xff0c;再把这个数字显示出来。 #include <iostream>using namespace std;int main() {// 提示用户输入数字cout << "请输入一个数字: ";// 用于存储用户输入的数字的变量double number;// 从…...

2023年生成式AI全球使用报告

生成式人工智能工具正在迅速改变多个领域&#xff0c;从营销和新闻到教育和艺术。 这些工具使用算法从大量培训材料中获取新的文本、音频或图像。虽然 ChatGPT 和 Midjourney 之类的工具可以用来实现超出人类能力或想象力的艺术效果&#xff0c;但目前它们最常用于比人类更轻松…...

安全防御之漏洞扫描技术

每年都有数以千计的网络安全漏洞被发现和公布&#xff0c;加上攻击者手段的不断变化&#xff0c;网络安全状况也在随着安全漏洞的增加变得日益严峻。寻根溯源&#xff0c;绝大多数用户缺乏一套完整、有效的漏洞管理工作流程&#xff0c;未能落实定期评估与漏洞修补工作。只有比…...

SPON世邦 IP网络对讲广播系统 多处文件上传漏洞复现

0x01 产品简介 SPON世邦IP网络对讲广播系统是一种先进的通信解决方案,旨在提供高效的网络对讲和广播功能。 0x02 漏洞概述 SPON世邦IP网络对讲广播系统 addscenedata.php、uploadjson.php、my_parser.php等接口处存在任意文件上传漏洞,未经身份验证的攻击者可利用此漏洞上…...

一个手机网站/中文域名注册官网入口

其中以WinExec最为简单&#xff0c;ShellExecute比WinExec灵活一些&#xff0c;CreateProcess最为复杂。 WinExec 有两个参数&#xff0c;前一个指定路径&#xff0c;后一个指定显示方式。 ShellExecute 可以指定工作目录,并且还可以寻找文件的关联直接打开不用加载与文件关联…...

定制网站建设服务器/上海关键词排名手机优化软件

参考&#xff1a;http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/tutorials.html 矩阵的掩码操作 矩阵的掩码操作很简单。其思想是&#xff1a;根据掩码矩阵&#xff08;也称作核&#xff09;重新计算图像中每个像素的值。掩码矩阵中的值表示近邻像素值&#…...

做微商网站公司/企业类网站有哪些例子

用 Create Table 建立一个表 Table1 &#xff0c;主键是自动编号字段&#xff0c;另一个字段是长度是 10 的文本字段。 代码如下:CREATE TABLE Table1 (Id COUNTER CONSTRAINT PrimaryKey PRIMARY KEY, MyText TEXT (10)) 再建一个包含两个字段的表 Table2&#xff0c;字段 id …...

南阳最新通知今天/seo交流网

-- -- PL/SQL --> PL/SQL记录 -- PL/SQL记录有着类似于表的数据结构&#xff0c;是一个或多个字段且拥有数据类型的集合体。定义了PL/SQL记录类型之后&#xff0c;可以定义PL/SQL记录变 量。声明一个PL/SQL记录变量相当于定义了多个标量变量&#xff0c;简化了变量的声明&am…...

为什么做企业网站/手机网络优化软件

thrift服务端的c语言实现 1.thrift 概念1 thrift是一个软件框架&#xff0c;用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎&#xff0c;以构建在 C, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Small…...

哈巴河网站制作/站长工具麻豆

求正整数数对 (x,y)(x,y)(x,y) &#xff0c;满足 x>yx>yx>y 且 (x−y)xyxyyx.(x-y)^{xy}x^yy^x.(x−y)xyxyyx. (2013&#xff0c;中国台湾数学奥林匹克训练营) 解法1&#xff1a; 设 (x,y)d,xdv,ydt,(v,t)1.(x,y)d ,xdv,ydt,(v,t)1.(x,y)d,xdv,ydt,(v,t)1. 则: dxy−…...