UE多实例云渲染之Nginx代理

news2025/1/8 6:09:21

Nginx的Https代理

我们实现UE像素流时大部分使用的是http协议,但是某些时候前端由于某些功能问题需要使用https的协议(如前端调用本地摄像头)需要使用https协议。如果此时在内部使用http请求就会被block掉。其中一种简单的方案就是通过修改浏览器的安全设置。

1 修改chrome

  1. 点击chrome url左侧的图标,进入该https的设置(Site settings)
  2. 找到: Insecure content,将block改成Allow
  3. chrome会提醒需要reload,点击reload即可

2 通过Nginx代理解决

某些情况下,前端调用摄像头需要使用https协议,https通常无法发送http的请求(对于一些静态的资源可以,接口服务不行)。相应的websocket的ws请求也要转换为wss请求。

1. 配置SSL证书

直接使用像素流插件的https设置需要在每一台云渲染的服务器上申请一份SSL的证书(https://www.joyssl.com/certificate/),申请证书一般情况下是需要收费的,证书是绑定域名,不同的域名需要不同的证书(域名识别为唯一值)。但是对于UE的多实例云渲染,为每台服务器绑定一个域名是不现实的。因此需要nginx来实现对http的反向代理.

2. 配置nginx

nginx用于做是一个高性能的HTTP和反向代理web服务器。 nginx教程(https://zhuanlan.zhihu.com/p/435009231),以下是一份支持https的的UE云渲染的初始写法。


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
		listen 80;
		listen 443 ssl;
		#配置HTTPS的默认访问端口为443。
		#如果未在此处配置HTTPS的默认访问端口,可能会造成Nginx无法启动。
		#如果您使用Nginx 1.15.0及以上版本,请使用listen 443 ssl代替listen 443和ssl on。
		server_name ue.hurrycloud.cn;  #服务器的访问名字;
		root html;
		index index.html index.htm;
    #设置SSL证书的地址,当前cert目录下;
		ssl_certificate cert/8892262_ue.hurrycloud.cn.pem;  
		ssl_certificate_key cert/8892262_ue.hurrycloud.cn.key; 
		ssl_session_timeout 5m;
		ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
		#表示使用的加密套件的类型。
		ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; #表示使用的TLS协议的类型,您需要自行评估是否配置TLSv1.1协议。
		ssl_prefer_server_ciphers on;
		#location / {
		#	root html;  #Web网站程序存放目录。
		#	index index.html index.htm;
		#}
	 
		location ^~/signallingserver/ {
			proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Nginx-Proxy true;
            proxy_cache_bypass $http_upgrade;
            #以下三行用于解决跨域问题。
      			add_header 'Access-Control-Allow-Origin' '*' always;
      			add_header 'Access-Control-Allow-Methods' 'GET,POST,DELETE,OPTION';
      			add_header 'Access-Control-Allow-Header' 'Content-Type,*';
            proxy_pass http://nodeapi; #反向代理
        }
		#wss的代理,解决websocket的代理问题。前端通过var weksocket=new WebkSocket("wss://ue.hurrycloud.cn/ws")创建连接。
		location /ws {

			proxy_pass http://websocket ; #//websocket的代理地址,如果要支持多个,可以通过设置负载均衡地址来解决多个服务器问题 如设置为
			proxy_redirect off;
			proxy_http_version 1.1; 
      #下面三个用于防止websocket默认1一分钟之内断开websocket连接
			proxy_connect_timeout 4s; #配置点1
      proxy_read_timeout 600s; #配置点2,如果没效,可以考虑这个时间配置长一点
      proxy_send_timeout 12s; #配置点3
      #websocket的标记
			proxy_set_header Upgrade $http_upgrade; 
			proxy_set_header Connection "Upgrade"; //websocket的代理标记,"Upgrade"是大小写区分的。
			proxy_set_header X-Real-IP $remote_addr;
		}            


   }
   
   upstream nodeapi {
			server 1.116.110.61:90;  //负载均衡地址服务器ip+端口
			#server 172.17.0.14:90;
			keepalive 64;
		}

    //websocket的负载均衡的地址。
     upstream websocket {
			server 1.116.110.61:801;  //负载均衡地址服务器ip+端口
			server 1.116.110.61:802;
			server 101.35.148.24:801;
			server 101.35.148.24:802;
			keepalive 64;
		}
   

}

以上配置主要解决以下几个问题

  1. https代理http的请求(如上代理的的http://1.116.110.61:90 的请求)
  2. 解决跨域问题
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET,POST,DELETE,OPTION';
add_header 'Access-Control-Allow-Header' 'Content-Type,*';

只是加以上代码是不能解决跨域问题的,在前端访问接口的时候会出现多个Access-Control-Allow-Origin请求头。直接在nginx上删除又不行。最后是在UE的matchmaker里面删除跨域相关代码。如下直接删除即可。

image.png

  1. 防止websocket默认一分钟断开连接
	proxy_connect_timeout 4s; #配置点1
  proxy_read_timeout 600s; #配置点2,如果没效,可以考虑这个时间配置长一点
  proxy_send_timeout 12s; #配置点3

以上实现有一个重要的问题,使用负载均衡的方式会出现在UE多实例中出现串流的现象(多个用户可能会同时进入一个websocket像素流)

我们需要的的是一个 websocket client 对应一个crrius的信令服务器,当一个客户端连接到服务端时,其他的客户端不能再次连接到这个信令服务器,否则会出现串流问题。如果使用负载均衡的调度方式,目前是没有办法让客户端和服务端实现1对1的占用式匹配,那目前的思路就不能使用负载均衡方案,解决办法是通过websocket的路由地址来做反向代理。

3. 解决串流问题

要使用路由解决像素流中客户端与服务器的1:1问题,前端就需要有一个动态路由(每一个前端可以通过统一的地址自动获取到当前服务器中已经开启的像素流服务的路由),由于https的协议问题,那么wss协议的域名必须是SSL证书申请时候的域名。如我申请的域名是: ue.hurrycloud.cn

3.1 修改后端像素流代码

  1. 给信令服务器cirrus添加标记(一个服务器机器添加一个标记即可.如在参数输入的时候添加 --Flag=“ueone”)
//cirrus 入口处添加
var ue_flag=config.Flag;

//设置连接matchmaker的地方添加一个flag标记传入到matchmarker中.
if (config.UseMatchmaker) {
	var matchmaker = new net.Socket();

	matchmaker.on('connect', function() {
		console.log(`Cirrus connected to Matchmaker ${matchmakerAddress}:${matchmakerPort}`);

		// message.playerConnected is a new variable sent from the SS to help track whether or not a player 
		// is already connected when a 'connect' message is sent (i.e., reconnect). This happens when the MM
		// and the SS get disconnected unexpectedly (was happening often at scale for some reason).
		var playerConnected = false;

		// Set the playerConnected flag to tell the MM if there is already a player active (i.e., don't send a new one here)
		if( players && players.size > 0) {
			playerConnected = true;
		}

		// Add the new playerConnected flag to the message body to the MM
		message = {
			type: 'connect',
			address: typeof serverPublicIp === 'undefined' ? '127.0.0.1' : serverPublicIp,
			port: httpPort,
			flag: ue_flag,  //新增一行代码,添加一个flag标记,ue_flag是cirrus外部参数传进来的一个参数
			ready: streamer && streamer.readyState === 1,
			playerConnected: playerConnected
		};

		matchmaker.write(JSON.stringify(message));
	});

  ....
}
  1. 在matchmarker连接中存储信令服务器标记
const matchmaker = net.createServer((connection) => {
	connection.on('data', (data) => {
		try {
			message = JSON.parse(data);

			if(message)
				console.log(`Message TYPE: ${message.type}`);
		} catch(e) {
			console.log(`ERROR (${e.toString()}): Failed to parse Cirrus information from data: ${data.toString()}`);
			disconnect(connection);
			return;
		}
		if (message.type === 'connect') {
			// A Cirrus server connects to this Matchmaker server.
			cirrusServer = {
				address: message.address,
				port: message.port,
				flag:message.flag,#获取标记,增加的代码
				numConnectedClients: 0,
				lastPingReceived: Date.now()
			};
...
}


//在前端做重定向的地方
if(enableRESTAPI) {
	// Handle REST signalling server only request.
	app.options('/signallingserver')
	app.get('/signallingserver', (req, res) => {
		cirrusServer = getAvailableCirrusServer();
		if (cirrusServer != undefined) {
     //返回到前端的数据,也就是信令服务器的websocket路由,是标记加端口组成。flagPath参数是为了让前端不需要解析做的
			res.json({ signallingServer: `${cirrusServer.address}/${cirrusServer.flag}${cirrusServer.port}`,flagPath:`${cirrusServer.flag}${cirrusServer.port}`});
			console.log(`Returning ${cirrusServer.address}:${cirrusServer.port}`);
		} else {
			res.json({ signallingServer: '', error: 'No signalling servers available'});
		}
	});
}
  1. 前端websocket代码
//获取信令服务器地址的



//创建websocket连接的地方
function connect() {
  // 建立长连接
  "use strict";

  window.WebSocket = window.WebSocket || window.MozWebSocket;

  if (!window.WebSocket) {
    alert('Your browser doesn\'t support WebSocket');
    return;
  }
  //  创建websocket的连接,域名加路由地址.
  ws = new WebSocket(`wss://ue.hurrycloud.cn/${flag_path}`);
  ....
}

//连接matchmarker的端口
function connectToMatchmakerServer(options, onConnect){

  //serverUrl的内容为 https://ue.hurrycloud.cn/signallingServer;
    let matchmakerServerAddr=options.serverUrl;
    //非信直连;
    if (matchmakerServerAddr.indexOf('signallingserver') != -1) {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
            if( xhr.readyState == 4){
                if( xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
                    let jsonData = JSON.parse(xhr.response);
                    console.log(jsonData.signallingServer);
                  //获取flag_path标记;
                    flag_path=jsonData.flagPath;

                    if (jsonData.error) {
                        console.log(jsonData.error);
                    } else {
                        console.log('ws to signal server: ', jsonData.signallingServer);
                        onConnect(jsonData.signallingServer);
                    }
                  }
            }
        };
        xhr.open("get", matchmakerServerAddr, true);
        xhr.send(null);
    } 
 
    else {
        matchmakerServerAddr=matchmakerServerAddr.replace('http://','');
        console.log('ws to server: ', matchmakerServerAddr);
        onConnect(matchmakerServerAddr);
        
    }
}
  1. nginx的配置
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
  worker_connections  1024;
}


http {
  include       mime.types;
  default_type  application/octet-stream;

  #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
  #                  '$status $body_bytes_sent "$http_referer" '
  #                  '"$http_user_agent" "$http_x_forwarded_for"';

  #access_log  logs/access.log  main;

  sendfile        on;
  #tcp_nopush     on;

  #keepalive_timeout  0;
  keepalive_timeout  65;

  #gzip  on;

  server {
    listen 80;
    listen 443 ssl;
    #配置HTTPS的默认访问端口为443。
    #如果未在此处配置HTTPS的默认访问端口,可能会造成Nginx无法启动。
    #如果您使用Nginx 1.15.0及以上版本,请使用listen 443 ssl代替listen 443和ssl on。
    server_name ue.hurrycloud.cn;
    root html;
    index index.html index.htm;
    ssl_certificate cert/8892262_ue.hurrycloud.cn.pem;  
    ssl_certificate_key cert/8892262_ue.hurrycloud.cn.key; 
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    #表示使用的加密套件的类型。
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; #表示使用的TLS协议的类型,您需要自行评估是否配置TLSv1.1协议。
    ssl_prefer_server_ciphers on;
    #location / {
    #	root html;  #Web网站程序存放目录。
    #	index index.html index.htm;
    #}

    location ^~/signallingserver/ {  #http的服务地址路由
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
      proxy_set_header X-Nginx-Proxy true;
      proxy_cache_bypass $http_upgrade;
      add_header 'Access-Control-Allow-Origin' '*' always;
      add_header 'Access-Control-Allow-Methods' 'GET,POST,DELETE,OPTION';
      add_header 'Access-Control-Allow-Header' 'Content-Type,*';
      proxy_pass http://nodeapi; #反向代理
    }

    location /ueone801 {   #路由为标记+端口号如 之前的标记为ueone服务器,端口为801
      proxy_pass http://1.116.110.61:801; #真实的websocket地址
      proxy_redirect off;
      proxy_http_version 1.1; 
      proxy_connect_timeout 4s; #配置点1
      proxy_read_timeout 600s; #配置点2,如果没效,可以考虑这个时间配置长一点
      proxy_send_timeout 12s; #配置点3
      proxy_set_header Upgrade $http_upgrade; 
      proxy_set_header Connection "Upgrade"; 
      proxy_set_header X-Real-IP $remote_addr;
    }            

    location /ueone802 {
      proxy_pass http://1.116.110.61:802;
      proxy_redirect off;
      proxy_http_version 1.1; 
      proxy_connect_timeout 4s; #配置点1
      proxy_read_timeout 600s; #配置点2,如果没效,可以考虑这个时间配置长一点
      proxy_send_timeout 12s; #配置点3
      proxy_set_header Upgrade $http_upgrade; 
      proxy_set_header Connection "Upgrade"; 
      proxy_set_header X-Real-IP $remote_addr;
    }            

  }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SOLID设计原则

1. SRP单一职责原则 任何一个软件模块都应该有且仅有一个被修改的原因。 反例是一个类的三个方法给三个部门提供服务&#xff0c;而这三个方法有一些公共子方法&#xff0c;很有可能因为A部门的代码变更改动&#xff0c;导致B、C部门调用的方法出现意料之外的结果。 2. OCP开…

nginx请求转发webSocket

原由 1.我有一个socket服务&#xff0c;用ip访问是成功的&#xff0c;但是老板说用这个不行&#xff0c;要用nginx请求转发&#xff0c;转发内网地址到某个域名 2.但是我改成了指定域名后失败&#xff0c;因为我没有配置nginx.conf 3.接下来一起学习下&#xff0c;怎么在ngin…

华硕电脑怎么录屏?华硕电脑录屏功能在哪?简单实用教程来了

​有很多小伙伴对如何录制华硕电脑的屏幕知识和信息知之甚少。现在大家都想多了解一些关于华硕电脑怎么录屏的相关知识和信息。所以今天小编收集了一些关于如何录制华硕电脑屏幕的知识和信息&#xff0c;与大家分享。 华硕电脑怎么录屏方法一&#xff1a;使用Windows自带的录屏…

day45 PHP反序列化POP链构造魔术方法原生类

前言 #知识点&#xff1a; 1、什么是反序列化操作&#xff1f;-格式转换 2、为什么会出现安全漏洞&#xff1f;-魔术方法 3、反序列化漏洞如何发现&#xff1f; -对象逻辑 4、反序列化漏洞如何利用&#xff1f;-POP链构造 补充&#xff1a;反序列化利用大概分类三类 -魔…

重磅来袭!共600页,又一分牛逼的Python文档面世!

前言 本文是为了帮大家快速学习 Python 中知识点&#xff0c;这套资料涵盖了诸多学习内容&#xff1a;面试题&#xff0c;教材视频&#xff0c;实战资料&#xff0c;电子书籍。 相信可以帮助大家在最短的时间内&#xff0c;能达到事半功倍效果&#xff0c;用来复习也是非常不…

150行代码写个低配版WPS?:手把手教你实现+附完整源码

前言&#xff1a;通过一个简单实例来实现Java的GUI编程&#xff0c;对于新手较为友好&#xff0c;且有一定的实用性&#xff0c;正在学习Java的同学看过来&#xff01;&#xff01;包教包会&#xff0c;如有疑问欢迎私信询问&#xff01; 目录 实例展示 一、GUI编程基本概念 …

java面向对象----抽象类 接口

目录 抽象类与抽象方法 概念 抽象类应用 接 口 概念 接口的特点&#xff1a; 接口应用举例 Java 8中关于接口的改进 内部类 如何声明局部内部类 局部内部类的特点 匿名内部类 总结 抽象类与抽象方法 概念 随着继承层次中一个个新子类的定义&#xff0c;类变得越…

机器学习之多元线性回归

1、多元线性回归模型&#xff1a;定义&#xff1a;具有多个特征的线性回归模型 多元线性回归模型&#xff0c;见下图&#xff1a; 多元线性回归总结&#xff08;参数、模型、损失函数、梯度下降算法&#xff09;见下图&#xff1a;【注意&#xff1a;梯度下降算法每次都是同时…

Vue2中过滤器的用法详解

目录 一、过滤器的概念 二、过滤器的使用位置 三、过滤器的分类 1、全局过滤器 2、本地过滤器 四、过滤器应用实例 1、使用过滤器实现省略号 2、使用过滤器处理时间戳 五、Vue3中已废弃过滤器 过滤器是vue中的一个特性&#xff0c;作用是用于对文本进行格式化的作用。…

动态与静态获取元素

&#x1f335;知识点简介 静态获取&#xff08;querySelectorAll&#xff09;时&#xff0c;选出的所有元素的数组&#xff0c;不会随着文档操作而改变&#xff1b; 动态获取&#xff08;getElementById&#xff09;时&#xff0c;选出的所有元素的数组&#xff0c;会随着文档的…

Paddle 点灯人 之 Tensor

Paddle 点灯人 之 Tensor 文章目录Paddle 点灯人 之 TensorPaddle点灯人介绍Tensor介绍Pytorch和Paddle的相似之处创建张量Tensor图片/文本转TensorDataLoader不需要加ToTensorPaddle中的 Tensor 的属性形状 shape数据类型&#xff08;dtype&#xff09;Tensor 的设备位置&…

高压放大器驱动压电器件工作原理

高压放大器在实际应用中经常会进行电容性负载驱动&#xff0c;对压电器件进行驱动&#xff0c;那么工作原理是什么呢&#xff0c;下面就请安泰电子来为我们讲解一下。 高压放大器是提高信号电压的装置&#xff0c;当负载是谐振电路或者耦合电路的时候&#xff0c;要求特定频率范…

Mybatis源码解析(十):一级缓存和二级缓存

Mybatis源码系列文章 手写源码&#xff08;了解源码整体流程及重要组件&#xff09; Mybatis源码解析(一)&#xff1a;环境搭建 Mybatis源码解析(二)&#xff1a;全局配置文件的解析 Mybatis源码解析(三)&#xff1a;映射配置文件的解析 Mybatis源码解析(四)&#xff1a;s…

转行学python?到底值不值

大学毕业后相当迷茫&#xff0c;不知道做些什么&#xff0c;于是跟着潮流去学了python&#xff0c;当年2w多买的python教程&#xff0c;三个月的时间成功上岸&#xff0c;现在用不着了&#xff0c;文末有领取方式。 面对当前情况&#xff0c;让众多职场人开始紧张&#xff0c;…

《棒球大联盟2nd》:青春赛场·棒球1号位

茂野大吾是个有着现役职业棒球选手的父亲的小学生。他因为向往曾经在棒球大联盟活跃的父亲吾郎&#xff0c;而开始了在少年棒球队“三船海豚队”的棒球训练。但是&#xff0c;因为背负着茂野二世这个称号的压力&#xff0c;无法发挥出原来的水平&#xff0c;以至于1年还不到就放…

基于java+springmvc+mybatis+jsp+mysql的整体衣柜定制系统

项目介绍 管理员后台&#xff1a; 功能&#xff1a;个人中心、客户管理、导购管理、店长管理、厂家管理 客户后台&#xff1a; 功能&#xff1a;个人中心、款式信息管理、款式预订管理、材料信息管理、材料预订管理、定制订单管理、安装信息管理、订单评价管理、联系客户管理 …

我发现了一个React、Vue等所有前端框架都存在的隐秘Bug?

什么 Bug&#xff1f; 昨天有个朋友请教了我一个问题&#xff0c;她在使用原生的 Details 元素封装一个手风琴组件。但是无论如何都不能按照预期工作。 起初我认为是她水平比较差&#xff0c;代码写的有问题。但是她一再向我保证绝对不是她的问题。所以我就抽出时间帮她看了一…

DP2515国产带SPI接口CAN总线控制器芯片兼容替代MCP2515/MCP2515-I/ST

目录什么是CAN&#xff1f;DP2515简介芯片特性参考原理图什么是CAN&#xff1f; CAN是控制器局域网络(Controller Area Network, CAN)的简称&#xff0c;是如今是国际上应用最广泛的现场总线之一&#xff0c;是ISO国际标准化的串行通信协议。在汽车产业中&#xff0c;出于对安…

项目管理必备,教你如何制作甘特图

甘特图是项目管理中常用的工具&#xff0c;又被称为横道图。 由表格和条形图组成&#xff0c;左侧显示项目中所有的任务及时间&#xff0c;右侧一条状进度条显示项目每个任务的进度。 因为它极其好用&#xff0c;不仅在比较大型和复杂的项目中被广泛使用&#xff0c;在日常工…

iPhone 微信多开,如何在苹果手机上安装多个微信,爱思助手怎么用?IPA文件怎么弄?

苹果实现微信多开,用爱思助手就能实现,简单易上手。爱思助手怎么用?IPA文件怎么弄? 设备:Mac(11.6)/14pm 助手:爱思助手 需求:在最新的苹果手机上实现微信多开 博主上个月底抢的14pm终于到手了,之前多开微信一直用的大灰免费版的,怎么说呢?挺好用的但是不稳定,…