【笔记】Spring Cloud Gateway 实现 gRPC 代理
Spring Cloud Gateway 在 3.1.x 版本中增加了针对 gRPC 的网关代理功能支持,本片文章描述一下如何实现相关支持.本文主要基于 Spring Cloud Gateway 的 官方文档 进行一个实践练习。有兴趣的可以翻看官方文档。
由于 Grpc 是基于 HTTP2 协议进行传输的,因此 Srping Cloud Gateway 在支持了 HTTP2 的基础上天然支持对 Grpc 服务器的代理,只需要在现有代理基础上针对 grpc 协议进行一些处理即可。
以下为实现步骤,这里提供了示例代码,可以按需取用.
生成服务器证书
由于 Grpc 协议使用了 Http2 作为通信协议, Http2 在正常情况下是基于 TLS 层上进行通信的,这就要求我们需要配置服务器证书,这里为了测试,使用脚本生成了一套 CA 证书:
#!/bin/bash
# 指定生成证书的目录
dir=$(dirname "$0")/../resources/x509
[ -d "$dir" ] && find "$dir" -type f -exec rm -rf {} \;
mkdir -p "$dir"
pushd "$dir" || exit
# 生成.key 私钥文件 和 csr 证书签名请求文件
openssl req -new -nodes -sha256 -newkey rsa:2048 -keyout ca.key -out ca.csr \
-subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=Ghimi Technology/OU=Ghimi Cloud/CN=ghimi.top"
# 生成自签名 .crt 证书文件
openssl x509 -req -in ca.csr -key ca.key -out ca.crt -days 3650
# 生成服务器私钥文件 和 csr 证书请求文件(私钥签名文件)
openssl req -new -nodes -sha256 -newkey rsa:2048 -keyout server.key -out server.csr \
-subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=Ghimi Technology/OU=Ghimi Blog/CN=blog.ghimi.top"
# 3. 生成 server 证书,由 ca证书颁发
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -extensions SAN \
-extfile <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:dns.ghimi.top,IP:127.0.0.1,IP:::1"))
# 将 crt 证书转换为 pkcs12 格式,生成 server.p12 文件,密码 123456
openssl pkcs12 -export -in server.crt -inkey server.key -CAfile ca.crt \
-password pass:123456 -name server -out server.p12
# 导出服务器证书和证书私钥为 java keystore 格式 server.jks 为最终的导出结果 密码 123456
keytool -importkeystore -srckeystore server.p12 -destkeystore server.jks \
-srcstoretype pkcs12 -deststoretype jks -srcalias server -destalias server \
-deststorepass 123456 -srcstorepass 123456
# 将 ca 证书导入到 server.jks 中
keytool -importcert -keystore server.jks -file ca.crt -alias ca -storepass 123456 -noprompt
popd || exit
构建 Grpc 服务
首先我们需要创建一个 Maven 工程,并编写 gRPC 相关的服务器代码:
添加 gRPC 所需要的相关依赖:
<!-- grpc 关键依赖-->
io.grpc:grpc-netty-shaded:jar:1.64.0:runtime -- module io.grpc.netty.shaded [auto]
io.grpc:grpc-protobuf:jar:1.64.0:compile -- module io.grpc.protobuf [auto]
io.grpc:grpc-stub:jar:1.64.0:compile -- module io.grpc.stub [auto]
io.grpc:grpc-netty:jar:1.64.0:compile -- module io.grpc.netty [auto]
用 protobuf 生成一个 Java gRPC模板:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "service";message HelloReq {string name = 1;
}
message HelloResp {string greeting = 1;
}
service HelloService {rpc hello(HelloReq) returns (HelloResp);
}
然后在 pom.xml 添加 prptobuf 生成插件:
<!-- project.build.plugins -->
<plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>0.6.1</version><configuration><protocArtifact>com.google.protobuf:protoc:3.25.1:exe:${os.detected.classifier}</protocArtifact><pluginId>grpc-java</pluginId><pluginArtifact>io.grpc:protoc-gen-grpc-java:1.64.0:exe:${os.detected.classifier}</pluginArtifact><!--设置grpc生成代码到指定路径--><!--<outputDirectory>${project.build.sourceDirectory}</outputDirectory>--><!--生成代码前是否清空目录--><clearOutputDirectory>true</clearOutputDirectory></configuration><executions><execution><goals><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions>
</plugin>
注意在指定 protoc 的版本时要和上面 grpc 依赖的 protobuf 版本保持一致,否则可能会出现类找不到的报错。
然后执行执行 Maven 命令生成 Protobuf 对应的 Java 代码:
mvn protobuf:compile protobuf:compile-custom
之后就可以基于生成的 Protobuf Java 代码编写一个 gRPC Server 了 :
public static void main(String[] args) throws IOException, InterruptedException {TlsServerCredentials.Builder tlsBuilder = TlsServerCredentials.newBuilder();File serverCert = new ClassPathResource("/x509/server.crt").getFile();File serverKey = new ClassPathResource("/x509/server.key").getFile();File caCert = new ClassPathResource("/x509/ca.crt").getFile();ServerCredentials credentials = tlsBuilder.trustManager(caCert).keyManager(serverCert, serverKey).build();// ServerCredentials credentials = InsecureServerCredentials.create(); // 不建议使用,非常坑Server server = Grpc.newServerBuilderForPort(443, credentials).addService(new HelloImpl()).build();server.start().awaitTermination();
}static class HelloImpl extends HelloServiceGrpc.HelloServiceImplBase {@Overridepublic void hello(HelloReq request, StreamObserver<HelloResp> responseObserver) {String msg = "hello " + request.getName() + " from server";System.out.println("server received a req,reply: " + msg);HelloResp res = HelloResp.newBuilder().setGreeting(msg).build();responseObserver.onNext(res);responseObserver.onCompleted();}
}
尝试启动 GrpcServer ,检查端口是否已被监听,当前端口绑定在 443 上,这里 GrpcServer 的服务器证书一定要配置.
编写 GrpcClient 代码:
public static void main(String[] args) throws InterruptedException, IOException {// 当服务器配置了证书时需要指定 ca 证书TlsChannelCredentials.Builder tlsBuilder = TlsChannelCredentials.newBuilder();File caCert = new ClassPathResource("/x509/ca.crt").getFile();ChannelCredentials credentials = tlsBuilder.trustManager(caCert).build();// 不做服务器证书验证时使用这个// ChannelCredentials credentials = InsecureChannelCredentials.create();ManagedChannelBuilder<?> builder = Grpc.newChannelBuilder("127.0.0.1:7443", credentials);ManagedChannel channel = builder.build();HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel);service.HelloReq.Builder reqBuilder = service.HelloReq.newBuilder();HelloResp resp = stub.hello(reqBuilder.setName("ghimi").build());System.out.printf("success greeting from server: %s", resp.getGreeting());channel.shutdown().awaitTermination(5, TimeUnit.MINUTES);
}
执行 GrpcClient,调用 443 端口的 GrpcServer 查看执行效果:
现在我们就可以开发 Spring Cloud Gateway 了,首先添加依赖,我这里添加了 spring-cloud-starter-gateway:3.1.9 版本(为了适配 Java8,已经升级 Java11 的可以提升至更高版本)。
org.springframework.cloud:spring-cloud-starter-gateway:3.1.9
编写 GrpcGateway 启动类:
@SpringBootApplication
public class GrpcGateway {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(GrpcGateway.class, args);}
}
先不做配置尝试运行一下,看下是否能够正常运行:
可以看到成功监听到了 8080 端口,这是 Spring Cloud Gateway 的默认监听端口,现在我们在 /src/main/resources/
目录下添加 application.yml
配置,配置代理 grpc 端口:
server:port: 7443 #端口号http2:enabled: truessl:enabled: truekey-store: classpath:x509/server.p12key-store-password: 123456key-store-type: pkcs12key-alias: server
spring:application:name: scg_grpccloud:gateway: #网关路由配置httpclient:ssl:use-insecure-trust-manager: true
# trustedX509Certificates:
# - classpath:x509/ca.crtroutes:- id: user-grpc #路由 id,没有固定规则,但唯一,建议与服务名对应uri: https://[::1]:443 #匹配后提供服务的路由地址predicates:#以下是断言条件,必选全部符合条件- Path=/** #断言,路径匹配 注意:Path 中 P 为大写- Header=Content-Type,application/grpcfilters:- AddResponseHeader=X-Request-header, header-value
添加 application.yml
后,重启 Spring Cloud Gateway
尝试用 GrpcClient 调用 7443 代理端口,可以看到请求成功:
报错分析
GrpcServer 和 GrpcClient 如果都配置了 InsecureServerCredentials 的情况下, GrpcClient 可以直接调用 GrpcServer 成功:
GrpcServer
TlsServerCredentials.Builder tlsBuilder = TlsServerCredentials.newBuilder();
ServerCredentials credentials = InsecureServerCredentials.create(); // 配置通过 h2c(http2 clear text) 协议访问
Server server = Grpc.newServerBuilderForPort(443, credentials).addService(new HelloImpl()).build();
server.start().awaitTermination();
GrpcClient
ChannelCredentials credentials = InsecureChannelCredentials.create(); // 通过 h2c 协议访问 GrpcServer
tlsBuilder.requireFakeFeature();
ManagedChannelBuilder<?> builder = Grpc.newChannelBuilder("127.0.0.1:443", credentials);
ManagedChannel channel = builder.build();
HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel);
service.HelloReq.Builder reqBuilder = service.HelloReq.newBuilder();
HelloResp resp = stub.hello(reqBuilder.setName("ghimi").build());
System.out.printf("success greeting from server: %s\n", resp.getGreeting());
channel.shutdown().awaitTermination(5, TimeUnit.MINUTES);
此时使用 GrpcClient 调用 GrpcServer ,可以调用成功:
但是,如果中间添加了 Spring Cloud Gateway 的话, Grpc Server 和 Grpc Client 就都不能使用 InsecureCredentials 了, Spring Cloud Gateway 在这种场景下无论与 client 还是和 server 通信都会由于不识别的协议格式而报错:
如果 GrpcServer 没有配置服务器证书而是使用了 InsecureServerCredentials.create()
,GrpcClient 虽然不使用证书访问能够直接验证成功,但是如果中间通过 GrpcGateway 的话这种机制就有可能出现问题,因为 GrpcGateway 与 GrpcServer 之间的通信是基于 Http2 的,而非 Grpc 特定的协议,在 GrpcServer 没有配置服务器证书的情况下处理的包可能会导致 GrpcGateway 无法识别,但是如果 GrpcServer 配置了证书后 GrpcGateway 就能够正常验证了。
GrpcServer 在没有配置证书的情况下通过 Srping Cloud Gateway 的方式进行代理,并且 Spring Cloud Gateway 的 spring.cloud.gateway.http-client.ssl.use-insecure-trust-manager=true
的场景下 GrpcClient 访问 Spring Cloud Gateway 会报错:
GrpcClient 报错信息:
Exception in thread "main" io.grpc.StatusRuntimeException: UNKNOWN: HTTP status code 500
invalid content-type: application/json
headers: Metadata(:status=500,x-request-header=header-value,content-type=application/json,content-length=146)
DATA-----------------------------
{"timestamp":"2024-06-28T13:18:03.455+00:00","path":"/HelloService/hello","status":500,"error":"Internal Server Error","requestId":"31f8f577/1-8"}at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:268)at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:249)at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:167)at service.HelloServiceGrpc$HelloServiceBlockingStub.hello(HelloServiceGrpc.java:160)at com.example.GrpcClient.main(GrpcClient.java:30)
报错信息解析,GrpcClient 报错结果来自于 Spring Cloud Gateway ,返回结果为不识别的返回内容 invalid content-type: application/json
这是由于 Spring Cloud Gateway 返回了的报错信息是 application/json
格式的,但是 GrpcClient 通过 grpc 协议通信,因此会将错误格式错误直接返回而非正确解析错误信息.
GrpcGateway 报错信息:
io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 00001204000000000000037fffffff000400100000000600002000000004080000000000000f0001at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1313) ~[netty-handler-4.1.100.Final.jar:4.1.100.Final]Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):*__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]*__checkpoint ⇢ HTTP POST "/HelloService/hello" [ExceptionHandlingWebHandler]
Original Stack Trace:at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1313) ~[netty-handler-4.1.100.Final.jar:4.1.100.Final]at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1383) ~[netty-handler-4.1.100.Final.jar:4.1.100.Final]
这里就是的报错信息是 GrpcGateway 无法正确解析来自 GrpcServer 的 http2 的包信息而产生的报错.这是由于 GrpcGateway 与 GrpcServer 在 h2c(Http2 Clean Text) 协议上的通信格式存在差异,从而引发报错.
最后是来自 GrpcServer 的报错:
6月 28, 2024 9:18:03 下午 io.grpc.netty.shaded.io.grpc.netty.NettyServerTransport notifyTerminated
信息: Transport failed
io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception: HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: 16030302650100026103036f6977c824c322105c600bd1dbat io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception.connectionError(Http2Exception.java:109)at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.readClientPrefaceString(Http2ConnectionHandler.java:321)at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.decode(Http2ConnectionHandler.java:247)at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:453)
这里就是 GrpcServer 与 GrpcGateway 通信过程由于协议包无法识别导致通信终止,从而引发报错.
报错场景2
在 Spring Cloud Gateway 的 application.yml 中同时配置了 use-insecure-trust-manager: true
和 trustedX509Certificates
导致的报错:
spring:cloud:gateway: #网关路由配置httpclient:ssl:use-insecure-trust-manager: truetrustedX509Certificates:- classpath:x509/ca.crt
use-insecure-trust-manager: true
表示在于 GrpcServer 通信的过程中不会验证服务器证书,这样如果证书存在什么问题的情况下就不会引发报错了,但是在同时配置了 use-insecure-trust-manager: true
和 trustedX509Certificates
的情况下 use-insecure-trust-manager: true
选项是不生效的,Spring Cloud Gateway 会还是尝试通过配置的 ca 证书去验证服务器证书,从而引发报错,因此不要同时配置 use-insecure-trust-manager: true
和 trustedX509Certificates
这两个选项。
# 同时配置了 `use-insecure-trust-manager: true` 和 `trustedX509Certificates` 后服务证书校验失败报错
javax.net.ssl.SSLHandshakeException: No subject alternative names matching IP address 0:0:0:0:0:0:0:1 foundat java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130) ~[na:na]Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):*__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]*__checkpoint ⇢ HTTP POST "/HelloService/hello" [ExceptionHandlingWebHandler]
Original Stack Trace:
客户端通常情况下只需要配置 ca 证书,用于验证服务器证书,但是验证服务器证书这一步是可以跳过的,在一些场景下服务器证书的校验比较严格的时候容易出问题,此时可以选择不进行服务器证书校验,在 Spring Cloud Gateway 代理访问 GrpcServer 时,可以为 Spring Cloud Gateway 配置 use-insecure-trust-manager: true
来取消对 GrpcServer 的强验证。
No subject alternative names matching IP address 0:0:0:0:0:0:0:1 found
这个问题就是在校验服务器证书时,由于服务器证书校验失败导致的报错了,通常情况下, client 会校验服务器的FQDN域名信息是否与请求的连接一致:
# 请求服务器证书
openssl req -new -nodes -sha256 -newkey rsa:2048 -keyout server.key -out server.csr \
-subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=Ghimi Technology/OU=Ghimi Blog/CN=blog.ghimi.top"
上面是在使用命令生成服务器证书时配置的信息,其中 CN=blog.ghimi.top
就是我配置的域名信息,这就要求我的 GrpcServer 的 ip 地址绑定了这个域名,然后 GrpcClient 通过这个域名访问:
ManagedChannelBuilder<?> builder = Grpc.newChannelBuilder("blog.ghimi.top:7443", credentials);
在这种情况下 GrpcClient 会拿服务器返回的证书与当前连接信息进行比较,如果一致则服务器验证成功,否则验证失败并抛出异常.
在 GrpcServer 只有 ip 地址没有域名的情况下,基于域名的验证就不生效了,此时去做证书验证就一定会报错:
# 同时配置了 `use-insecure-trust-manager: true` 和 `trustedX509Certificates` 后服务证书校验失败报错
javax.net.ssl.SSLHandshakeException: No subject alternative names matching IP address 0:0:0:0:0:0:0:1 foundat java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130) ~[na:na]Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):*__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]*__checkpoint ⇢ HTTP POST "/HelloService/hello" [ExceptionHandlingWebHandler]
Original Stack Trace:
报错信息中提到的 subject alternative names
就是在域名失效后的另外一种验证手段,他要求ca在签发服务器证书时向服务器证书中添加一段附加信息,这个信息中可以添加证书的可信 ip 地址:
# 通过 ca 证书颁发服务器证书
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -extensions SAN \
-extfile <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:dns.ghimi.top,IP:127.0.0.1"))
上面脚本中的 IP:127.0.0.1
就是添加的可信地址,我们可以同时添加多个服务器地址,以上面的报错为例,我们只需要在生成服务器证书的时候添加 ::1
的本地 ipv6 地址即可修复该错误:
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -extensions SAN \
-extfile <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:dns.ghimi.top,IP:127.0.0.1,IP:::1"))
报错场景4 使用 pkcs12 配置了多张自签名 ca 证书识别失效问题
解决方案,改为使用 Java Keystore 格式的证书即可修复.
参考资料
- Spring Cloud Gateway and gRPC
- spring-cloud-gateway-grpc
- gRPC-Spring-Boot-Starter 文档
- rx-java
- Working with Certificates and SSL
- 介绍一下 X.509 数字证书中的扩展项 subjectAltName
相关文章:
![](https://img-blog.csdnimg.cn/direct/c622bf228e034f27b20f352728c596da.png)
【笔记】Spring Cloud Gateway 实现 gRPC 代理
Spring Cloud Gateway 在 3.1.x 版本中增加了针对 gRPC 的网关代理功能支持,本片文章描述一下如何实现相关支持.本文主要基于 Spring Cloud Gateway 的 官方文档 进行一个实践练习。有兴趣的可以翻看官方文档。 由于 Grpc 是基于 HTTP2 协议进行传输的,因此 Srping …...
![](https://img-blog.csdnimg.cn/direct/fa793ea5619a49e586feabbe1dda4c6a.png)
云顶之弈数据网站
摘要:随着云顶之弈游戏的广泛流行,玩家对于游戏数据的查询和最新资讯的获取需求呈现出显著增长的趋势。设计一款云顶之弈数据网站,为玩家提供便捷、高效的数据查询和资讯浏览服务,能满足玩家对于游戏数据的快速查询和实时资讯获取…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux(Ubuntu)下源码开发整个流程完成版本(下载->编译->模拟器运行)
写这篇文章没别的意思, 年纪大了记性不好, 这次工作中下载,编译遇到了一些之前没遇到的问题,所以就所幸记录一下, 以便日后能快速查阅 好了, 正题开始 首先我们下载AOSP源代码开始 AOSP源代码下载 首先找到官网https://source.android.google.cn/ 进入后最上面点击获取源代…...
![](https://www.ngui.cc/images/no-images.jpg)
el-form表单实现校验
前端表单实现, rules 属性传入约定的验证规则,并将 form-Item 的 prop 属性设置为需要验证的特殊键值即可。 <el-form ref"ruleFormRef" :model"interviewForm" label-position"left" require-asterisk-position"…...
![](https://www.ngui.cc/images/no-images.jpg)
一台TrinityCore服务器客户端连接网速慢(未解决)
在FreeBSD开bhyve安装Ubuntu,然后安装了TrinityCore服务器,在只是经过一层NAT,两边都是局域网的情况下,连接速度竟然很慢,慢到600ms。 服务器安装见:尝试在FreeBSD 的jail、bhyve里安装TrinityCore-CSDN博…...
![](https://img-blog.csdnimg.cn/direct/59c0aa8eaf5f457894b504fbae7e85a5.png)
[系统运维|Xshell]宿主机无法连接上NAT网络下的虚拟机进行维护?主机ping不通NAT网络下的虚拟机,虚拟机ping的通主机!解决办法
遇到的问题:主机ping不通NAT网络下的虚拟机,虚拟机ping的通主机 服务器:Linux(虚拟机) 主机PC:Windows 虚拟机:vb,vm测试过没问题,vnc没测试不清楚 虚拟机网络࿱…...
![](https://www.ngui.cc/images/no-images.jpg)
C 语言实例 - 查找数组中最大的元素值
查找数组中最大的元素值。 实例 1 #include <stdio.h>int main() {int array[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};int loop, largest;largest array[0];for(loop 1; loop < 10; loop) {if( largest < array[loop] ) largest array[loop];}printf("最大…...
![](https://www.ngui.cc/images/no-images.jpg)
MySQL之可扩展性(七)
可扩展性 通过集群扩展 理想的扩展方案时单一逻辑数据库能够存储尽可能多的数据,处理尽可能多的查询,并如期望的那样增长。许多人的第一想法就是建立一个"集群"或者"网格"来无缝处理这些事情,这样应用就无须去做太多工…...
![](https://img-blog.csdnimg.cn/direct/7a6cb3e136c1422f9829c181cadbf1f0.png)
微服务框架中Nacos的个人学习心得
微服务框架需要学习的东西很多,基本上我把它分为了五个模块: 第一:微服务技术模块 分为三个常用小模块: 1.微服务治理: 注册发现 远程调用 配置管理 网关路由 2.微服务保护: 流量控制 系统保护 熔断降级 服…...
![](https://img-blog.csdnimg.cn/direct/a795e0f98e7648dea2754d064fb778ac.png)
Unity Animator 运行时修改某个动画状态的播放速度
1.添加动画参数,选择需要动态修改速度的动画状态 2.在属性面板种设置速度倍速参数...
![](https://img-blog.csdnimg.cn/direct/4f415a0a41084562ab867cec2b2a1fee.png)
阿里云常用的操作
阿里云常见的产品和服务 容器服务 可以查看容器日志、监控容器cpu和内存, 日志服务 SLS 可以查看所有服务的日志, Web应用防火墙 WAF 可以查看 QPS. 阿里云查看集群: 点击 “产品和服务” 中的 容器服务,可以查看 集群列表&…...
![](https://img-blog.csdnimg.cn/direct/334ac8248b044115935b537b6aa99ff0.png)
【MATLAB源码-第231期】基于matlab的polar码编码译码仿真,对比SC,SCL,BP,SCAN,SSC等译码算法误码率。
操作环境: MATLAB 2022a 1、算法描述 极化码(Polar Code) 极化码(Polar Code)是一种新型的信道编码技术,由土耳其裔教授Erdal Arıkan在2008年提出。极化码在理论上被证明能够在信道容量上达到香农极限…...
![](https://img-blog.csdnimg.cn/direct/54c6a92dd39d4e76ab50ef22b2465aeb.png)
创新实训(十三) 项目开发——实现用户终止对话功能
思路分析: 如何实现用户终止AI正在进行的回答? 分析实现思路如下: 首先是在用户点击发送后,切换终止对话,点击后大模型终止对话,停止sse,不再接收后端的消息。同时因为对话记录存入数据库是后…...
![](https://img-blog.csdnimg.cn/direct/9eb3cc9cdeca4be39b4f584fa4dd30dd.png)
基于Java+MySQL停车场车位管理系统详细设计和实现(源码+LW+调试文档+讲解等)
💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,…...
![](https://www.ngui.cc/images/no-images.jpg)
LeetCode 53.最大子数组和(dp)
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。 示例 1: 输入:nums [-2,1,-3,4,-1,2,1,-5,4] 输出:…...
![](https://img-blog.csdnimg.cn/direct/04aa268893344d0b9d71d4740fe69f72.png)
IOS17闪退问题Assertion failure in void _UIGraphicsBeginImageContextWithOptions
最近项目更新到最新版本IOS17,发现一个以前的页面突然闪退了。原来是IOS17下,这个方法 UIGraphicsBeginImageContext(CGSize size) 已经被移除,原参数如果size为0的话,会出现闪退现象。 根据说明,上述方法已经被替换…...
![](https://img-blog.csdnimg.cn/2d61eca442984641b8abef076b4951b4.jpg)
float8格式
产生背景 在人工智能神经元网络中,一个参数用1字节表示即可,或者说,这是个猜想:因为图像的颜色用8比特表示就够了,所以说,猜想神经元的区分度应该小于256。 数字的分配 8比特有256个码位,分为…...
![](https://img-blog.csdnimg.cn/direct/011df70966a14d8cb89fdbcd22399c1e.png)
云效BizDevOps上手亲测
云效BizDevOps上手亲测 什么是云效项目协作Projex配置2023业务空间原始诉求字段原始诉求工作流创建原始诉求配置2023产品空间创建主题业务原始诉求关联主题配置2023研发空间新建需求需求关联主题 与传统区别云效开发流程传统开发流程云效BizDevOps 操作体验 什么是云效 在说到…...
![](https://csdnimg.cn/release/blog_editor_html/release2.3.6/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=N7T8)
亚太杯赛题思路发布(中文版)
导读: 本文将继续修炼回归模型算法,并总结了一些常用的除线性回归模型之外的模型,其中包括一些单模型及集成学习器。 保序回归、多项式回归、多输出回归、多输出K近邻回归、决策树回归、多输出决策树回归、AdaBoost回归、梯度提升决策树回归…...
![](https://www.ngui.cc/images/no-images.jpg)
【Linux】部署 GitLab 服务
1、配置实验环境 安装git apt install git 安装docker apt install docker 安装tree apt install tree 2、安装 Gitlab 下载官方库与安装包 下载官方库的安装脚本 curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bas…...
![](https://img-blog.csdnimg.cn/direct/bc3bda3063364b979425b1b56bcceaa7.png)
cs与msf权限传递以及mimikatz抓取win2012明文密码
启动服务端 进入客户端 建立监听 制作脚本 客户端运行程序 主机上线 打开msf 调用handler模块 创建监听 11.cs->msf 传递会话 12.传参完成 msf->cs会话传递 抓取密码(null) 修改注册表 shell reg add "HKEY_LOC…...
![](https://img-blog.csdnimg.cn/img_convert/5004eb9dc4eb7806dcc28ccb6dbf3d44.png)
C++ 矩阵的最小路径和解法
描述 给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。 数据范围: 1≤𝑛,𝑚≤5001≤n,m≤500,矩阵中任意值都满足 0≤𝑎𝑖,𝑗≤1000≤ai,j≤100 要求…...
![](https://img-blog.csdnimg.cn/direct/024e433466f248e7a8de9355d5e8e890.png)
http服务网络请求如何确保数据安全(含python示例源码)
深度学习类文章回顾 【YOLO深度学习系列】图像分类、物体检测、实例分割、物体追踪、姿态估计、定向边框检测演示系统【含源码】 【深度学习】物体检测/实例分割/物体追踪/姿态估计/定向边框/图像分类检测演示系统【含源码】 【深度学习】YOLOV8数据标注及模型训练方法整体流程…...
![](https://img-blog.csdnimg.cn/direct/812ad30cae744309893406405a624db6.jpeg)
网络构建关键技术_2.IPv4与IPv6融合组网技术
互联网数字分配机构(IANA)在2016年已向国际互联网工程任务组(IETF)提出建议,要求新制定的国际互联网标准只支持IPv6,不再兼容IPv4。目前,IPv6已经成为唯一公认的下一代互联网商用解决方案&#…...
![](https://www.ngui.cc/images/no-images.jpg)
数仓建模—数据生命周期管理
数仓建模—数据生命周期管理 数据生命周期管理 (DLM) 是一种在从数据输入到数据销毁的整个生命周期内管理数据的方法。 数据根据不同的条件分处不同的阶段,随着其完成不同的任务或满足特定要求而逐次经历这些阶段。 一个出色的 DLM 流程提供针对企业数据的结构和组织,帮助实…...
![](https://www.ngui.cc/images/no-images.jpg)
【INTEL(ALTERA)】Nios II软件开发人员手册中设计位置的错误示例
目录 说明 解决方法 说明 Nios II软件开发人员手册正确无误 请参阅 Nios 中包含的Nios II硬件设计示例 II 嵌入式设计套件 (EDS)。提供设计示例 设计上 Altera网站的示例页面。 Nios II软件开发人员手册正确无误 请参阅 创建本应用程序和创建本 bsp …...
![](https://img-blog.csdnimg.cn/direct/fd997ae1e6f9451a894c6c6bf839de2a.png)
jeecg导入excel 含图片(嵌入式,浮动式)
jeecgboot的excel导入 含图片(嵌入式,浮动式) 一、啰嗦二、准备三、 代码1、代码(修改覆写的ExcelImportServer)2、代码(修改覆写的PoiPublicUtil)3、代码(新增类SAXParserHandler&a…...
![](https://www.ngui.cc/images/no-images.jpg)
GPT-5 一年半后发布?对此你有何期待?
GPT-5 一年半后发布?对此你有何期待? IT之家6月22日消息,在美国达特茅斯工程学院周四公布的采访中,OpenAI首席技术官米拉穆拉蒂被问及GPT-5是否会在明年发布,给出了肯定答案并表示将在一年半后发布。此外,…...
![](https://img-blog.csdnimg.cn/direct/410767c8969f4229974ee7bbd37163f3.png#pic_center)
SHELL脚本学习(十二)sed进阶
一、多行命令 概述 sed 编辑器的基础命令都是对一行文本进行操作。如果要处理的数据分布在多行中,sed基础命令是没办法处理的。 幸运的是,sed编辑器的设计人员已经考虑了这个问题的解决方案。sed编辑器提供了3个处理多行文本的特殊命令。 命令描述N加…...
![](https://img-blog.csdnimg.cn/direct/642f518ec953404fa6e954109d5b3134.png)
【python】一篇文零基础到入门:快来玩吧~
本笔记材料源于: PyCharm | 创建你的第一个项目_哔哩哔哩_bilibili Python 语法及入门 (超全超详细) 专为Python零基础 一篇博客让你完全掌握Python语法-CSDN博客 0为什么安装python和pycharm? 不同于c,c࿰…...
![](https://img-blog.csdnimg.cn/direct/f4c7ac65a6024daa8af9900bb0860c7d.png)
Python武器库开发-武器库篇之Thinkphp5 SQL注入漏洞(六十六)
Python武器库开发-武器库篇之Thinkphp5 SQL注入漏洞(六十六) 漏洞环境搭建 这里我们使用Kali虚拟机安装docker并搭建vulhub靶场来进行ThinkPHP漏洞环境的安装,我们进入 ThinkPHP漏洞环境,可以 cd ThinkPHP,然后通过 …...
![](https://www.ngui.cc/images/no-images.jpg)
2024.6.28刷题记录
目录 一、13. 罗马数字转整数 贪心 二、16. 最接近的三数之和 排序指针 三、17. 电话号码的字母组合 dfs(深度优先搜索) 四、19. 删除链表的倒数第 N 个结点 1.模拟 2.前后同步指针 五、20. 有效的括号 栈 六、21. 合并两个有序链表 1.递归 …...
![](https://img-blog.csdnimg.cn/direct/b5090c6c9c8949a392df49767f554c4b.png)
柔性数组(flexible array)
柔性数组从C99开始支持使用 1.柔性数组的概念 概念: 结构体中,结构体最后一个元素允许是未知大小的数组,这就叫[柔性数组]的成员 struct S {int n;char arr[]; //数组大小未知(柔性数组成员) }; 柔性数组的特点: 结构体中柔性…...
![](https://www.ngui.cc/images/no-images.jpg)
服务器配置路由
translator 在Linux系统中,通过ip route add命令添加的路由规则通常不会永久保存,它们只会在当前会话中生效。当系统重新启动后,这些临时添加的路由规则会丢失。 要求在开关机之后仍然保留这条路由,需要将路由规则永久保存。在大多…...
![](https://img-blog.csdnimg.cn/direct/fc87d23fbdd9425b8aead1d3c829035c.png)
老生常谈问题之什么是缓存穿透、缓存击穿、缓存雪崩?举个例子你就彻底懂了!!
老生常谈问题之什么是缓存穿透、缓存击穿、缓存雪崩?举个例子你就彻底懂了!! 缓存穿透发生场景解决方案 缓存击穿解决方案 缓存雪崩发生场景解决方案 总结三者区分三者原因三者解决方案 想象一下,你开了一家便利店,店里…...
![](https://www.ngui.cc/images/no-images.jpg)
[code snippet] 生成随机大文件
[code snippet] 生成随机大文件 一个无聊的测试代码,因为要测试大文件的网络传输,就写了一个随机大文件生成脚本,做个备份。 基本上都是 GPT 生成的,哈哈。 C# 代码 namespace ConsolePlayground;internal class BigFileGenera…...
![](https://img-blog.csdnimg.cn/img_convert/e07122cc2600cb9e00fe95284e80f2ed.png)
计算机网路面试HTTP篇三
HTTPS RSA 握手解析 我前面讲,简单给大家介绍了的 HTTPS 握手过程,但是还不够细! 只讲了比较基础的部分,所以这次我们再来深入一下 HTTPS,用实战抓包的方式,带大家再来窥探一次 HTTPS。 对于还不知道对称…...
![](https://img-blog.csdnimg.cn/direct/efc056b146334106bf84146b3a60e94c.png#pic_center)
如何不改变 PostgreSQL 列类型#PG培训
开发应用程序并在其背后操作数据库集群时,会遇到一个意想不到的问题是实践与理论、开发环境与生产之间的差异。这种不匹配的一个完美例子就是更改列类型。 #PG考试#postgresql培训#postgresql考试#postgresql认证 关于如何在 PostgreSQL(以及其他符合 SQ…...
![](https://img-blog.csdnimg.cn/direct/ebe43044e1d94ad79e387602fb345b74.png)
RocketMQ快速入门:事务消息原理及实现(十)
目录 0. 引言1. 原理2. 事务消息的实现2.1 java client实现(适用于spring框架)2.2 springboot实现 3. 总结 0. 引言 rocketmq 的一大特性就是支持事务性消息,这在诸多场景中有所应用。在之前的文章中我们已经讲解过事务消息的使用࿰…...
![](https://img-blog.csdnimg.cn/direct/b580c553f6b0467dbbe1eddbc3d4988d.png)
Kotlin设计模式:深入理解桥接模式
Kotlin设计模式:深入理解桥接模式 在软件开发中,随着系统需求的不断增长和变化,类的职责可能会变得越来越复杂,导致代码难以维护和扩展。桥接模式(Bridge Pattern)是一种结构型设计模式,它通过…...
![](https://img-blog.csdnimg.cn/direct/ef88994c03df40adaf2d58ef9dc652e3.png)
常用MQ消息中间件Kafka、ZeroMQ和RabbitMQ对比及RabbitMQ详解
1、概述 在现代的分布式系统和实时数据处理领域,消息中间件扮演着关键的角色,用于解决应用程序之间的通信和数据传递的挑战。在众多的消息中间件解决方案中,Kafka、ZeroMQ和RabbitMQ 是备受关注和广泛应用的代表性系统。它们各自具有独特的特…...
![](https://img-blog.csdnimg.cn/direct/411f6df9f19b4f4498189ef6ad961138.png)
【UE5.3】笔记6-第一个简单小游戏
打砖块小游戏: 1、制造一面砖块组成的墙 在关卡中放置一个cube,放这地面上,将其转换成蓝图类,改名BP_Cube,更换砖块的贴图,按住alt键进行拷贝,堆出一面墙,复制出来的会很多,全选移动…...
![](https://img-blog.csdnimg.cn/direct/b88f22e37f4d42e890dce361df27ac8f.png)
LeetCode---402周赛
题目列表 3184. 构成整天的下标对数目 I 3185. 构成整天的下标对数目 II 3186. 施咒的最大总伤害 3187. 数组中的峰值 一、构成整天的下标对数目 I & II 可以直接二重for循环暴力遍历出所有的下标对,然后统计符合条件的下标对数目返回。代码如下 class So…...
![](https://www.ngui.cc/images/no-images.jpg)
循环冗余校验
循环冗余校验(Cyclic Redundancy Check,简称CRC)是一种广泛使用的错误检测编码技术,用于检测数据在传输或存储过程中是否发生错误。CRC通过在数据后面添加一个校验值(通常称为CRC码或CRC校验和)来实现错误检…...
![](https://www.ngui.cc/images/no-images.jpg)
resample sensor
resample sensor 的一个问题。 背景: 项目要求,发送多个数据到 sensor-hal 上去,发现无论怎样,在 sensor-hal 上都 只有一个数据。 resample sensor 是重新采样,这个怎么理解的,我的理解是: 假设 sensor 采…...
![](https://img-blog.csdnimg.cn/direct/573bb8e53f724552b336e5db5a3a291a.png)
【Linux】多线程的相关知识点
一、线程安全 1.1 可重入 VS 线程安全 1.1.1 概念 线程安全:多个线程并发执行同一段代码时,不会出现不同的结果。常见对全局变量或者静态变量进行操作,并且没有锁的保护的情况下,会出现问题。重入:同一个函数被不同…...
![](https://www.ngui.cc/images/no-images.jpg)
Java反射详解
Java反射 一.什么是反射 我们使用的一些像框架,tomcat,或者一些其他的组件(jackson 对象–>json)。他们可以做到给他什么类名,就可以创建给定类的对象,并调用该对象的方法和属性。这是如何做到的? 当他们加载我们…...
![](https://www.ngui.cc/images/no-images.jpg)
Spring Boot与Apache Kafka集成的深度指南
Spring Boot与Apache Kafka集成的深度指南 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在现代分布式系统中,消息队列的作用愈发重要࿰…...
![](https://img-blog.csdnimg.cn/direct/3ddb2ad2267c45d9a93acb9840c53a42.png#pic_center)
甄选版“论软件系统架构评估”,软考高级论文,系统架构设计师论文
论文真题 对于软件系统,尤其是大规模的复杂软件系统来说,软件的系统架构对于确保最终系统的质量具有十分重要的意义,不恰当的系统架构将给项目开发带来高昂的代价和难以避免的灾难。对一个系统架构进行评估,是为了:分析现有架构存在的潜在风险,检验设计中提出的质量需求,…...
![](https://img-blog.csdnimg.cn/direct/237c24e3f43148d5ad9d145e857c75c8.png)
uniapp开发企业微信内部应用
最近一直忙着开发项目,终于1.0版本开发完成,抽时间自己总结下在项目开发中遇到的技术点。此次项目属于自研产品,公司扩展业务,需要在企业微信中开发内部应用。因为工作中使用的是钉钉,很少使用企业微信,对于…...
![](https://www.ngui.cc/images/no-images.jpg)
重生之我要学后端01--后端语言选择和对应框架选择
编程语言 后端开发通常需要掌握至少一种编程语言。以下几种语言在后端开发中非常流行: Java:广泛用于企业级应用程序。Python:因其易学性和强大的库支持(如Django和Flask)而受欢迎。Node.js(JavaScript&a…...
![](https://img-blog.csdnimg.cn/direct/ed8e5b33509d4281b20f2602bc93e0be.png)
C++ 和C#的差别
首先把眼睛瞪大,然后憋住一口气,读下去: 1、CPP 就是C plus plus的缩写,中国大陆的程序员圈子中通常被读做"C加加",而西方的程序员通常读做"C plus plus",它是一种使用非常广泛的计算…...
![](https://img-blog.csdnimg.cn/direct/512eaab3189146f5960f1f24a18df6f1.png)
每周题解:最大半连通子图
题目链接 最大半连通子图 题目描述 一个有向图 G ( V , E ) G\left(V,E\right) G(V,E) 称为半连通的 (Semi-Connected),如果满足: ∀ u , v ∈ V \forall u,v\in V ∀u,v∈V,满足 u → v u\to v u→v 或 v → u v\to u v→u࿰…...
![](https://www.ngui.cc/images/no-images.jpg)
微信小程序文件结构示例
微信小程序文件结构示例 miniprogram │ ├── app.js // 小程序逻辑 ├── app.json // 全局配置 ├── app.wxss // 全局样式 │ ├── pages // 页面文件夹 │ ├── index // 首页 │ │ ├── index.js // 页面逻辑 │ │ ├── index.json // 页面配置 │ │ ├─…...
![](https://www.ngui.cc/images/no-images.jpg)
深⼊理解MySQL Innodb存储引擎的缓冲池、事务、索引底层工作原理,掌握 MySQL 主从同步,读写分离技术以及集群的搭建,具备分库分表,SQL调优经验
深入理解MySQL的InnoDB存储引擎是数据库管理员和开发人员的重要技能。以下是对InnoDB存储引擎的缓冲池、事务、索引以及主从同步、读写分离技术和集群搭建的详细原理介绍: ### InnoDB存储引擎 1. **缓冲池(Buffer Pool)**: - 缓冲池是InnoDB存储引擎…...
![](https://img-blog.csdnimg.cn/img_convert/254a4c3c21e1abf35046a06bcf1a842e.gif)
Docker-compose 实现Prometheus+Grafana监控MySQL及Linux主机
. ├── Grafana │ ├── data │ └── docker-compose.yaml ├── Mysql │ ├── conf │ ├── data │ ├── docker-compose.yaml │ └── logs ├── Mysqld_exporter │ ├── conf │ └── docker-compose.yaml ├── node-exporter │…...
![](https://www.ngui.cc/images/no-images.jpg)
续写广交会篇章骆驼蓄电池国际版向新而行
近日,第135届广交会在广州落下帷幕。开幕以来,这场被誉为中国第一展的盛会成为了全球贸易的焦点,让更多中国造走向世界,写下贸易强国的新篇章。骆驼蓄电池作为中国汽车低压电池行业前列的蓄电池品牌,同样将中国质造的蓄电池产品推向五湖四海。骆驼蓄电池在汽车低压电池制造…...
![](https://img-blog.csdnimg.cn/direct/9b0d4fc92ac447cf8a21c58beec74e15.png)
【Linux 网络编程】网络的基础知识详解!
文章目录 1. 计算机网络背景2. 认识 "协议"3. 协议分层 1. 计算机网络背景 网络互联: 多台计算机连接在一起, 完成数据共享; 🍎局域网(LAN----Local Area Network): 计算机数量更多了, 通过交换机和路由器连接。 🍎 广…...
![](https://img-blog.csdnimg.cn/img_convert/40c1cf1224b97ee07e0eddede4915b92.png)
【openlayers系统学习】1.6下载要素,将要素数据序列化为 GeoJSON并下载
六、下载要素 下载要素 上传数据并编辑后,我们想让用户下载结果。为此,我们将要素数据序列化为 GeoJSON,并创建一个带有 download 属性的 <a> 元素,该属性会触发浏览器的文件保存对话框。同时,我们将在地图…...
![](https://www.ngui.cc/images/no-images.jpg)
解读一下15.52.34.160/27
IP地址15.52.34.160/27可以分解为两部分来解读: IP地址: 15.52.34.160 这是分配给网络接口的地址,用于在网络中标识一个特定的设备。 子网掩码: /27 这表示子网掩码是27位长,意味着网络部分占据了IP地址的前27位,剩下的5位用于主…...
![](https://img-blog.csdnimg.cn/img_convert/336067fe50dfc9d0eef6ce69f2592c19.png)
搜维尔科技:Movella Xsens用于动画,CG,短视频制作案例
用户名称 广州百漫文化传播有限公司 应用场景 基于Xsens MVN Link 动作捕捉系统的动画制作、CG制作、短视频制作、快速动画MAYA插件、影视动漫实时合成预渲染。 现场照片 《西行纪》内容简介:在远古神明的年代,世间存在着天众、龙众、阿修罗等八部众…...
![](https://img-blog.csdnimg.cn/img_convert/2359ad83ce8e09195f0cc60f54ea9397.webp?x-oss-process=image/format,png)
Hotcoin Research | 市场洞察:2024年5月13日-5月19日
加密货币市场表现 目前,加密货币总市值为1.32万亿,BTC占比54.41%。 本周行情呈现震荡上行的态势,BTC在5月15日-16日,有一波大的拉升,周末为震荡行情。BTC现价为67125美元。 上涨的主要原因:美国4月CPI为3…...