背景:

        前端:angular 12,websocket接口由lib.dom.d.ts提供

        后端:java,websocket接口由jetty 12提供

问题现象:

        前端连上server后,每隔30s就会断开,由于长时间空闲,会导致websocket连接断开,所以前端也发送了ping报文(由于前端接口没有单独的ping/ping接口,因此ping报文和普通报文一样,都是调用的send()方法),每隔30s发一次。当然前端可实现以重连机制,但是这样就会出现反复重连的情况,会导致界面感知不友好,所以还是得找下根本原因。

前端打印的日志:

后端打印的日志:

onWebSocketClose, statusCode=1005, reason=null

前后端都没有断连的具体原因,只有状态码,这就很难办了。 为了省事,我用gpt搜出来的常见状态码如下:

从上图可以看出,不管是1005还是1006,都表示没有收到关闭帧的异常关闭。

 排查思路:

        因为客户端周期性的发送了ping报文,所以先排查下是不是服务端的空闲超时时间太短了导致的?

        // 显式创建 ServerConnector 并设置空闲超时ServerConnector connector = new ServerConnector(server);connector.setPort(port);connector.setIdleTimeout(86400000); // 1 天(毫秒)

上面的代码就是修改空闲超时时间,先设置为一天,然后重新测试,发现还是不行,前端还是会不断重连。

        难道设置的时间没效果?那就把jetty的日志打开,日志如下:

DEBUG 25-07-25 14:25:59.133 org.eclipse.jetty.websocket.core.server.internal.AbstractHandshaker.upgradeRequest(AbstractHandshaker.java:116) [qtp956673894-39]
session WebSocketCoreSession@1e78624f{SERVER,WebSocketSessionState@78abbc31{CONNECTING,i=NO-OP,o=NO-OP,c=null},[ws://10.10.10.10:8080/mq?token=test,null,false.[permessage-deflate]],af=true,i/o=4096/4096,fs=65536}->JettyWebSocketFrameHandler@6a65aae4[com.nsb.enms.notification.server.WebSocketServer]DEBUG 25-07-25 14:25:59.134 org.eclipse.jetty.io.IdleTimeout.setIdleTimeout(IdleTimeout.java:85) [qtp956673894-39]
Setting idle timeout 86400000 -> 86400000 on SocketChannelEndPoint@202ab0ab[{l=/10.10.10.10:8080,r=/20.20.20.20:45678,OPEN,fill=-,flush=-,to=6/86400000}{io=0/0,kio=0,kro=1}]->[HttpConnection@7fb68543[p=HttpParser{s=END,0 of -1},g=HttpGenerator@7e82a7c8{s=START}]=>HttpChannelState@bd8ef5b{handling=Thread[#39,qtp956673894-39,5,main], handled=false, send=SENDING, completed=false, request=GET@68dd4ee2 http://10.10.10.10:8080/mq?token=test HTTP/1.1}]

从日志上可以看到服务端的设置是生效了的。

        既然服务端没问题,那可能是客户端的空闲超时时间导致的?查了下资料,angular自带的websocket没有设置空闲超时时间的方法。那就换个思路,用java写个客户端来测试这个问题。

import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.api.Frame;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.*;
import org.eclipse.jetty.websocket.core.OpCode;import java.nio.ByteBuffer;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;@WebSocket
public class ClientSocket {long start;public final CountDownLatch closeLatch = new CountDownLatch(1);private Session session;private ScheduledExecutorService scheduler;@OnWebSocketOpenpublic void onOpen(Session session) {this.session = session;start = System.currentTimeMillis();System.out.println("客户端:已连接到服务端,URI: " + session.getUpgradeRequest().getRequestURI() + "," + start);// 启动心跳scheduler = Executors.newSingleThreadScheduledExecutor();// 注意这里设置的间隔时间是31s
//        scheduler.scheduleAtFixedRate(this::sendPing, 0, 31, TimeUnit.SECONDS);// 注意这里设置的间隔时间是32s
//        scheduler.scheduleAtFixedRate(this::sendMSG, 0, 32, TimeUnit.SECONDS);new Thread(this::readConsoleInput).start();}@OnWebSocketMessagepublic void onMessage(Session session, String message) {System.out.println("客户端:收到服务端消息: " + message);}@OnWebSocketFramepublic void onFrame(Session session, Frame frame, Callback cb) {System.out.println("客户端:收到帧,操作码: " + frame.getOpCode());if (frame.getOpCode() == OpCode.PONG) {System.out.println("客户端:收到 PONG 帧,负载: " + frame.getPayload());}}@OnWebSocketClosepublic void onClose(Session session, int statusCode, String reason) {this.session = null;System.out.println("客户端:连接关闭,状态码: " + statusCode + ", 原因: " + reason + "," + (System.currentTimeMillis() - start));closeLatch.countDown();}@OnWebSocketErrorpublic void onError(Session session, Throwable throwable) {System.err.println("客户端:发生错误: " + throwable.getMessage() + "," + System.currentTimeMillis());throwable.printStackTrace();}private void readConsoleInput() {Scanner scanner = new Scanner(System.in);System.out.println("请输入消息(输入 'ping' 发送 PING 帧,'exit' 退出):");while (session != null && session.isOpen()) {String input = scanner.nextLine();if ("exit".equalsIgnoreCase(input)) {try {session.close(1000, "Client requested closure", Callback.from(() -> {System.out.println("客户端:消息发送成功: " + input);}, throwable -> {throwable.printStackTrace();}));} catch (Exception e) {e.printStackTrace();}break;} else if ("ping".equalsIgnoreCase(input)) {try {ByteBuffer payload = ByteBuffer.wrap("PingTest".getBytes());session.sendPing(payload, Callback.from(() -> {System.out.println("客户端:发送 PING 帧成功");}, throwable -> {throwable.printStackTrace();}));} catch (Exception e) {e.printStackTrace();}} else if (!input.trim().isEmpty()) {try {session.sendText(input, Callback.from(() -> {System.out.println("客户端:消息发送成功: " + input);}, throwable -> {throwable.printStackTrace();}));} catch (Exception e) {e.printStackTrace();}}}scanner.close();}private void sendPing() {if (session != null && session.isOpen()) {try {ByteBuffer payload = ByteBuffer.wrap("PingTest".getBytes());session.sendPing(payload, Callback.from(() -> {System.out.println("客户端:发送 PING 帧成功");}, throwable -> {throwable.printStackTrace();}));} catch (Exception e) {e.printStackTrace();}}}private void sendMSG() {if (session != null && session.isOpen()) {try {String input = String.valueOf(System.currentTimeMillis());session.sendText(input, Callback.from(() -> {System.out.println("客户端:消息发送成功: " + input);}, throwable -> {throwable.printStackTrace();}));} catch (Exception e) {e.printStackTrace();}}}
}

注意看,上面的代码,默认是把这两行代码屏蔽了的:

//        scheduler.scheduleAtFixedRate(this::sendPing, 0, 31, TimeUnit.SECONDS);
//        scheduler.scheduleAtFixedRate(this::sendMSG, 0, 32, TimeUnit.SECONDS);

这两行代码表示周期性发送ping/msg,

第一行表示每隔31s发送一次ping报文,

第二行表示每隔32s发送一次msg消息。

以下是调用代码:

import org.eclipse.jetty.websocket.client.WebSocketClient;import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;public class TestClient {public static void main(String[] args) throws Exception {String serverUri = "ws://10.10.10.10:8080/mq";WebSocketClient client = new WebSocketClient();
//        client.setMaxTextMessageSize(65536);try {client.start();System.out.println("WebSocket 客户端已启动");ClientSocket wsClient = new ClientSocket();// 设置空闲超时时间,默认注释该行
//            client.setIdleTimeout(Duration.ofSeconds(60));client.connect(wsClient, new URI(serverUri));boolean closed = wsClient.closeLatch.await(5, TimeUnit.MINUTES);if (!closed) {System.out.println("等待连接关闭超时");}} catch (Exception e) {e.printStackTrace();} finally {client.stop();System.out.println("WebSocket 客户端已停止");}}
}

注意,因为java client支持设置空闲超时时间,所以上面的代码,默认先注释掉设置空闲超时时间的代码。执行上述代码,等待一会,可以看到如下输出日志:

WebSocket 客户端已启动
客户端:已连接到服务端,URI: ws://10.10.10.10:8080/mq,1753427445848
请输入消息(输入 'ping' 发送 PING 帧,'exit' 退出):
客户端:消息发送成功: 1753427445852
客户端:发生错误: Connection Idle Timeout,1753427475886
org.eclipse.jetty.websocket.api.exceptions.WebSocketTimeoutException: Connection Idle Timeoutat org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler.convertCause(JettyWebSocketFrameHandler.java:436)at org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler.onError(JettyWebSocketFrameHandler.java:240)...
Caused by: org.eclipse.jetty.websocket.core.exception.WebSocketTimeoutException: Connection Idle Timeout... 10 more
Caused by: java.util.concurrent.TimeoutException: Idle timeout expired: 30011/30000 msat org.eclipse.jetty.io.IdleTimeout.checkIdleTimeout(IdleTimeout.java:167)... 7 more
客户端:连接关闭,状态码: 1001, 原因: Connection Idle Timeout,30040
WebSocket 客户端已停止

从日志上可以得知,关闭原因是:Connection Idle Timeout,30040,说明连接空闲时间超过了30s导致客户端被关闭。

服务端也是打印的相同的日志:

onWebSocketClose, statusCode=1001, reason=Connection Idle Timeout, 

因为服务器端的空闲超时时间设置的1天,由此说明,连接断开是受客户端的空闲超时时间影响的,从日志上也可以得出,默认情况下,客户端的空闲超时时间就是30s

        我们前面提到的几行注释代码,就是为了验证这个30s的问题,接下来,挨个测试下那些被注释的代码,看下都有什么输出的结果。

验证代码:

测试1:设置客户端的超时时间

放开TestClient下的代码:

client.setIdleTimeout(Duration.ofSeconds(60));

这个表示空闲超时时间为60s后,重新执行测试用例,输出如下:

WebSocket 客户端已启动
客户端:已连接到服务端,URI: ws://10.10.10.10:8080/mq,1753428684378
请输入消息(输入 'ping' 发送 PING 帧,'exit' 退出):
客户端:发生错误: Connection Idle Timeout,1753428744397
...
Caused by: org.eclipse.jetty.websocket.core.exception.WebSocketTimeoutException: Connection Idle Timeout... 10 more
Caused by: java.util.concurrent.TimeoutException: Idle timeout expired: 60005/60000 msat org.eclipse.jetty.io.IdleTimeout.checkIdleTimeout(IdleTimeout.java:167)... 7 more
客户端:连接关闭,状态码: 1001, 原因: Connection Idle Timeout,60020
WebSocket 客户端已停止

日志显示60s之后才报超时,说明前面设置的超时代码生效了。

测试2:周期性发送ping报文

先注释掉TestClient的60s超时机制,保持默认30s,然后,将ClientSocket下的周期性发送ping报文的代码打开,间隔为31s。

TestClient.java 修改如下:

            // TestClient.java 中注释该行
//            client.setIdleTimeout(Duration.ofSeconds(60));

ClientSocket.java 修改如下: 

// ClientSocket.java 中放开该行,且周期为31s
scheduler.scheduleAtFixedRate(this::sendPing, 0, 31, TimeUnit.SECONDS);

执行结果如下:

WebSocket 客户端已启动
客户端:已连接到服务端,URI: ws://10.10.10.10:8080/mq,1753429262205
请输入消息(输入 'ping' 发送 PING 帧,'exit' 退出):
客户端:发送 PING 帧成功
客户端:收到帧,操作码: 10
客户端:收到 PONG 帧,负载: java.nio.HeapByteBufferR[pos=0 lim=8 cap=8]
客户端:发生错误: Connection Idle Timeout,1753429292256
Connection Idle Timeout... 10 more
Caused by: java.util.concurrent.TimeoutException: Idle timeout expired: 30015/30000 msat org.eclipse.jetty.io.IdleTimeout.checkIdleTimeout(IdleTimeout.java:167)... 7 more
客户端:连接关闭,状态码: 1001, 原因: Connection Idle Timeout,30053
WebSocket 客户端已停止

日志显示,问题复现,连接空闲超时超过30s 。

现在修改下ClientSocket.java代码,将超时时间设置为29s,代码如下:

// ClientSocket.java 中放开该行,且周期为29s
scheduler.scheduleAtFixedRate(this::sendPing, 0, 29, TimeUnit.SECONDS);

然后执行,输出的结果就不一样了: 

WebSocket 客户端已启动
客户端:已连接到服务端,URI: ws://10.10.10.10:8080/mq,1753429377099
请输入消息(输入 'ping' 发送 PING 帧,'exit' 退出):
客户端:发送 PING 帧成功
客户端:收到帧,操作码: 10
客户端:收到 PONG 帧,负载: java.nio.HeapByteBufferR[pos=0 lim=8 cap=8]
客户端:发送 PING 帧成功
客户端:收到帧,操作码: 10
客户端:收到 PONG 帧,负载: java.nio.HeapByteBufferR[pos=0 lim=8 cap=8]
客户端:发送 PING 帧成功
客户端:收到帧,操作码: 10
客户端:收到 PONG 帧,负载: java.nio.HeapByteBufferR[pos=0 lim=8 cap=8]
客户端:发送 PING 帧成功
客户端:收到帧,操作码: 10
客户端:收到 PONG 帧,负载: java.nio.HeapByteBufferR[pos=0 lim=8 cap=8]
客户端:发送 PING 帧成功
客户端:收到帧,操作码: 10
客户端:收到 PONG 帧,负载: java.nio.HeapByteBufferR[pos=0 lim=8 cap=8]

从上面可以得出结论,只要周期在30s以内发送ping报文,则不会出现超时的问题。

那么,ping报文是否必须发送呢,如果只发送msg呢,是否也能达到相同的效果?

测试3:发送msg报文

修改ClientSocket.java,代码如下:

        // 注释该行,不发送ping报文
//        scheduler.scheduleAtFixedRate(this::sendPing, 0, 29, TimeUnit.SECONDS);// 仅发送msg报文scheduler.scheduleAtFixedRate(this::sendMSG, 0, 32, TimeUnit.SECONDS);

设置发送周期为32s,输出结果如下: 

WebSocket 客户端已启动
客户端:已连接到服务端,URI: ws://10.10.10.10:8080/mq,1753430236546
请输入消息(输入 'ping' 发送 PING 帧,'exit' 退出):
客户端:消息发送成功: 1753430236548
客户端:发生错误: Connection Idle Timeout,1753430266587
org.eclipse.jetty.websocket.api.exceptions.WebSocketTimeoutException: Connection Idle Timeout...
Caused by: org.eclipse.jetty.websocket.core.exception.WebSocketTimeoutException: Connection Idle Timeout... 10 more
Caused by: java.util.concurrent.TimeoutException: Idle timeout expired: 30011/30000 msat org.eclipse.jetty.io.IdleTimeout.checkIdleTimeout(IdleTimeout.java:167)... 7 more
客户端:连接关闭,状态码: 1001, 原因: Connection Idle Timeout,30042
WebSocket 客户端已停止

问题同上,因为发送周期为32s,超过了30s,所以会报超时的错误。

接下来把发送周期改小为29s,看下是什么情况:

scheduler.scheduleAtFixedRate(this::sendMSG, 0, 29, TimeUnit.SECONDS);

输出日志:

WebSocket 客户端已启动
客户端:已连接到服务端,URI: ws://100.10.10.10:8080/mq,1753430446727
请输入消息(输入 'ping' 发送 PING 帧,'exit' 退出):
客户端:消息发送成功: 1753430446728
客户端:消息发送成功: 1753430475742
客户端:消息发送成功: 1753430504734
客户端:消息发送成功: 1753430533728
客户端:消息发送成功: 1753430562739
客户端:消息发送成功: 1753430591733
客户端:消息发送成功: 1753430620732
客户端:消息发送成功: 1753430649737
客户端:消息发送成功: 1753430678739

周期性地发送msg报文,连接也正常,没有出现超时的问题。

通过上面几个日志的对比,可以得出如下结论:

1、验证了默认30s超时的问题。

2、 只要在30s内周期性地发送报文,无论是ping还是msg,都可以避免超时的问题。

解决方案:

        经过以上的分析验证,现在已经明确了,问题就出在客户端的空闲超时上。解决方案有三种:

        1、设置客户端的空闲超时时间为一个很大的数;这个方法不现实,同时,因为angular上没相应的接口,所以也没法实现。

        2、客户端周期发送ping报文,间隔需要小于客户端的空闲超时时间;

        3、客户端周期发送msg报文,间隔需要小于客户端的空闲超时时间;实际上,msg报文是根据业务产生的,不具有周期性。java侧是将ping报文和msg报文分开的,但angular没有提供发送ping报文的单独接口,所以发送ping报文实际也是通过发送msg报文的接口发送出去的。

        4、服务端周期性的发送ping报文,间隔需要小于客户端的空闲超时时间;这个方法有个问题,服务端需要对每个新的请求都建一个定时的timer,并在每个请求断开时,取消对应的timer,这就增加了服务端管理session的复杂度。因此,我不建议采用这种方法。

        所以,比较好的解决办法是,angular需要周期性的发送ping报文,间隔时间需要小于空闲超时时间。

        但在文章开头,我们已经介绍了,前端实际上是有实现周期发送ping报文的,间隔周期设置的是30s。这个30s,就是问题的根源,因为是超时的临界值,稍不注意就超时了,可以用前面介绍的java客户端做测试,将周期改为30s,就会出现超时的情况。

        基于此,本文提出的问题也好解决,将超时时间改为30s以内即可,为了保险起见可以改为15s。       

        本以为找到问题的根本原因了,结果经测试,问题并没有解决,哈哈,😂。没办法了,打开前端的debug模式,看到控制台有很多异常打印:

ERROR SyntaxError: Unexpected token 'p', "ping" is not valid JSONat JSON.parse (<anonymous>)at t.onMessage (main-es2015.d1b55912bea89f3f09c9.js:1:1177790)at ws.onmessage [as __zone_symbol__ON_PROPERTYmessage] (main-es2015.d1b55912bea89f3f09c9.js:1:1177023)
ERROR SyntaxError: Unexpected token 'p', "pong" is not valid JSONat JSON.parse (<anonymous>)at t.onMessage (main-es2015.d1b55912…3f09c9.js:1:1177790)at ws.onmessage [as __zone_symbol__ON_PROPERTYmessage] (main-es2015.d1b55912…3f09c9.js:1:1177023)at WebSocket.S (vendor-es2015.5e60c9…21fe60.js:1:5147553)

 这打印的异常说明处理的数据不是json格式的,因为收到的是ping和pong消息,所以一开始觉得这个错误没啥影响,也就一直没放在心上。报错的源码如下:

  protected onMessage(evt) {const msg: Message = JSON.parse(evt.data);const notice = msg.data;const type = msg.type; ...}

按照前面的分析,前端每15s发送一次ping,理论上可以保持连接活跃了,但接近一分钟的时候还是断了。经过一番查询后,还是怀疑这个点,于是加上try/catch试试,不让其报错,修改的代码如下:

  protected onMessage(evt) {let msg: any;try {msg = JSON.parse(evt.data);} catch (e) {console.warn('Received non-JSON message from server:', evt.data);return;  // 跳过非 JSON 消息,比如ping/pong}...}

然后再测试,发现对了,好吧,问题总算是解决了。 前端我也不熟悉,所以就不总结了,就这样吧,完结,撒花。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习深度学习】模型私有化部署与微调训练:赋能特定问题处理能力

目录 前言 一、私有化部署的背景&#xff1a;通用能力 ≠ 企业实用 暴露问题 二、微调训练的核心目的 2.1 动作一&#xff1a;私有化部署&#xff08;Private Deployment&#xff09; 2.2 动作二&#xff1a;领域微调&#xff08;Domain Fine-Tuning&#xff09; 2.3 微…

Seq2Seq学习笔记

Seq2Seq模型概述Seq2Seq&#xff08;Sequence-to-Sequence&#xff09;是一种基于深度学习的序列生成模型&#xff0c;主要用于处理输入和输出均为序列的任务&#xff0c;如机器翻译、文本摘要、对话生成等。其核心思想是将可变长度的输入序列映射为另一个可变长度的输出序列。…

react useId

useId useId 是 React 18 引入的一个内置 Hook&#xff0c;用于生成唯一且稳定的 ID &#xff0c; 主要用于&#xff0c;解决在客户端和服务器端渲染&#xff08;SSR&#xff09;时&#xff0c;动态生成 ID 可能导致的冲突问题&#xff1b; 特别适合用于&#xff0c;需要关联 H…

排水管网实时监测筑牢城市安全防线

排水管网的实时监测工作&#xff0c;强调其对于保障城市安全的重要作用。“排水管网”明确了具体的关注对象&#xff0c;它是城市基础设施的重要组成部分&#xff0c;承担着雨水、污水排放等关键功能。“实时监测”突出了监测的及时性和持续性&#xff0c;意味着能够随时获取排…

SZU大学物理实验报告|电位差计

写在前面&#xff1a;博文里放图片&#xff0c;主要省去了对文档的排版时间&#xff0c;实验还是要自己做的&#xff0c;反正都要去实验室上课&#xff0c;顺带锻炼下动手能力。有些结果是实验手写的&#xff0c;所以看不到&#xff0c;有结果的可以对下结果差的不太多就行&…

RoPE简单解析

文章目录简介拆解一些tricks简介 因为RoPE的优异性能&#xff0c;其已成为各种大模型中位置编码的首选&#xff0c;包括多模态模型&#xff1b;在一些多模态模型或视频理解模型中&#xff0c;甚至会用到多维度RoPE。虽然RoPE已广泛应用&#xff0c;之前也看了不少针对其原理解…

windows 获取 APK 文件的包名和启动 Activity 名称

使用 aapt 命令确保环境变量配置正确&#xff1a;首先需要确保你的系统环境变量中包含了 Android SDK 的 build-tools 目录路径。这是因为 aapt 工具位于该目录下。运行命令&#xff1a; 打开命令提示符&#xff08;CMD&#xff09;&#xff0c;然后输入以下命令来查看 APK 的详…

【Mac版】Linux 入门命令行快捷键+联想记忆

Linux Mac 用户终端命令行快捷键 符号速查全解作为一个刚接触 Linux 和终端的 macOS 用户&#xff0c;常常被命令行的各种快捷键和符号弄得头晕脑胀&#xff0c;本文将带你系统地掌握命令行中最常用的快捷键和符号&#xff0c;并通过逻辑联想帮助你轻松记住每一个组合。一、基…

AUTOSAR Mcal Dio - 模块介绍 + EB配置工具介绍

文章目录1. 模块简介2. 主要功能3. 缩略语4. API接口5. 功能介绍5.1. ChannelGroup5.2. Dio_MaskedWritePort6. 序列图6.1.读GPIO电平6.2. 设置GPIO电平7. EB 工具配置7.1.General7.2.DioPort8. 参考资料1. 模块简介 Dio&#xff0c;全称“Digital Input Output”。Dio模块&am…

ICT模拟零件测试方法--晶体管测试

ICT模拟零件测试方法–晶体管测试 文章目录ICT模拟零件测试方法--晶体管测试晶体管测试晶体管测试配置晶体管测试配置晶体管测量选项晶体管测试 i3070 在线测试软件为每个晶体管提供两种测试&#xff1a; 使用二极管测试对晶体管的两个 PN 结进行测试。这是检查设备存在的快速…

AI算法实现解析-C++实例

基于C++实现的AI 以下是基于C++实现的AI/机器学习相关示例,涵盖基础算法、计算机视觉、自然语言处理等领域,适合不同阶段的学习者参考: 基础机器学习算法 线性回归 使用梯度下降法预测连续值,核心公式: 损失函数: 逻辑回归 二分类问题实现,Sigmoid函数: K-Means…

亚马逊云科技实战架构:构建可扩展、高效率、无服务器应用

对于今天的开发者、架构师和技术爱好者而言&#xff0c;云计算早已超越了简单的“虚拟机租赁”或“服务器托管”阶段。它已经演化为一套丰富、强大且精密的工具集&#xff0c;能够以前所未有的方式设计、部署和扩展应用程序。真正的云原生思维&#xff0c;是掌握并运用多种架构…

论文阅读:《无约束多目标优化的遗传算法,群体和进化计算》

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

嵌入式单片机中位带操作控制与实现

STM32 单片机的SRAM有两个区支持位带(bit-band)操作。 那么,什么是位带,位带操作的原理是怎样的呢? 今天来梳理一下这个知识点。 在介绍位带操作之前,先看一看 ARM Crotext-M3 的存储器映射。 CM3 的地址空间是 4GB, 程序可以在代码区,内部 SRAM 区以及外部 RAM 区中执…

考研初试专业分146!上岸新疆大学!信号与系统考研经验,通信考研小马哥。

信号与系统专业课分数146&#xff0c;希望以下的经验能够帮助到正在努力学习的学弟学妹们更好的学习专业课。本人是从四月份开始学习专业课&#xff0c;当时我觉得专业课应该要尽早开始越拖到后期学习压力越大&#xff0c;所以在周边同学还在只学习公共课的时候我就开始了专业课…

负载均衡算法中的加权随机算法

import org.apache.commons.lang3.tuple.Pair;import java.util.Arrays; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors;/*** 加权随机,nacos*/ public class RouterWeightRandom {/**** param list [{"a&q…

AI时代SEO关键词优化策略

内容概要 在人工智能&#xff08;AI&#xff09;技术深度融入数字营销的背景下&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;的关键词优化策略正经历一场智能变革&#xff0c;这不仅重塑了传统研究方式&#xff0c;还为企业带来了全新的竞争机遇。本文将从AI时代SEO的变…

复矩阵与共轭转置矩阵乘积及其平方根矩阵

设 是一个 的复数矩阵&#xff0c;其共轭转置矩阵&#xff08;Hermitian 共轭&#xff09;记为 &#xff08;即 &#xff09;&#xff0c;则矩阵 &#xff08; &#xff09;和 &#xff08; &#xff09;的性质如下文所述。1. Hermitian 性&#xff08;自共轭性&#x…

Vue 框架 学习笔记

作为初学者对于Vue框架的学习笔记 总结了Vue框架的核心知识点&#xff0c;包括&#xff1a;1. 基础概念&#xff1a;渐进式框架、两种使用方式、Vue实例创建流程、模板语法和响应式特性。2. 常用指令&#xff1a;详细介绍了v-html、v-show/v-if、v-for、v-on、v-bind、v-model等…

飞牛系统安装DataEase自定义Docker包

飞牛系统安装DataEase自定义Docker包背景构造DataEase Docker包1.在Linux 系统中&#xff08;比如我这里选麒麟V10&#xff09;安装Docker2.准备打包文件3.执行打包4.验证打好的包上传DataEase Docker包1.把本地docker 容器导出1.1查看镜像列表命令&#xff1a;docker images1.…