从服务器接收到请求到对应后台接收到请求

本文详细介绍了负载均衡的实现方式及调度算法,并对比了HTTP1.0、HTTP1.1、HTTP2.0和HTTPS的不同之处。同时,还探讨了GET与POST的区别、GZIP压缩的作用、长连接与短连接的特点以及浏览器的本地存储方案。

负载均衡
对于大型的项目,由于并发访问量非常大,所以往往一台服务器是吃不消的,一般会有若干台服务器组成一个集群,然后通过配合反向代理实现负载均衡

这里实现负载均衡的方式有很多种,我们以比较熟悉的反向代理负载均衡为例,先来看看它的调度算法:
1.weight(轮询)
​ 接收到的请求按照顺序逐一分配到不同的后端服务器,即使在使用过程中,某一台服务器宕机,nginx会自动将这台服务器剔除队列,请求受理的情况不会受到任何影响。在这种方式下,可以给不同的后端服务器设置一个权重值,用于调整不同的服务器上请求的分配率,权重数据越大,被分配到的几率越大,该权重值主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的。
2.ip_hash
每个请求按照发起客户端的ip的hash结果进行匹配,这样的算法保证了下一个固定ip地址的客户端总是会访问到上一次访问的服务器,这也在一定程度上解决了集群服务器环境下session共享问题。
3.fair
动态的根据后端服务器的请求处理到响应的时间进行均衡分配,响应时间短处理效率高的服务器分配到请求的概率高,响应时间长处理效率低的服务器分配到的请求少。默认nginx不支持此算法,需要安装upstream_fair模块。
4.url_hash
​ 按照访问的url的hash结果分配请求,每个请求的url会指向后端的固定服务器,可以在nginx作为静态服务器的情况下提高缓存效率,同样nginx也不支持此算法,需要安装hash包。
**HTTP1.0、HTTP1.1、HTTP2.0和HTTPS

HTTP1.0**
http/1.0最大的问题是连接无法复用,比如浏览器页面中包含很多同一服务器下的图片,那么使用http/1.0协议的话会导致连接无法复用,每次连接都会造成资源的浪费。尤其在高延迟的3次握手阶段以及大文件的慢启动阶段导致用户的体验遭到影响。
HTTP1.1

​ 为了客户http/1.0的缺陷,http/1.1使用长连接的访问机制,即在在过期时间内一个TCP连接中可以传送多个http请求,以此来减少建立和关闭连接的消耗和延迟。
HTTP2.0
​ 相对于http/1.1来说浏览器再同一时间对同一域名的请求是有最大限制的。http/2.0通过多路复用技术,同一个tcp请求可以请求多个资源

以下是http/2.0的新特性:

​ 1.多路复用

​ 2.首部压缩

​ 3.二进制分帧

​ 4.服务器端推送

​ 5.请求优先级设置

HTTPS

​ https就是安全版本的http,譬如一些支付操作就需要用到https协议

下面简述SSL/TLS协议的握手流程

​ 1.浏览器请求建立SSL连接,并向服务端发送一个随机数(Client-Random)和客户端所支持的算法。

​ 2.服务端选出一组算法,并回复一个随机数(Server-Random),并将安全证书(公钥包含其中)发送给浏览器。

​ 3.浏览器收到服务器的证书后,首先会生成第三个随机数(Premaster-secret),并且会验证证书是否合法有效。并通过约定好算法与服务器发送的公钥进行加密这个随机数。

​ 4.服务器使用自己的私钥获取这个随机数的“真面目”。

​ 5.服务器使用约定的算法,以及之前的三个随机数,生成对话密钥(session key),用来加密之后的过程。
GET和POST区别
​ 上文中,我们提到应用层HTTP协议规定的数据的规范**,实际用于传输的协议是TCP/IP协议**。并且针对不同浏览器上GET和POST的实践也有些不同,所以这里我们不讨论传输层或不同浏览器中GET和POST的区别,我们只讨论在语义上两者所带来的区别。

​ GET表达的是一种幂等的,只读的操作。讲通俗一些,就是他只查数据,而不会对数据做任何操作,因此对于大部分GET请求都可以被缓存下来,这能大大减少服务器的压力。

​ POST相对于GET表达的是非幂等的,并且对数据有影响的操作,这些必须通过服务器进行处理

​ 若把GET请求全被换成POST请求,首先所有的CDN全部废掉了,服务器的压力将变得巨大。

GZIP压缩
开启GZIP压缩的好处显而易见,一般文本可以将其压缩至原大小的60%,从而提升请求的效率。如果想要开启GZIP传输的话,需要后端容器进行配置,开启压缩功能。

​ 浏览器发送请求给Web服务器,request中有Accept-Encoding:gzip,deflate。这里表示浏览器支持GZIP压缩,请服务器帮忙压缩后再进行相应

​ 服务器通过LZ77算法和哈夫曼编码对其response进行压缩后发送给浏览器。浏览器再对其进行解码,再将其展示在页面上。

​ 需要注意的是,GZIP对于压缩图片这部分会大大增加服务器的CPU压力,并且压缩效果也不好,所以不太推荐针对图片进行压缩
长连接与短连接
在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就会建立一次连接,任务结束就中断连接。

​ 而从HTTP/1.1开始,默认使用长连接,用以保持连接活性。使用长连接,会在响应头加入这行代码。

Connection: keep-alive

在使用长连接的的情况下,当一个网页打开完成后,客户端与服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个过期时间,可以在不同的服务器软件中设定这个时间。

​ 实现长连接需要客户端和服务端都支持长连接,HTTP长连接和短连接实际上是TCP协议的长连接和短连接。
浏览器本地存储方案
Cookie

​ 1.大小受限制,cookie大小被限制在4KB

​ 2.cookie的实现是通过扩展HTTP协议实现,cookie存储的内容将保留在请求头中。并且对于同源的请求中,每次cookie都在浏览器和服务器中传输,这样会造成不必要的资源浪费。一般优化的方案是通过拆分服务器域名,将静态资源,请求多的服务器和使用cookie的服务器进行分离.

​ 3.对于服务器来说处理cookie非常方便,但是通过js处理cookie虽然有很多很棒的库帮忙,但是本质上还是通过正则表达式来进行分割处理。

SessionStorage

​ 1.大小为5M,可以存储较多的数据。

​ 2.sessionStorage与服务器的session类似,它是会话级别的缓存,关闭浏览器后将被清除。

​ 3.不同窗口不可以共享sessionStorage。

​ 4.他非常方便的API。

LocalStorage

​ 1.大小为5M,同sessionStorage。

​ 2.他是一种持久化方案,如果说不手动清除得话,数据是不会过期的。

​ 3.不同窗口,非跨域情况可以共享。

总结
上文说到,服务器已经接受到了通过tcp/ip协议发送过来的数据了,此时这台服务器如果是反向代理服务器的话,还会根据负载均衡将请求派发到具体的容器中。对应容器又会将请求转交到后台接口中,此时如果涉及到权限验证,跨域验证等没有通过的话,将直接根据对应的http协议返回响应结果,拒绝请求。只有通过了验证才能进行访问数据库等操作,等程序执行完毕后,将返回一个http响应包,重复上文的过程,完成交互。

<think> 我们正在处理一个关于在UE5中使用C++接收后台发送的数据请求的问题。根据用户的需求,我们需要参考站内引用,特别是引用[2]中提到了远程过程调用(RPC)的概念,引用[5]中提到了回调函数的使用。 用户的问题:在UE5中使用C++接收后台发送的数据请求的方法。 分析: 1. 在UE5中,网络通信通常涉及到客户端和服务器之间的交互。后台发送的数据请求可以理解为从服务器(或另一个客户端)发送到当前客户端的数据。 2. 引用[2]中提到了远程过程调用(RPC)的概念。RPC允许客户端或服务器调用对方的一个函数。因此,我们可以使用RPC来接收后台发送的数据请求。 3. 引用[5]展示了一个回调函数的例子,它可以在异步操作完成时设置结果。在UE5中,我们也可以使用回调或事件委托来处理接收到的数据。 解决方案: 在UE5中,接收后台发送的数据请求,通常有以下几种方法: 方法一:使用RPC(远程过程调用) - 如果后台指的是服务器,那么服务器可以通过RPC将数据发送到客户端。 - 在UE5中,RPC分为三种: 1. 服务器RPC(Server RPC):客户端调用,在服务器上执行。 2. 客户端RPC(Client RPC):服务器调用,在客户端上执行。 3. 多播RPC(Multicast RPC):服务器调用,在服务器和所有客户端上执行。 - 要接收服务器发送的数据,我们可以在客户端上定义一个客户端RPC函数,然后由服务器调用这个RPC函数,将数据作为参数传递。 方法二:使用变量复制(Replication) - 如果数据是以属性的形式存在,并且设置了复制,那么当服务器更新该属性时,它会自动复制到客户端。客户端可以通过属性变化回调(如RepNotify)来响应数据更新。 方法三:使用事件委托(Delegates)和回调(Callbacks) - 引用[1]中详细解释了委托(邮递员)的机制。我们可以使用委托来解耦数据接收和处理的逻辑。 - 当收到数据时,我们可以触发一个事件,然后由事先注册的回调函数来处理数据。 - 引用[5]中展示了一个回调函数的实现,它使用了`std::future`和`std::promise`,但在UE5中,我们通常会使用UE自己的委托系统。 结合用户的问题,我们主要讨论如何使用RPC和委托来接收数据。 详细步骤(以RPC为例): 1. 在客户端角色类(例如`AMyCharacter`)中声明一个客户端RPC函数,用于接收数据。 ```cpp UFUNCTION(Client, Reliable) void ClientReceiveData(const FMyDataStruct& Data); ``` - `Client`表示这是一个在客户端执行的RPC。 - `Reliable`表示可靠的传输,确保数据到达。 2. 在服务器端,当需要发送数据给某个客户端时,获取该客户端对应的角色对象,并调用它的`ClientReceiveData`函数。 ```cpp if (AMyCharacter* ClientCharacter = Cast<AMyCharacter>(ClientPlayerController->GetPawn())) { ClientCharacter->ClientReceiveData(MyData); } ``` 3. 在客户端RPC函数中,处理接收到的数据。 ```cpp void AMyCharacter::ClientReceiveData_Implementation(const FMyDataStruct& Data) { // 在这里处理接收到的数据,比如更新UI、触发事件等 // 可以使用委托将数据传递给其他系统 OnDataReceived.Broadcast(Data); } ``` 4. 在其他需要处理该数据的类中,可以订阅这个委托(例如在UI类中): ```cpp // 假设在UI类的初始化中 MyCharacter->OnDataReceived.AddDynamic(this, &UMyUI::HandleDataReceived); ``` 5. 在UI类中定义处理函数: ```cpp void UMyUI::HandleDataReceived(const FMyDataStruct& Data) { // 更新UI显示等 } ``` 注意事项: - RPC函数需要在网络环境中使用,确保在客户端和服务器之间建立连接。 - 使用委托时要注意生命周期问题,避免在对象销毁后仍调用委托(可以使用弱引用或及时取消绑定)。 另外,如果后台发送的数据请求是通过HTTP等非游戏网络协议发送的,那么我们需要使用UE5提供的HTTP模块(如`FHttpModule`)来发送HTTP请求并处理响应。但根据用户的问题和引用,似乎更关注游戏内的网络通信(RPC)。 总结: 在UE5中,接收后台服务器)发送的数据请求,推荐使用客户端RPC函数,并结合委托机制将数据传递给其他系统进行处理。这样可以实现解耦和灵活的扩展。 根据要求,生成相关问题: </think> ### UE5 C++ 接收后台发送的数据请求的方法 在 UE5 中,使用 C++ 接收后台发送的数据请求主要有以下三种方法: #### 1. **远程过程调用 (RPC)** 当后台服务器)需要主动向客户端发送数据时: ```cpp // 声明客户端 RPC(在角色类中) UFUNCTION(Client, Reliable) void ClientReceiveData(const FString& Data); // 实现 void AMyCharacter::ClientReceiveData_Implementation(const FString& Data) { UE_LOG(LogTemp, Warning, TEXT("接收数据:%s"), *Data); // 处理数据逻辑... } // 服务器触发发送 void AMyServerActor::SendDataToClient(AMyCharacter* TargetClient, const FString& Data) { if (TargetClient) { TargetClient->ClientReceiveData(Data); // 客户端执行 } } ``` - **特点**:服务器直接调用客户端函数,实时性强 - **用例**:实时同步游戏状态、指令下发[^2] #### 2. **变量复制 (Replication)** 通过属性复制自动同步数据: ```cpp // 头文件声明 UPROPERTY(ReplicatedUsing=OnRep_ServerData) FString ServerData; // 回调函数 UFUNCTION() void OnRep_ServerData(); // CPP 实现 void AMyActor::OnRep_ServerData() { UE_LOG(LogTemp, Warning, TEXT("更新数据:%s"), *ServerData); } // 服务器更新数据 void AMyActor::UpdateDataOnServer(const FString& NewData) { if (HasAuthority()) { ServerData = NewData; // 自动复制到客户端 } } ``` - **特点**:自动同步,适合频繁更新的数据 - **注意**:需在 `GetLifetimeReplicatedProps` 中注册属性[^2] #### 3. **异步回调机制** 结合委托处理非实时数据请求: ```cpp // 声明委托 DECLARE_DELEGATE_OneParam(FDataReceivedDelegate, const FString&); // 数据接收类 class FDataReceiver { public: FDataReceivedDelegate OnDataReceived; void RequestDataFromBackend() { // 模拟异步请求 AsyncTask(ENamedThreads::GameThread, [this]() { FString FakeData = "Backend Response"; OnDataReceived.ExecuteIfBound(FakeData); // 回调执行 }); } }; // 使用示例 void UMyWidget::FetchData() { FDataReceiver Receiver; Receiver.OnDataReceived.BindUObject(this, &UMyWidget::HandleData); Receiver.RequestDataFromBackend(); } void UMyWidget::HandleData(const FString& Data) { TextBlock->SetText(FText::FromString(Data)); } ``` - **特点**:解耦发送/接收逻辑,适合 HTTP 等异步请求[^1][^5] - **优势**:避免阻塞主线程,通过委托通知结果 --- ### 选择建议 1. **实时游戏交互** → 优先选用 RPC 或变量复制 2. **非实时后台通信** → 使用异步回调+委托 3. **复杂数据流** → 结合 RPC 和委托机制(如 RPC 触发后通过委托分发数据) > **关键注意事项**: > - RPC 函数必须用 `_Implementation` 后缀 > - 复制变量需要在 `GetLifetimeReplicatedProps` 注册 > - 委托绑定需注意 UObject 生命周期(避免野指针) > - 后台通信建议使用 UE 的 `Http` 模块或 `WebSockets` 模块[^5]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值