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

分布式应用开发的核心技术系列之——基于TCP/IP的原始消息设计

本文由葡萄城技术团队原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

前言

本文的内容主要围绕以下几个部分:

  1. TCP/IP的简单介绍。
  2. 消息的介绍。
  3. 基于消息分类的传输格式(流类型和XML类型)。
  4. 消息体系的组成。

TCP/IP的简单介绍

TCP/IP (传输控制协议/网际协议) 是互联网中的基本通信语言或协议。它其实是一个两层的程序,分为高层与低层。高层为传输控制协议,负责聚集信息或把文件拆分成更小的包。这些包通过网络传送到接收端的 TCP层,接收端的 TCP 层把包还原为原始文件。低层是网际协议,它处理每个包的地址部分,使这些包正确地到达目的地。网络上的网关计算机根据信息的地址来进行路由选择。即使来自同一文件的分包路由也有可能不同,但最后会在目的地汇合。TCP/IP 使用客户端/服务器模式进行通信。

在架构上,TCP/IP 并不完全符合 0SI 的 7 层参考模型。传统的开放式系统互连参考模型是一种通信协议的 7 层抽象的参考模型,其中每一层执行某一特定任务。该模型的目的是使各种硬件在相同的层次上相互通信。这 7 层是: 物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而 TCP/IP 通信协议采用了 4 层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。这 4 层分别为:

  • 应用层:应用程序间沟通的层,如简单邮件传输协议 (SMTP)、文件传输协议 (FTP)、远程网络访问协议 (Telnet) 等。
  • 传输层:在此层中,它提供结点间的数据传送和应用程序之间的通信服务,主要功能是数据格式化、数据确认和丢失重传等。如传输控制协议 (TCP)、用户数据报协议 (UDP) 等,TCP 和 UDP 给数据包加入传输数据并把它传送到下一层中,这一层负责传送数据,并且确定数据已被送达并接收。
  • 互连网络层:负责提供基本的数据封包传送功能,让每一个数据包都能够到达目的主机 (但不检查是否被正确接收),如网际协议 (IP)。
  • 网络接口层 (主机-网络层): 接收 IP 数据报并进行传输,从网络上接收物理帧,抽取 IP 数据报转交给下一层,管理实际的网络媒体,定义如何使用实际网络 (如 Ethernet、Serial Line 等) 来传送数据。

Tcp/IP中常用的函数

1.Socket函数

int socket(int domain,int type,int protocol),

domain 指明所使用的协议族,通常为 PF INET,表示互联网协议族(TCP/IP 协议族); type 参数指定 socket 的类型;用于 TCP 的SOCK STREAM 或用于 UDP 的 SOCK DGRAM; protocol 通常赋值[0]。socket函数调用返回一个整型 socket 描述符,可以在后面调用它。

2.bind函数:

bind 函数将 socket 与本机上的一个端口相关联,随后就可以在该端口监听服务请求。bind 函数原型为:

int bind(int sockfd,struct sockaddr *my addr, int addrlen);

sockfd 是调用 socket 函数返回的 socket 描述符;my addr 是一个指向包含有本机 IP 地址及端口号等信息的 sockaddr 类型的指针:addrlen 常被设置为 sizeof (struct sockaddr)。

3.connect连接函数:

面向连接的客户程序使用连接 (connect) 函数来配置 socket 并与远端服务器建立一个 TCP 连接,其函数原型为:

int connect(int sockfd, struct sockaddr *serv addr,int addrlen);

sockfd 是 socket 函数返回的 socket 描述符; serv addr 是包含远端主机 IP 地址和端口号的指针; addrlen 是远端地址结构的长度。connect 函数在出现错误时返回-1,并且设置 errno 为相应的错误码。进行客户端程序设计无须调用 bind 0,因为这种情况下只需要知道目的机器的 IP 地址即可,而客户通过哪个端口与服务器建立连接并不需要关心socket 执行体程序自动选择一个未被占用的端口,并通知程序数据什么时候到达端口。

4.listen监听函数:

网络监听 (listen) 函数使 socket 处于被动的监听模式,并为该socket 建立一个输入数据队列,将到达的服务请求保存在此队列中,直到程序处理它们。

int listen(int sockfd, int backlog);

sockfd 是 Socket 系统调用返回的 socket 描述符;backlog 指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待接收函数accept 0)(参考下文)。backlog 对队列中等待服务的请求的数目进行了限制,通常系统默认值为 20。如果一个服务请求到来时,输入队列已满该 socket 将拒绝连接请求,客户将收到一个出错信息。

5.accept接收函数:

accept0函数让服务器接收客户的连接请求。在建立好输入队列后,服务器就调用 accept 函数,然后睡眠并等待客户的连接请求。

int accept(int sockfd, void *addr, int *addrlen);

sockfd 是被监听的 socket 描述符,addr 通常是一个指向sockaddr_in 变量的指针,该变量用来存放提出连接请求服务的主机的信息(某台主机从某个端口发出该请求); addrlen 通常为一个指向值为sizeof (struct sockaddr in) 的整型指针变量。出现错误时 accept 函数返回-1 并设置相应的 errno 错误码。

6.sendto函数和recvfrom函数:

int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen):

to 表示目的机的IP 地址和端号信息,而 tolen 常常被赋值为 sizeof (struct sockaddr)。sendto 函数返回实际发送的数据字节长度或在出现发送错误时返回-1。

int recyfrom(int sockfd,void *buf,int len,unsigned int flags,structsockaddr *from,int *fromlen);

from 是一个 struct sockaddr 类型的变量,该变量保存源主机的 IP 地址及端口号。fromlen 常置为 sizeof (struct sockaddr),当 recvfrom()返回时,fromlen 包含实际存入 from 中的数据字节数。recvfrom() 函数返回接收到的字节数或当出现错误时返回-1,并设置相应的 errno 错误码。

7.shutdown函数

shutdown函数来关闭该 socket。该函数允许你只停止某个方向上的数据传输,而另一个方向上的数据传输继续进行。

int shutdown(int sockfd,int how);

sockfd 是需要关闭的 socket 的描述符。参数 how 允许为 shutdown操作选择以下几种方式:

  • 0一一不允许继续接收数据
  • 1–不允许继续发送数据
  • 2一一不允许继续发送和接收数据

shutdown 在操作成功时返回 0,在出现错误时返回-1 并设置相应errno 错误码。

8.fcntl函数

fcntl函数可以改变已打开的文件的性质。

int fcntl (int fields, int cmd, .../* int arg */) ;

9.getsockopt 与 setsockopt 函数

这两个函数可以获取或者设置与某个套接字关联的选项。为了操作套接字层的选项,应该将层的值指定为 SOL SOCKET。为了操作其他层的选项控制选项的合适协议号必须给出。例如,为了表示一个选项是由 TCP 解析,层应该设定为协议号 TCP。

int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);

10.select函数

select 函数是一种用于多路复用(Multiplexing)的系统调用或函数。它通常用于处理多个输入和输出流,以实现异步的 I/O 操作。

int select(int n, fd set * readfds, fd set * writefds, fd set * exceptfds,struct timeval * timeout);

参数 n 代表最大的文件描述词加 1,参数 readfds、writefds 和exceptfds 称为描述词组,是用来回传该描述词的读、写或例外的状况。

11.poll函数

int poll(struct pollfd fds[], nfds t nfds, int timeout);

其中 fds 是一个 struct pollfd 结构类型的数组,用于存放需要检测其状态的 socket 描述字。struct pollfd 的定义如下:

struct pollfd {//descriptor to checkint fd;//events of interest on fdshort events;//events that occurred on fdshort revents;
}

什么是消息

消息是分布式应用开发中,网络上两个逻辑实体之间进行通信时,在编程层面的最小单元。

对以上定义,有以下几点说明:

(1) 消息的概念存在于开发工作中,位于编程层面。在系统运行时,对应用用户是透明的。

(2) 网络上的两个逻辑实体,是指两个可独立运行的程序,它们可以部署于网络中两个不同的物理设备上,也可以部署于同一个物理设备上,但一般是两个没有父子关系的独立进程 (这一点与 IPC 编程中最基本的消息概念不同)。

(3) 消息是分布式通信时编程层面的最小单元,即无论参与通信的数据量是多还是少,程序代码中都通过发送与接收一个或多个消息来实现。

(4) 网络上两个应用之间的通信,包括数据流传输与远程过程(函数)调用两种类型。

(5) 利用消息可以实现分布式应用之间的结构化数据通信。也就是说编程人员在通信层面面对的不再是实际字节流,而是可以由多种数据类型组合而成的结构化数据单元。

其实,这种结构化数据单元本身就是“消息”,它对外可以表现为结构或者类。因此,当基于以上定义的消息机制建立起来以后,程序员在编码过程中,当需要进行分布式通信时,只需要生成相应的消息,然后调用相应的发送与接收接口方便地实现即可,而不需要了解 TCP/IP 知识,不需要掌握socket 编程的基本技能,也不需要考虑串行消息过多、并发消息过多、网络流量控制等其他多方面的问题,从而才能真正地将分布式应用开发的精力集中到业务实现上来,极大地提高了分布式系统的开发效率与质量,特别是大型分布式系统。

关于消息的存在形式,在传统 C 语言中,可以是一个结构 struct;在面向对象语言中 (C++ 或 Java),则可以是一个类 class。

基于消息分类的传输格式

基于消息传输的格式不同,可以将消息分为流消息和XML消息,流消息基于二进制字节流式格式传输,XML消息基于XML格式的字符串传输。

流消息

流消息是指在计算机系统中,以流(stream)的方式传递和处理的消息。流消息由一系列连续的数据组成,在发送端按照一定的顺序生成,并以流的形式传输到接收端。传输过程中,接收端可以逐个读取流中的数据。,对于流消息来说,无论程序员如何表示消息,消息在真正发送之前,都需要先转换为二进制流格式,这个转换过程称为流化 (Streamlization),也可称序列化 (Serilization),

XML消息

XML消息是指使用可扩展标记语言(XML)作为消息格式的数据传输方式。XML是一种用于描述和存储数据的文本标记语言,它使用标签来定义数据的结构和属性。在 XML 消息机制中,程序员用 XML 格式表示消息内容之后,不需要再为发送传输做任何格式转换工作(不包括为安全传输所做的加密工作),直接就可以以 XML 字符串格式发送出去。XML 消息应用也比较广泛,如 Web Service 中的 SOAP 协议,就是基于 XML 消息设计实现的。

举个例子:基于流消息的设计与实现方法

下面小编为大家简单地介绍一下如何在两个应用程序上发送和接受一个人的信息(包括身高、姓名和年龄)

(1)定义一个类存放人的信息:

struct Person {char name[20] ;float height;int age;
}
struct Person p;
strcpy(p.name ,"Michael Zhang");
height = 170.00;
age = 30;

(2)将信息序列结构化

char sendStream[1024] = {0};
sprintf(sendStream,"|%s|%f"%d",p.name, p.height, p.age);

(3)发送方发送字节流:

/*注: 这里省略建立/管理/关闭 TCP 连接的代码*/
char datalen[4+1] = (0);
sprintf(datalen,"04d" , strlen (sendStream) );
if(SendBytes ( socket, datalen, 4) == -1) {return -l;
}
if(SendBytes(socket, sendStream, strlen(sendStream)) == -1) {return -1
}

注意,以上代码中的函数 SendBytes 实际上是保证一定长度的字节流全部成功发送完毕后才返回,主要是由于在 socket 上调用 send 或 write函数不能保证一次能将一定长度的字节流发送完。SendBytes 的基本思想是循环发送,直至成功发完所有字节,其实现代码如下所示:

int SendBytes (int sd, const void *buffer, unsigned len) {int rez = 0;int leftlen = len;int readlen = 0:
}
while(true) {rez = write (socket, (char *)buffer+readlen, len-readlen);if(rez < 0) {if (errno != EWOULDBLOCK && errno != EINTR) {ErrorMsg("Error is serious );DisConnect(socket);}return -l:}readlen += rez;leftlen -= rez;if(leftlen <= 0){break;}}
return len:
}

(4)接收方接收字节流:

char datalen[4+1] = {0};
char receiveStream[1024] = {0};
sprintf(datalen,"%04d", strlen(sendStream)) ;
if(ReceiveBytes(socket, datalen, 4) == -1 {return -l;
}
int packet len = atoi(datalen) :
if(ReceiveBytes (socket, receiveStream, packet len) == -1) {return -l;
}

ReceiveBytes函数可以参考第三步发送方发送该字节流。

(5)字节流反序列化得到结构:

struct Person p;
sscanf(receiveStream,"%[`|]|%f|%d", p.name, &p.height, &p.age) ;

总结

本文简单的介绍了TCP/IP协议及其常用的接口函数,然后介绍了TCP/IP协议中消息的分类以及传输格式,最终以一个简单的消息发送小例子作为收尾。如对内容有何意见建议,欢迎大家在评论区中留言和讨论。

参考书籍:《消息设计与开发——分布式应用开发的核心技术》 何小朝

扩展链接:

从表单驱动到模型驱动,解读低代码开发平台的发展趋势

低代码开发平台是什么?

基于分支的版本管理,帮助低代码从项目交付走向定制化产品开发


欢迎了解葡萄城优秀产品:

SpreadJS 纯前端表格控件

活字格 企业级低代码开发平台

Wyn 嵌入式商业智能和报表软件

ActiveReportsJS 纯前端报表控件

相关文章:

分布式应用开发的核心技术系列之——基于TCP/IP的原始消息设计

本文由葡萄城技术团队原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 本文的内容主要围绕以下几个部分&#xff1a; TCP/IP的简单介绍。消息的介绍。基于消息分类的传输格式&…...

医疗领域的数字化浪潮:互联网医院平台的关键作用

数字化浪潮正在迅速改变医疗领域的方式和效率。互联网医院平台作为数字化医疗的关键元素&#xff0c;正在为医疗行业带来巨大的变革。本文将探讨互联网医院平台的关键作用&#xff0c;并提供一个示例&#xff0c;使用Python编写一个简单的医疗预约系统。 互联网医院平台的关键…...

将本地的项目上传到Gitee

目录 1.先在Gitee新建一个仓库,提交即可 2.进入到要上传的项目里面&#xff0c;右键选择 Git Bash Here 3.右键后就打开了Git命令窗口 4.配置你的用户名和邮箱(已经配置过则可跳过) 5.查看你的用户名和邮箱配置&#xff08;可不查看&#xff09; 6.输入git init指令&#…...

概率论_概率公式中的分号(;)、逗号(,)、竖线(|)

1. 概率公式中的分号(;)、逗号(,)、竖线(|) ; 分号代表前后是两类东西&#xff0c;以概率P(x;θ)为例&#xff0c;分号前面是x样本&#xff0c;分号后边是模型参数。 , 逗号代表两者地位平等&#xff0c;代表与的关系 | 竖线代表 if&#xff0c;一上面为例&#xff0c;就是如果…...

Spark Streaming 整合 Kafka

本文代码链接:https://download.csdn.net/download/shangjg03/88442308 1.版本说明 Spark 针对 Kafka 的不同版本,提供了两套整合方案:`spark-streaming-kafka-0-8` 和 `spark-streaming-kafka-0-10`,其主要区别如下: 本文使用的 Kafka 版本为 `kafka_2.12-2.2.0`,故采用…...

【API篇】五、Flink分流合流API

文章目录 1、filter算子实现分流2、分流&#xff1a;使用侧输出流3、合流&#xff1a;union4、合流&#xff1a;connect5、connect案例 分流&#xff0c;很形象的一个词&#xff0c;就像一条大河&#xff0c;遇到岸边有分叉的&#xff0c;而形成了主流和测流。对于数据流也一样…...

flutter开发的一个小小小问题,内网依赖下不来

问题 由于众所周知的原因&#xff0c;flutter编译时&#xff0c;经常出现Could not get resource https://storage.googleapis.com/download.flutter.io…的问题&#xff0c;如下&#xff1a; * What went wrong: Could not determine the dependencies of task :app:lintVit…...

RabbitMQ队列及交换机的使用

目录 一、简单模型 1、首先控制台创建一个队列 2、父工程导入依赖 3、生产者配置文件 4、写测试类 5、消费者配置文件 6、消费者接收消息 二、WorkQueues模型 1、在控制台创建一个新的队列 2、生产者生产消息 3、创建两个消费者接收消息 4、能者多劳充分利用每一个消…...

分布式唯一Id,它比GUID好

分布式唯一Id&#xff0c;它比GUID好 一、前言 分布式唯一Id&#xff0c;顾名思义&#xff0c;是指在全世界任何一台计算机上都不会重复的唯一Id。 在单机/单服务器/单数据库的小型应用中&#xff0c;不需要用到这类东西。但在高并发、海量数据、大型分布式应用中&#xff0c…...

计算机服务器中了勒索病毒怎么解决,勒索病毒解密流程,数据恢复

计算机服务器中了勒索病毒是一件非常令人头疼的事情&#xff0c;勒索病毒不仅会加密企业服务器中的数据&#xff0c;还会对企业计算机系统带来损害&#xff0c;严重地影响了企业的正常运转。最近&#xff0c;云天数据恢复中心工程师总结了&#xff0c;今年以来网络上流行的勒索…...

【NPM】vuex 数据持久化库 vuex-persistedstate

在 GitHub 上找到&#xff1a;vuex-persistedstate。 安装 npm install --save vuex-persistedstate使用 import { createStore } from "vuex"; import createPersistedState from "vuex-persistedstate";const store createStore({// ...plugins: [cr…...

英语——分享篇——每日200词——2601-2800

2601——resistant——[rɪzɪstənt]——adj.抵抗的——resistant——resi热死(拼音)st石头(拼音)ant蚂蚁(熟词)——热死了石头上的蚂蚁还在抵抗——The body may be less resistant if it is cold. ——天冷时&#xff0c;身体的抵抗力会下降。 2602——prospect——[prɒspe…...

SpringCloud-Sentinel

一、介绍 &#xff08;1&#xff09;提供界面配置配置服务限流、服务降级、服务熔断 &#xff08;2&#xff09;SentinelResource的blockHandler只处理后台配置的异常&#xff0c;运行时异常fallBack处理&#xff0c;且资源名为value时才生效&#xff0c;走兜底方法 二、安装…...

为什么索引要用B+树来实现呢,而不是B树

首先&#xff0c;常规的数据库存储引擎&#xff0c;一般都是采用 B 树或者 B树来实现索引的存储。 B树 因为 B 树是一种多路平衡树&#xff0c;用这种存储结构来存储大量数据&#xff0c;它的整个高度会相比二叉树来说&#xff0c;会矮很多。 而对于数据库来说&#xff0c;所有…...

使用vue3前端开发的一些知识点

Vue 3 是一种流行的 JavaScript 框架&#xff0c;用于构建用户界面。它是 Vue.js 框架的第三个主要版本&#xff0c;具有许多新特性和性能改进。下面是 Vue 3 的一些常用语法和概念的详细介绍&#xff1a; 创建 Vue 实例&#xff1a; 在 Vue 3 中&#xff0c;你可以通过创建一个…...

零基础Linux_20(进程信号)内核态和用户态+处理信号+不可重入函数+volatile

目录 1. 内核态和用户态 1.1 内核态和用户态概念 1.2 内核态和用户态转化 2. 处理信号 2.2 捕捉信号 2.2 系统调用sigaction 3. 不可重入函数 4. volatile关键字 5. SIGCHLD信号&#xff08;了解&#xff09; 6. 笔试选择题 答案及解析 本篇完。 1. 内核态和用户态…...

vite+vue3+elementPlus+less+router+pinia+axios

1.创建项目2.按需引入elementplus3.引入less安装vue-router安装 axios安装 piniapinia的持久化配置(用于把数据放在localStorage中)---另外增加的配置 1.创建项目 npm init vitelatest2.按需引入elementplus npm install element-plus --save//按需引入 npm install -D unpl…...

VMwarePlayer安装Ubuntu,切换中文并安装中文输入法

1.下载和安装 虚拟机使用的免费版官网链接&#xff1a;VMwarePlayer Ubuntu镜像下载官网链接&#xff1a;Ubuntu桌面版 自己学习使用&#xff0c;不需要考虑迁移之类的。选择单个磁盘IO性能会更高 安装过程中如果出现如下报错&#xff0c;则用系统管理员身份运行 右击VMwa…...

C# JSON转为实体类和List,以及结合使用

引用 using Newtonsoft.Json;using Newtonsoft.Json.Linq;JSON转实体类 public class Person {public string Name { get; set; }public int Age { get; set; }public string Gender { get; set; } }string jsonStr "{\"name\": \"Tom\", \"a…...

使用TensorRT-LLM进行高性能推理

LLM的火爆之后&#xff0c;英伟达(NVIDIA)也发布了其相关的推理加速引擎TensorRT-LLM。TensorRT是nvidia家的一款高性能深度学习推理SDK。此SDK包含深度学习推理优化器和运行环境,可为深度学习推理应用提供低延迟和高吞吐量。而TensorRT-LLM是在TensorRT基础上针对大模型进一步…...

Redis上篇--知识点总结

Redis上篇–解析 本文大部分知识整理自网上&#xff0c;在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库&#xff0c;Redis 的键值对中的 key 就是字符串对象&#xff0c;而 val…...

spring boot使用HttpServletResponse实现sse后端流式输出消息

1.以前只是看过SSE的相关文章&#xff0c;没有具体实践&#xff0c;这次接入AI大模型使用到了流式输出&#xff0c;涉及到给前端流式返回&#xff0c;所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…...

深入理解 C++ 左值右值、std::move 与函数重载中的参数传递

在 C 编程中&#xff0c;左值和右值的概念以及std::move的使用&#xff0c;常常让开发者感到困惑。特别是在函数重载场景下&#xff0c;如何合理利用这些特性来优化代码性能、确保语义正确&#xff0c;更是一个值得深入探讨的话题。 在开始之前&#xff0c;先提出几个问题&…...

day51 python CBAM注意力

目录 一、CBAM 模块简介 二、CBAM 模块的实现 &#xff08;一&#xff09;通道注意力模块 &#xff08;二&#xff09;空间注意力模块 &#xff08;三&#xff09;CBAM 模块的组合 三、CBAM 模块的特性 四、CBAM 模块在 CNN 中的应用 一、CBAM 模块简介 在之前的探索中…...

开源 vGPU 方案:HAMi,实现细粒度 GPU 切分

本文主要分享一个开源的 GPU 虚拟化方案&#xff1a;HAMi&#xff0c;包括如何安装、配置以及使用。 相比于上一篇分享的 TimeSlicing 方案&#xff0c;HAMi 除了 GPU 共享之外还可以实现 GPU core、memory 得限制&#xff0c;保证共享同一 GPU 的各个 Pod 都能拿到足够的资源。…...

C++ 使用 ffmpeg 解码 rtsp 流并获取每帧的YUV数据

一、简介 FFmpeg 是一个‌开源的多媒体处理框架‌&#xff0c;非常适用于处理音视频的录制、转换、流化和播放。 二、代码 示例代码使用工作线程读取rtsp视频流&#xff0c;自动重连&#xff0c;支持手动退出&#xff0c;解码并将二进制文件保存下来。 注意&#xff1a; 代…...

【RabbitMQ】- Channel和Delivery Tag机制

在 RabbitMQ 的消费者代码中&#xff0c;Channel 和 tag 参数的存在是为了实现消息确认机制&#xff08;Acknowledgment&#xff09;和精细化的消息控制。 Channel 参数 作用 Channel 是 AMQP 协议的核心操作接口&#xff0c;通过它可以直接与 RabbitMQ 交互&#xff1a; 手…...

基于 Transformer robert的情感分类任务实践总结之二——R-Drop

基于 Transformer robert的情感分类任务实践总结之一 核心改进点 1. R-Drop正则化 原理&#xff1a;通过在同一个输入上两次前向传播&#xff08;利用Dropout的随机性&#xff09;&#xff0c;强制模型对相同输入生成相似的输出分布&#xff0c;避免过拟合。实现&#xff1a…...

Redis——主从哨兵配置

目录 基础概念 ‌一、核心原理‌ ‌二、核心特性‌ ‌三、技术意义与应用价值‌ ‌四、典型应用场景‌ 案例部署 ‌一、主从复制配置命令‌ ‌二、哨兵模式部署命令‌ ‌关键注意事项‌ 基础概念 ‌一、核心原理‌ ‌内存存储与高性能‌ Redis 所有数据存储于内存中&…...

前端验证下跨域问题(npm验证)

文章目录 一、背景二、效果展示三、代码展示3.1&#xff09;index.html3.2&#xff09;package.json3.3&#xff09; service.js3.4&#xff09;service2.js 四、使用说明4.1&#xff09;安装依赖4.2&#xff09;启动服务器4.3&#xff09;访问前端页面 五、跨域解决方案说明六…...