首页 > 系统相关 >fiber使用websocket--多进程版本

fiber使用websocket--多进程版本

时间:2024-04-22 17:56:26浏览次数:32  
标签:em fiber websocket log -- 0.5 item var

多进程数据是隔离的,也就是说处理不好,不同的用户登录,其实不在一个进程,没办法直接通信

解决办法:定义一个全局变量,所有进程公用,要加锁

如果是单进程版本其实就跟gin框架那些一样了多线程+channel不存在数据隔离的问题

main.go

package main

import (
	"flag"
	"fmt"
	"log"
	"sync"

	"github.com/gofiber/contrib/websocket"
	"github.com/gofiber/fiber/v2"
)

// Add more data to this type if needed
type client struct {
	isClosing bool
	mu        sync.Mutex
}

// Note: although large maps with pointer-like types (e.g. strings) as keys are slow,
// using pointers themselves as keys is acceptable and fast
var clients = make(map[*websocket.Conn]*client)

func main() {
	app := fiber.New(fiber.Config{
		Prefork: true,
	})

	app.Static("/", "./home.html")

	app.Use(func(c *fiber.Ctx) error {
		if websocket.IsWebSocketUpgrade(c) { // Returns true if the client requested upgrade to the WebSocket protocol
			return c.Next()
		}
		return c.SendStatus(fiber.StatusUpgradeRequired)
	})

	app.Get("/ws", websocket.New(func(c *websocket.Conn) {
		// When the function returns, unregister the client and close the connection
		defer func() {
			fmt.Println("触发了删除")
			delete(clients, c)
			c.Close()
		}()

		// Register the client
		clients[c] = &client{}
		log.Println(len(clients))
		for {
			messageType, message, err := c.ReadMessage()
			if err != nil {
				if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
					log.Println("read error:", err)
				}
				return
			}
			if messageType == websocket.TextMessage {
				// Broadcast the received message
				for connection, c := range clients {
					go func(connection *websocket.Conn, c *client) { // send to each client in parallel so we don't block on a slow client
						c.mu.Lock()
						defer c.mu.Unlock()
						if c.isClosing {
							return
						}
						if err := connection.WriteMessage(websocket.TextMessage, []byte(message)); err != nil {
							c.isClosing = true
							log.Println("write error:", err)
							connection.WriteMessage(websocket.CloseMessage, []byte{})
							connection.Close()
							delete(clients, connection)
						}
					}(connection, c)
				}
			} else {
				log.Println("websocket message received of type", messageType)
			}
		}
	}))

	addr := flag.String("addr", ":8080", "http service address")
	flag.Parse()
	log.Fatal(app.Listen(*addr))
}

html

<!-- See https://github.com/gorilla/websocket/blob/master/examples/chat/home.html -->

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>Chat Example</title>
	<script type="text/javascript">
		window.onload = function () {
			    var conn;
			    var msg = document.getElementById("msg");
			    var log = document.getElementById("log");

			    function appendLog(item) {
				            var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
				            log.appendChild(item);
				            if (doScroll) {
						                log.scrollTop = log.scrollHeight - log.clientHeight;
						            }
				        }

			    document.getElementById("form").onsubmit = function () {
				            if (!conn) {
						                return false;
						            }
				            if (!msg.value) {
						                return false;
						            }
				            conn.send(msg.value);
				            msg.value = "";
				            return false;
				        };

			    if (window["WebSocket"]) {
				            conn = new WebSocket("ws://" + document.location.host + "/ws");
				            conn.onclose = function (evt) {
						                var item = document.createElement("div");
						                item.innerHTML = "<b>Connection closed.</b>";
						                appendLog(item);
						            };
				            conn.onmessage = function (evt) {
						                var messages = evt.data.split('\n');
						                for (var i = 0; i < messages.length; i++) {
									                var item = document.createElement("div");
									                item.innerText = messages[i];
									                appendLog(item);
									            }
						            };
				        } else {
						        var item = document.createElement("div");
						        item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
						        appendLog(item);
						    }
		};
	</script>
<style type="text/css">
html {
	    overflow: hidden;
}

					    body {
						        overflow: hidden;
							    padding: 0;
							        margin: 0;
								    width: 100%;
								        height: 100%;
									    background: gray;
					    }

					    #log {
						        background: white;
							    margin: 0;
							        padding: 0.5em 0.5em 0.5em 0.5em;
								    position: absolute;
								        top: 0.5em;
									    left: 0.5em;
									        right: 0.5em;
										    bottom: 3em;
										        overflow: auto;
					    }

					    #form {
						        padding: 0 0.5em 0 0.5em;
							    margin: 0;
							        position: absolute;
								    bottom: 1em;
								        left: 0px;
									    width: 100%;
									        overflow: hidden;
					    }

</style>
	</head>
	<body>
		<div id="log"></div>
		<form id="form">
			    <input type="submit" value="Send" />
			        <input type="text" id="msg" size="64" autofocus autocomplete="off" />
		</form>
	</body>
</html>

标签:em,fiber,websocket,log,--,0.5,item,var
From: https://www.cnblogs.com/qcy-blog/p/18151124

相关文章

  • 为何3D动画工作室偏爱使用在线渲染农场?
    随着市场需求的不断增长和生产挑战的加剧,3D动画工作室面临着前所未有的压力。为了有效应对这些挑战,众多工作室选择了使用网络渲染农场。这种选择使他们能够借助网络渲染农场的强大渲染能力和高度灵活的资源配置,以此优化他们的工作流程,削减成本并缩短制作时间。 一、网络渲染农......
  • 多线程
    1.线程(Thread)和进程(Process) 进程是操作系统分配的实例,它是由操作系统分配的单元 线程是进程的执行单元,由操作系统进行调度,一个进程可以有多个线程,这些线程共享一个进程的资源 进程是相互独立的,他们之间不会相互影响 线程是共享相同进程的资源,因此一个线程可能会影响所在的......
  • js逆向实战之微信公众平台pwd参数解密
    网址:https://mp.weixin.qq.com/分析过程调出开发者工具,切换到network模块,随便输入一个账号和密码,抓包。看到pwd参数被加密了,接下来就是去找到pwd参数的加密过程。但其实这里可以进行加密方法的猜测,密码处输入123456,抓包。相信有经验的人可以很快的反应出是个md5算法。其......
  • python+appium+pytest做app自动化测试
    我在另一篇博客中写了使用unittest做app自动化测试的,包含了前期的环境的环境搭建,请参考如下链接:python+appium+unittest做app自动化测试这里,我们使用pytest框架再改写一个版本,因为pytest做测试报告看着更加好看,代码改良如下:fromappiumimportwebdriverimportpytest@pytest......
  • NET6 Hangfire 可视化配置
    Nuget<PackageReferenceInclude="Hangfire"Version="1.8.5"/><PackageReferenceInclude="Hangfire.AspNetCore"Version="1.8.5"/><PackageReferenceInclude="Hangfire.Console"Version="1......
  • 刚交付了智慧园区统一管理平台,前端零代码+后端零代码+物联网平台,完美搭配!(一)
    先看下交付效果,2人3个月完成,涉及120个页面,80来个接口,30多个二级模块。其中负责前端的实施工程师,无需懂任何代码编程。其中界面和功能,基本是严格按照墨刀的产品原型实现的: 记录下这个有意思的过程。我是后端工程师,前端开发懂一点点但也不多,平时开发底层为主,CURD项目业务......
  • 详解工业网关在线探测功能及用途
    工业网关专为工业物联网应用设计,可实现包括不同通讯协议之间的兼容和转换,提供软硬件加密保障工业数据安全传输,发挥强大算力实现数据边缘预处理,联动联调工业网络设备实现高效协同等。在线探测功能是佰马工业网关的一项重要功能,本文就为大家介绍一下工业网关在线探测功能及用途。 ......
  • vis.js动态样式折线图
    代码案例<!doctypehtml><html><head><title>Timeline</title><scripttype="text/javascript"src="https://unpkg.com/vis-timeline@latest/standalone/umd/vis-timeline-graph2d.min.js"></script>......
  • 下级平台级联EasyCVR视频汇聚平台后,设备显示层级并存在重复的原因排查
    视频汇聚平台/视频监控系统/国标GB28181协议EasyCVR安防平台可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力,平台支持7*24小时实时高清视频监控,能同时播放多路监控视频流,视频画面1......
  • 缓存问题+Spring Cache
    在微信小程序端,展示菜品的相关信息时,如果同一时间有大量用户访问或点餐,其实会生成很多sql语句,数据库访问压力很大的,如果访问压力过大,造成数据库性能下降,用户的体验感下降,具体体现在,点击菜品信息后,一直转圈。 如果把这个商品缓存到redis中,这样可以大大提高查询性能 实现思路......