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

【SpringBoot框架篇】37.使用gRPC实现远程服务调用

文章目录

  • RPC简介
  • gPRC简介
  • protobuf
    • 1.文件编写规范
    • 2.字段类型
    • 3.定义服务(Services)
  • 在Spring Boot中使用grpc
    • 1.父工程pom配置
    • 2.grpc-api模块
      • 2.1.pom配置
      • 2.2.proto文件编写
      • 2.3.把proto文件编译成class文件
    • 3.grpc-server模块
      • 3.1.pom文件和application.yaml
      • 3.2.实现grpc-api模块的接口
      • 3.3.启动服务
    • 4.grpc-client模块
      • 4.1.pom文件和application.yaml
      • 4.2.创建http接口调用grpc-server
      • 4.3.启动服务测试
  • 项目配套代码

RPC简介

RPC简介:

  • RPC(Remote Procedure Call)是一种用于实现分布式系统中不同节点之间通信的协议。它允许一个节点(称为客户端)调用另一个节点(称为服务器)上的远程方法,就像调用本地方法一样。RPC的目标是隐藏底层通信细节,使得远程调用过程对开发者透明。
  • 在RPC中,客户端通过发送请求消息给服务器来调用远程方法,服务器接收到请求后执行相应的方法,并将结果返回给客户端。RPC可以跨越不同的网络和操作系统,使得分布式系统中的不同节点能够进行高效的通信和协作。
  • RPC的实现方式有多种,常见的包括基于HTTP协议的RESTful API、基于TCP/IP协议的Socket编程、以及基于消息队列的异步通信等。不同的实现方式有不同的特点和适用场景,开发者可以根据具体需求选择合适的RPC框架或协议。

gPRC简介

gprc官网: https://grpc.io/docs/
gRRC的g代表google,gRPC最初是由Google创建的,是一个现代的开源高性能远程过程调用(RPC)框架,可以在任何环境中运行。它可以高效地连接数据中心内和跨数据中心的服务,支持负载平衡、跟踪、运行状况检查和身份验证。它也适用于分布式计算的最后一英里,将设备、移动应用程序和浏览器连接到后端服务。

gRPC的特性
看官方文档的介绍,有以下几点特性:

  • grpc可以跨语言使用。支持多种语言 支持C++、Java、Go、Python、Ruby、C#、Node.js、Android - Java、Objective-C、PHP等编程语言
  • 基于 IDL ( 接口定义语言(Interface Define Language))文件定义服务,通过 proto3 工具生成指定语言的数据结构、服务端接口以及客户端 Stub;
  • 通信协议基于标准的 HTTP/2 设计,支持·双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC - 在移动端设备上更加省电和节省网络流量;
  • 序列化支持 PB(Protocol Buffer)和 JSON,PB - 是一种语言无关的高性能序列化框架,基于 HTTP/2 + PB, 保障了 RPC 调用的高性能。

性能
gRPC消息使用一种有效的二进制消息格式protobuf进行序列化。Protobuf在服务器和客户机上的序列化非常快。Protobuf序列化后的消息体积很小,能够有效负载,在移动应用程序等有限带宽场景中显得很重要。与采用文本格式的JSON相比,采用二进制格式的protobuf在速度上可以达到前者的5倍!Auth0网站所做的性能测试结果显示,protobuf和JSON的优势差异在Java、Python等环境中尤为明显。下图是Auth0在两个Spring Boot应用程序间所做的对比测试结果。
在这里插入图片描述

  • gRPC是为HTTP/2而设计的,它是HTTP的一个主要版本,与HTTP 1.x相比具有显著的性能优势::
  • 二进制框架和压缩。HTTP/2协议在发送和接收方面都很紧凑和高效。通过单个TCP连接复用多个HTTP/2调用。多路复用消除了线头阻塞。

代码生成

  • gRPC框架都为代码生成提供了一流的支持。gRPC开发的核心文件是*.proto文件 ,它定义了gRPC服务和消息的约定。根据这个文件,gRPC框架将生成服务基类,消息和完整的客户端代码。
  • 通过在服务器和客户端之间共享*.proto文件,可以从端到端生成消息和客户端代码。客户端的代码生成消除了客户端和服务器上的重复消息,并为您创建了一个强类型的客户端。无需编写客户端代码,可在具有许多服务的应用程序中节省大量开发时间。

严格的规范

  • 不存在具有JSON的HTTP API的正式规范。开发人员不需要讨论URL,HTTP动词和响应代码的最佳格式。(想想,是用Post还是Get好?使用Get还是用Put好?一想到有选择恐惧症的你是不是又开了纠结,然后浪费了大量的时间)
  • 该gRPC规范是规定有关gRPC服务必须遵循的格式。gRPC消除了争论并节省了开发人员的时间,因为gPRC在各个平台和实现之间是一致的。

  • HTTP/2为长期的实时通信流提供了基础。gRPC通过HTTP/2为流媒体提供一流的支持。
  • gRPC服务支持所有流组合:
    • 一元(没有流媒体): 简单rpc 这就是一般的rpc调用,一个请求对象对应一个返回对象。客户端发起一次请求,服务端响应一个数据,即标准RPC通信。 (rpc Method(request) returns (response)){}
    • 服务器流RPC是指客户端发一个对象,服务器返回一个Stream流式消息(rpc Method(request) returns (stream response)){}
    • 客户端流RPC,客户端发一个流给服务器,服务器返回一个对象(rpc Method(stream request) returns ( response)){}
    • 双向流媒体:双向流式rpc 结合客户端流式rpc和服务端流式rpc,可以传入多个对象,返回多个响应对象。应用场景:聊天应用。(rpc Method(stream request) returns (stream response)){}

gRPC非常适合以下场景:

  • 微服务:gRPC设计为低延迟和高吞吐量通信。gRPC非常适用于效率至关重要的轻型微服务。
  • 点对点实时通信: gRPC对双向流媒体提供出色的支持。gRPC服务可以实时推送消息而无需轮询。
  • 多语言混合开发环境: gRPC工具支持所有流行的开发语言,使gRPC成为多语言开发环境的理想选择。
  • 网络受限环境:使用Protobuf(一种轻量级消息格式)序列化gRPC消息。gRPC消息始终小于等效的JSON消息。

protobuf

官方文档: https://protobuf.dev/programming-guides/proto3/

  • protobuf 即 Protocol Buffers,是一种轻便高效的结构化数据存储格式,与语言、平台无关,可扩展可序列化。
  • Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。json、xml都是基于文本格式,protobuf 是以二进制方式存储的,占用空间小,但也带来了可读性差的缺点。
  • protobuf 在通信协议和数据存储等领域应用广泛。例如著名的分布式缓存工具 Memcached 的 Go 语言版本groupcache 就使用了 protobuf 作为其 RPC 数据格式。
  • Protobuf 在 .proto 定义需要处理的结构化数据,可以通过 protoc 工具,将 .proto 文件转换为C++、Golang、Java、Python 等多种语言的代码,兼容性好,易于使用。

1.文件编写规范

syntax = "proto3";
package main;message User {string name = 1;bool enabled = 2;repeated int32 roles = 3;
}

逐行解读user.proto

  • protobuf 有2个版本,默认版本是 proto2,如果需要 proto3,则需要在非空非注释第一行使用 syntax = “proto3” 标明版本。
  • package,即包名声明符是可选的,用来防止不同的消息类型有命名冲突。
  • 消息类型 使用 message 关键字定义,User 是类型名,name, enabled, roles 是该类型的 3 个字段,类型分别为 string, bool 和 []int32。字段可以是标量类型,也可以是合成类型。
  • 每个字段的修饰符默认是 singular,一般省略不写,repeated 表示字段可重复,即用来表示数组类型。
  • 每个字符 =后面的数字称为标识符,每个字段都需要提供一个唯一的标识符。标识符用来在消息的二进制格式中识别各个字段,一旦使用就不能够再改变,标识符的取值范围为 [1, 2^29 - 1] 。
  • .proto 文件可以写注释,单行注释 //,多行注释 /* … */
    一个 .proto 文件中可以写多个消息类型,即对应多个结构体(struct)。

2.字段类型

基础字段类型
在这里插入图片描述

枚举(Enumerations)
举类型适用于提供一组预定义的值,选择其中一个。例如我们将用户状态定义为枚举类型。

  enum Status {ENABLED = 0;DISABLED = 1;}message User {string name = 1;string password=2;Status status = 3;
}

嵌入其它消息体
可以再message里面嵌套message,和java内嵌一个原理

// 返回结果
message LoginResultVo {Result result = 1; // 状态信息UserInfo data = 2; // 数据
}
message Result {int32 code = 1;string msg = 2;
}

3.定义服务(Services)

如果消息类型是用来远程通信的(Remote Procedure Call, RPC),可以在 .proto 文件中定义 RPC 服务接口。例如我们定义了一个名为 UserServiceApi 的 RPC 服务,提供了login接口,入参是 LoginInfoDTO 类型,返回类型是 LoginResultVo 类型

service UserServiceApi {rpc login (LoginInfoDTO) returns (LoginResultVo);
}// 请求参数
message LoginInfoDTO {string username = 1;string password=2;
}

在Spring Boot中使用grpc

创建一个聚合项目,分三个子模块

  • grpc-api: 封装需要远程调用的API,和dubbo类似
  • grpc-server: 远程调用的服务提供者
  • grpc-client: 客户端调用者
    在这里插入图片描述

1.父工程pom配置

    <modules><module>grpc-api</module><module>grpc-server</module><module>grpc-client</module></modules><properties><java.version>1.8</java.version><!-- grpc依赖--><grpc.version>1.53.0</grpc.version><grpc.spring.boot.version>2.14.0.RELEASE</grpc.spring.boot.version><protoc.version>3.22.0</protoc.version><protobuf.java.version>3.21.7</protobuf.java.version><!--grpc编译插件--><protobuf.plugin.version>0.6.1</protobuf.plugin.version><os.maven.plugin.version>1.7.1</os.maven.plugin.version><!-- 自定义grpc api模块版本--><grpc-api.version>0.0.1-SNAPSHOT</grpc-api.version></properties><!--统一管理版本号--><dependencyManagement><dependencies><!-- gRpc 依赖 --><dependency><groupId>io.grpc</groupId><artifactId>grpc-bom</artifactId><version>${grpc.version}</version><type>pom</type><scope>import</scope></dependency><!-- gRpc Protobuf --><dependency><groupId>io.grpc</groupId><artifactId>grpc-protobuf</artifactId><version>${grpc.version}</version></dependency><!-- gRpc Stub --><dependency><groupId>io.grpc</groupId><artifactId>grpc-stub</artifactId><version>${grpc.version}</version></dependency><!-- protobuf-java  --><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>${protobuf.java.version}</version></dependency><!-- gRpc Server --><dependency><groupId>net.devh</groupId><artifactId>grpc-server-spring-boot-starter</artifactId><version>${grpc.spring.boot.version}</version></dependency><!-- gRpc Client --><dependency><groupId>net.devh</groupId><artifactId>grpc-client-spring-boot-starter</artifactId><version>${grpc.spring.boot.version}</version></dependency><dependency><groupId>com.ljm.boot.grpc</groupId><artifactId>grpc-api</artifactId><version>${grpc-api.version}</version></dependency></dependencies></dependencyManagement>

2.grpc-api模块

2.1.pom配置

.proto文件编译成java文件需要引入已下三个依赖和两个插件

    <dependencies><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId></dependency><dependency><groupId>io.grpc</groupId><artifactId>grpc-protobuf</artifactId></dependency><dependency><groupId>io.grpc</groupId><artifactId>grpc-stub</artifactId></dependency></dependencies><build><extensions><!-- OS 插件 --><extension><groupId>kr.motd.maven</groupId><artifactId>os-maven-plugin</artifactId><version>${os.maven.plugin.version}</version></extension></extensions><plugins><plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>${protobuf.plugin.version}</version><configuration><pluginId>grpc-java</pluginId><protoSourceRoot>src/main/proto</protoSourceRoot><protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact><pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact></configuration><executions><execution><goals><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin></plugins></build>

2.2.proto文件编写

在这里插入图片描述

  • 第一步: 在src.main目录下新建proto目录
  • 第二步: 在commom包下面新建result.proto文件封装通用的响应信息
  • 第三部: 在user包下面新建user.proto文件,封装用户相关的接口信息

result.proto文件内容如下

syntax = "proto3";package api.common;option java_package = "com.ljm.boot.grpc.api.common"; //包名
option java_outer_classname = "ResultProto"; //编译后的类名
option java_multiple_files = true; //生成多个文件message Result {bool ok = 1; // 是否成功int32 code = 2; // 状态码string message = 3; // 消息
}

user.proto文件如下


syntax = "proto3";package api.login;import "api/common/result.proto"; //引入common包下的result.proto模块, api/common路径对应result.proto里的 package api.common;option java_package = "com.ljm.boot.grpc.api.user"; //包名
option java_outer_classname = "UserServiceProto"; //编译后的类名
option java_multiple_files = true; //生成多个文件// 接口类
service UserServiceApi {rpc login (LoginInfoDTO) returns (LoginResultVo);
}// 请求参数
message LoginInfoDTO {string username = 1;string password=2;
}// 返回结果
message LoginResultVo {api.common.Result result = 1; // 状态信息UserInfo data = 2; // 数据
}message UserInfo {string token = 1; // token信息int32 id = 2; // 用户Id
}

2.3.把proto文件编译成class文件

在grpc-api目录下执行install命令

cd grpc-api
mvn clean install	

在这里插入图片描述
看到如上信息就可以去target目录下找编译后的文件
和接口相关的三个类, xxxApiGrpc、 xxxApiGrpc.xxxImplBase、xxxApiStub

  • xxxApiGrpc: 对应上面编写user.proto文件中service UserServiceApi

  • xxxApiGrpc.xxxImplBase: 抽象类,需要grpc-server模块去具体业务类中继承这个类然后重写方法里写具体业务代码

  • xxxApiGrpc.xxxApiStub :这个类中的login方法就是grpc-client需要调用的接口
    在这里插入图片描述
    在这里插入图片描述

  • UserServiceApiGrpc文件就是对应接口编译后service类

  • 在 UserServiceApi类下面有个静态类UserServiceApiStub,这个类下面的login方法就是grpc-client需要调用的接口

  • 在 UserServiceApi类下面有个抽象类UserServiceApiImplBase,需要grpc-server去继承这个类然后重写方法里写具体业务代码

3.grpc-server模块

3.1.pom文件和application.yaml

pom文件
需要继承父工程

    <parent><groupId>com.ljm.boot.grpc</groupId><artifactId>parent</artifactId><version>0.0.1-SNAPSHOT</version></parent><dependencies><dependency><groupId>com.ljm.boot.grpc</groupId><artifactId>grpc-api</artifactId></dependency><!-- gRpc Server --><dependency><groupId>net.devh</groupId><artifactId>grpc-server-spring-boot-starter</artifactId></dependency></dependencies>   

application.yaml
默认端口是9090,可以通过下面配置修改

grpc:server:port: 9090 #默认9090

3.2.实现grpc-api模块的接口

  • @GrpcService 注解表示这个接口是需要通过grpc调用
  • .newBuilder()实例化对象
  • onNext()设置返回结果
  • onCompleted() 可以理解为return,表示这次调用结束
@GrpcService
public class UserServiceApi extends UserServiceApiGrpc.UserServiceApiImplBase {@Overridepublic void login(LoginInfoDTO request, StreamObserver<LoginResultVo> responseObserver) {LoginResultVo.Builder builder=LoginResultVo.newBuilder();Result.Builder rBuilder=Result.newBuilder();if (!"admin".equals(request.getUsername()) || !"123456".equals(request.getPassword())){rBuilder.setOk(false);rBuilder.setCode(101);rBuilder.setMessage("用户名或密码错误!");}else{rBuilder.setOk(true);rBuilder.setCode(200);rBuilder.setMessage("登录成功!");builder.setData(UserInfo.newBuilder().setToken(UUID.randomUUID().toString()).setId(1).build());}builder.setResult(rBuilder);responseObserver.onNext(builder.build());responseObserver.onCompleted();}}

3.3.启动服务

启动类和普通的springboot项目并无区别

@SpringBootApplication
public class GrpcServerApplication {public static void main(String[] args) {SpringApplication.run(GrpcServerApplication.class, args);}
}

运行程序后可以看到gRPC服务已启动,绑定的端口是9090
在这里插入图片描述

4.grpc-client模块

4.1.pom文件和application.yaml

pom文件
相比于server模块添加了web服务模块

    <parent><groupId>com.ljm.boot.grpc</groupId><artifactId>parent</artifactId><version>0.0.1-SNAPSHOT</version></parent><dependencies><dependency><groupId>com.ljm.boot.grpc</groupId><artifactId>grpc-api</artifactId></dependency><!-- gRpc Client --><dependency><groupId>net.devh</groupId><artifactId>grpc-client-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

application.yaml文件配置

server:port: 8037grpc:client:#@GrpcClient注解需要和下面的grpc-server一致grpc-server:#grpc服务端的调用地址address: 'static://127.0.0.1:9090'enable-keep-alive: truekeep-alive-without-calls: true#传输类型设置为明文negotiation-type: plaintext

4.2.创建http接口调用grpc-server

  • @GrpcClient注解内的值需要和grpc.client.grpc-server保持一致
@RequestMapping
@RestController
public class UserController {@GrpcClient("grpc-server")private UserServiceApiGrpc.UserServiceApiBlockingStub serviceApiBlockingStub;@PostMapping("/login")public String login(@RequestParam String username, @RequestParam String password) {LoginInfoDTO loginInfoDTO = LoginInfoDTO.newBuilder().setUsername(username).setPassword(password).build();LoginResultVo loginResultVo = serviceApiBlockingStub.login(loginInfoDTO);String result;if (loginResultVo.getResult().getOk()) {result = String.format("登录成功,token=%s, userId=%d", loginResultVo.getData().getToken(), loginResultVo.getData().getId());} else {result = String.format("登录失败,code=%d,msg=%s", loginResultVo.getResult().getCode(), loginResultVo.getResult().getMessage());}return result;}
}

4.3.启动服务测试

@SpringBootApplication
public class GrpcClientApllication {public static void main(String[] args) {SpringApplication.run(GrpcClientApllication.class, args);}
}

在这里插入图片描述

通过接口测试工具调用 http://localhost:8037/login接口

设置账号密码和后台一致测试
在这里插入图片描述
设置密码错误再测试
在这里插入图片描述

由上可以看到结果和预期一致,使用gRPC分页查询数据的在gitee代码中提交了,篇幅有限就不一一概括了。

项目配套代码

gitee代码地址

创作不易,要是觉得我写的对你有点帮助的话,麻烦在gitee上帮我点下 Star

【SpringBoot框架篇】其它文章如下,后续会继续更新。

  • 1.搭建第一个springboot项目
  • 2.Thymeleaf模板引擎实战
  • 3.优化代码,让代码更简洁高效
  • 4.集成jta-atomikos实现分布式事务
  • 5.分布式锁的实现方式
  • 6.docker部署,并挂载配置文件到宿主机上面
  • 7.项目发布到生产环境
  • 8.搭建自己的spring-boot-starter
  • 9.dubbo入门实战
  • 10.API接口限流实战
  • 11.Spring Data Jpa实战
  • 12.使用druid的monitor工具查看sql执行性能
  • 13.使用springboot admin对springboot应用进行监控
  • 14.mybatis-plus实战
  • 15.使用shiro对web应用进行权限认证
  • 16.security整合jwt实现对前后端分离的项目进行权限认证
  • 17.使用swagger2生成RESTful风格的接口文档
  • 18.使用Netty加websocket实现在线聊天功能
  • 19.使用spring-session加redis来实现session共享
  • 20.自定义@Configuration配置类启用开关
  • 21.对springboot框架编译后的jar文件瘦身
  • 22.集成RocketMQ实现消息发布和订阅
  • 23.集成smart-doc插件零侵入自动生成RESTful格式API文档
  • 24.集成FastDFS实现文件的分布式存储
  • 25.集成Minio实现文件的私有化对象存储
  • 26.集成spring-boot-starter-validation对接口参数校验
  • 27.集成mail实现邮件推送带网页样式的消息
  • 28.使用JdbcTemplate操作数据库
  • 29.Jpa+vue实现单模型的低代码平台
  • 30.使用sharding-jdbc实现读写分离和分库分表
  • 31.基于分布式锁或xxx-job实现分布式任务调度
  • 32.基于注解+redis实现表单防重复提交
  • 33.优雅集成i18n实现国际化信息返回
  • 34.使用Spring Retry完成任务的重试
  • 35.kafka环境搭建和收发消息
  • 36.整合Tess4J搭建提供图片文字识别的Web服务
  • 37.使用gRPC实现远程服务调用

相关文章:

【SpringBoot框架篇】37.使用gRPC实现远程服务调用

文章目录 RPC简介gPRC简介protobuf1.文件编写规范2.字段类型3.定义服务(Services) 在Spring Boot中使用grpc1.父工程pom配置2.grpc-api模块2.1.pom配置2.2.proto文件编写2.3.把proto文件编译成class文件 3.grpc-server模块3.1.pom文件和application.yaml3.2.实现grpc-api模块的…...

投资的三个匹配

许多人亏钱都是犯了同样错误&#xff0c;要么对投资的预期过高&#xff0c;要么是投资期限不匹配&#xff0c;要么是波动承受能力不匹配。投资想要赚钱&#xff0c;先解决匹配问题。 1.预期收益率要匹配 就是明确自己做投资&#xff0c;每年想赚多少钱。凡事都要有个目标&…...

[Netty实践] 请求响应同步实现

目录 一、介绍 二、依赖引入 三、公共部分实现 四、server端实现 五、client端实现 六、测试 一、介绍 本片文章将实现请求响应同步&#xff0c;什么是请求响应同步呢&#xff1f;就是当我们发起一个请求时&#xff0c;希望能够在一定时间内同步&#xff08;线程阻塞&am…...

Java进阶—哈希冲突的解决

1. 什么是哈希冲突 哈希函数&#xff1a;哈希函数是一种将输入数据(键)映射到固定大小范围的输出值(哈希值)的函数。哈希函数通常用于存储 数据存储和检索领域&#xff0c;例如哈希表中。 哈希表&#xff1a;哈希表(Hash Table)&#xff0c;也成为哈希映射(Hash Map)或字典&…...

css的border详解

CSS的border属性是一个简写属性&#xff0c;用于设置以下四个边框属性&#xff1a; border-width&#xff1a;定义边框的宽度。可以使用具体的像素值&#xff0c;或者使用预定义的关键字如thin、medium和thick。border-width不支持百分比值。默认情况下&#xff0c;边框的宽度是…...

如何保障消息一定能发送到RabbitMQ?

我们知道&#xff0c;RabbitMQ的消息最终是存储在Queue上的&#xff0c;而在Queue之前还要经过Exchange&#xff0c;那么这个过程中就有两个地方可能导致消息丢失。第一个是Producer到Exchange的过程&#xff0c;第二个是Exchange到Queue的过程。 为了解决这个问题&#xff0c…...

【web前端】CSS语法

CSS语法 1. CSS语法格式 通常情况下语法格式如下: 选择器{属性名:属性值;属性名:属性值;属性名:属性值;... }2. CSS添加方式 2.1 行内样式 直接将样式写在本行的标签内。 <h1><p style"font-size: 48px; color:red;";>行内样式测试</p></…...

JS+CSS3点击粒子烟花动画js特效

JSCSS3点击粒子烟花动画js特效 JSCSS3点击粒子烟花动画js特效...

docker镜像复制与常见命令

一、前言 最近通过阿里的镜像仓库远程拉取镜像&#xff0c;发现以前的版本不见了&#xff0c;拉取了最新的镜像&#xff0c;有发现版本不配问题。那么想使用老版本的镜像那就要从别的环境获取。于是就需要进行离线镜像复制&#xff0c;打包&#xff0c;上传&#xff0c;重新导入…...

如何在linux环境上部署单机ES(以8.12.2版本为例)

ES安装&#xff08;以8.12.2版本为例&#xff09; 首先创建好对应的文件夹然后在对应的文件夹下执行依次这些命令 1.wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.12.2-linux-x86_64.tar.gz 2.wget https://artifacts.elastic.co/downloads/…...

如何利用人工智能技术实现企业营销效率提升10倍(下)

01. AI在私域运营中可扮演重要角色 私域用户体验历程中的不满&#xff0c;对企业来说&#xff0c;无疑是一记沉重的打击。这些不满不仅会让用户感到失望和沮丧&#xff0c;更会在无形中侵蚀企业的各个环节&#xff0c;给业务带来不可估量的损失。 在私域环境中&#xff0c;每…...

【PHP + 代码审计】数组函数

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…...

Keepalive与idle监测及性能优化

Keepalive 与 idle监测 Keepalive&#xff08;保活&#xff09;: Keepalive 是一种机制&#xff0c;通常用于TCP/IP网络。它的目的是确保连接双方都知道对方仍然存在并且连接是活动的。这是通过定期发送控制消息&#xff08;称为keepalive消息&#xff09;实现的。如果在预定时…...

DS-红黑树(RBTree)

一.红黑树 1.1 红黑树的起源 当对对AVL树做一些结构修改的操作时候&#xff0c;性能较为低下&#xff0c;比如&#xff1a;插入时要维护其绝对平衡&#xff0c;旋转的次数比较多&#xff0c;更差的是在删除时&#xff0c;有可能一直要让旋转持续到根的位置。 因此1972年Rudolf…...

ubuntu 如何使用阿里云盘

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…...

sqlite3 交叉编译

#1.下载源码并解压 源码路径如下&#xff0c;下载autoconf版本 SQLite Download Page 解压 tar -zxvf sqlite-autoconf-3450200.tar.gz cd sqlite-autoconf-3450200 mkdir build # 2. 配置源代码 # 假设你已经安装了交叉编译工具链&#xff0c;如gcc-arm-linux-gnueabih…...

【AI生成文章】flutter ChangeNotifierProvider 实用场景举例

内容由Ai 大模型生成&#xff0c;不能完全保障真实 ChangeNotifierProvider 是 Flutter 中一个非常实用的工具&#xff0c;用于在应用程序中管理和传递状态。以下是一些实用的场景举例&#xff1a; 1. 用户信息管理 在应用程序中&#xff0c;用户信息&#xff08;如用户名、…...

【0274】从shared init file或local init file加载relation cache(2 - 1)

上一篇: 【0273】深入分析 relcache(relation descriptor cache)初始化第一阶段(1) 【0264】深入分析relcache(relation descriptor cache)缓存初始化第2阶段(2) 1. 前言 本文内容是作为《【0264】深入分析relcache(relation descriptor cache)缓存初始化第2阶段…...

蓝桥杯-02-2023蓝桥杯c/c++省赛B组题目

参考 2023 年第十四届蓝桥杯 C/C B组省赛题解 2023蓝桥杯c/c省赛B组题目(最全版)&#xff1a; A&#xff1a;日期统计 这题方法应该很多&#xff0c;没有和别人讨论想法。我的解法思路是&#xff1a;先 load 函数生成所有这一年的合法日期&#xff0c;然后枚举所有可以从数据…...

欧拉筛+并查集

集合 - 洛谷 std::vector<int> minp, primes,primes1;void sieve(int n,int p) {minp.assign(n 1, 0);primes.clear();for (int i 2; i < n; i) {if (minp[i] 0) {minp[i] i;primes.push_back(i);}for (auto p : primes) {if (i * p > n) {break;}minp[i * p]…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...