Giter Club home page Giter Club logo

gowebsocket's Introduction

gowebsocket's People

Contributors

dependabot[bot] avatar link1st avatar onism68 avatar stellarisw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gowebsocket's Issues

大佬你好,请教一个问题

为什么一个连接进入,首先会有 Register,再然后才是 Login,是因为没有登录功能而做的妥协吗?或者是基于其他什么考虑呢?望回复,另外这个项目给我帮助很大,请问有交流群可以分享一下吗?

找不到配置文件

完整报错如下:
panic: Fatal error config file: Config File "config/app" Not Found in "[D:\Workspace\Go\src\github.com\link1st\gowebsocket]"

goroutine 1 [running]:
main.initConfig()
D:/Workspace/Go/src/github.com/link1st/gowebsocket/main.go:72 +0x29f
main.main()
D:/Workspace/Go/src/github.com/link1st/gowebsocket/main.go:27 +0x2d

为了跑这个项目,我go get了 14个小时,终于get完了,结果找不到配置文件。

你们都是怎么跑起来的呀?

有个小问题

非常好的项目 根据这个做了进一步的开发 但是有个问题 想请教一下
将您目前的代码修改为 用户登录后再登录之后 关闭旧的登录 但是由于EventUnregister 执行的不及时导致 AddUser 之后被删除;
也就是说 用户在A设备上登录 然后又去B设备登录 登录B设备的时候想将A设备踢下线
原本想的流程为:将设备A踢下线manager.Socket.Close() (这里会触发 client.write 的defer 方法 在这里往管道clientManager.Unregister里面写入了数据; 之后执行 manager.AddUser() 新的用户

但是实际执行的流程却是 先增加后删除 新登录的 和旧的 都被删除了 不知道我这样表达能不能让您明白

原本在A设备登录的时候 manager.User 大概是 map[1:0xc000035b00] 但是B登录后 就变空了

最后 希望您留个赞助码什么的 对目前的项目帮助挺大的!

基于收发数据分离,相比webSocket,整个项目似乎更适合用SSE EventSource实现

采用 HTTP 发送消息,为了收发数据分离,进行数据解耦,提升发送数据的成功率。
  • 服务分离,让acc系统尽量的简单一点,不掺杂其它业务逻辑
  • 发送消息是走http接口,不使用webSocket连接,采用收和发送数据分离的方式,可以加快收发数据的效率

基于这个项目的websocket只用于推送消息到客户端,而客户端发送消息则调用http接口,那么SSE似乎是一个更好的选择。

这个项目和 gochat 不同,客户端使用http接口来发消息,而不是使用grpc proto来通信,项目中的grpc仅用于服务间的通讯,那么websocket相对于SSE支持二进制和客户端主动发消息的双向通讯优势也就没有了,剩下的相比SSE全是劣势。

Gin server-sent-event 示例

Gin realtime-advanced 示例

Gin realtime-chat 示例

gin本身对SSE提供了支持,前端用起来更简单,创建一个EventSource对象就可以实现对数据流的监听,不需要前端去考虑断线重连,心跳等问题,同时还支持服务优雅降级,支持单独特定事件监听,也可指定事件ID等。

每个websocket服务的单一责任就是推消息到客户端,客户端则通过接口来发消息,那么选择更简单更轻量的SSE似乎更好。

protobuf 生成协议报错

protoc --go_out=./ *.proto
protoc-gen-go: unable to determine Go import path for "im_protobuf.proto"

Please specify either:
• a "go_package" option in the .proto source file, or
• a "M" argument on the command line.

使用这个可以生成,与之前的比较又不一样。请问是用的那个版本,如何生成im_protobuf.pb.go 文件?
我用的方式是brew install protobuf
go get -u google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go
go get -u google.golang.org/grpc/cmd/protoc-gen-go-grpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc

这个命令可以执行,但是与原来的不一样,代码未改动,我想生成一个。使用的是mac m1
protoc -I=. --go_out=. --go-grpc_out=. im_protobuf.proto

CentOS7云服务器重启导致 runtime error: invalid memory address or nil pointer dereference

请教前辈一个问题:

前提说明:
本地和云端都没有使用Nginx,仅仅是单纯的运行。

问题如下:
本地Windows环境IDEA跑这个项目,多次重启都没有问题,聊天页面可以进行聊天;
把项目放到阿里云CentOS 7 服务器上,第一次启动也没问题,聊天页面可以进行聊天。
但是,一旦重新启动,即Ctrl+C停止服务后,再次go run main.go,聊天页面就无法访问。

前端Http状态码返回503
后端报错如下:

2019/12/25 14:29:23 http: panic serving 114.64.253.3:3257: runtime error: invalid memory address or nil pointer dereference
goroutine 171 [running]:
net/http.(*conn).serve.func1(0xc00018e8c0)
	/usr/lib/golang/src/net/http/server.go:1767 +0x139
panic(0xc26460, 0x13bd940)
	/usr/lib/golang/src/runtime/panic.go:679 +0x1b2
github.com/gin-gonic/gin.(*Context).Next(0xc00009cbb0)
	/home/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:124 +0x36
github.com/gin-gonic/gin.(*Engine).handleHTTPRequest(0xc000141400, 0xc00009cbb0)
	/home/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:389 +0x5b2
github.com/gin-gonic/gin.(*Engine).ServeHTTP(0xc000141400, 0xe562e0, 0xc00017e380, 0xc0000d7600)
	/home/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:351 +0x134
net/http.serverHandler.ServeHTTP(0xc00017e1c0, 0xe562e0, 0xc00017e380, 0xc0000d7600)
	/usr/lib/golang/src/net/http/server.go:2802 +0xa4
net/http.(*conn).serve(0xc00018e8c0, 0xe58920, 0xc000288700)
	/usr/lib/golang/src/net/http/server.go:1890 +0x875
created by net/http.(*Server).Serve
	/usr/lib/golang/src/net/http/server.go:2927 +0x38e

如果把项目文件夹从阿里云服务器删除,然后重新上传,再次启动,依然是第一次启动可以访问通,再次重启无法访问,一样的报错。

云端启停都是root用户。

我根据 runtime error: invalid memory address or nil pointer dereference 去网上搜索:

网上有些人说是代码的问题,但是,第一次运行的时候,确实是能跑通的。

还有人说是centOS7 防火墙问题,我检测了一下,防火墙是关闭状态。

前辈是否也遇到过同样的问题呢?

你好,请问可以用您的项目来作为论文吗?

我正在写一片论文,使用golang服务的+uni-app客户端,需要一些文档,看见您的项目,故想拿来参考一下,会拜读您的项目,理解后,进行重写,您的项目功能太多了,所以只会使用您的一部分功能。不会原封不动抄,望回复。

websocket高可用如何实现向指定的客户端发送消息?

老师,您好。看你这个项目是使用nginx做的负载均衡,我有一个疑问:

  • 现有server A和server B
  • 客户端向服务端建立连接: client A -> server A
  • 如果使用API方式,调用websocket集群,向client A发送消息。因clientA是与server A建立的长连接,如何保障消息是通过server A发送到client A的,server B是没法发送消息到client A的?

grpc_server中QueryUsersOnline的疑问

感谢作者的开源项目,看了下源码,有两处疑问希望作者帮忙解答下,不确定是不是我有遗漏

grpc_server中QueryUsersOnline

我理解的如果是分布式部署,所有机器共用一个redis的,用户在线信息是可以直接查redis拿到的,这里设计一个grpc的接口作用是啥呢,我想到一种,就是不能直接访问redis的服务,通过rpc调用去获得用户在线信息

源码中设计了通过心跳来维持用户在线信息,可是没有找到使用的地方

在这里 https://github.com/link1st/gowebsocket/blob/master/servers/websocket/user_srv.go#L103
只是把用户在线信息从redis中取出来,并没有检查其中的用户是否在线,其中有个心跳时间,还有个是否退出的标识,我的理解既然用心跳来维持用户在线状态了,是不是得检查下,这里是不是真的遗漏了,还是有其他考虑呢

能不能加一个登录授权的功能啊

比如我集成在自己的系统里,前端要直接连接到websocket服务上,后端还要用http发信息到websocket上,那这个安全的问题应该怎么做呢

Errors you may encounter when upgrading the library

(The purpose of this report is to alert link1st/gowebsocket to the possible problems when link1st/gowebsocket try to upgrade the following dependencies)

An error will happen when upgrading library gin-gonic/gin:

github.com/gin-gonic/gin

-Latest Version: V1.6.3 (Latest commit 6a8b8b6 on 3 May)
-Where did you use it:
https://github.com/link1st/gowebsocket/search?q=gin-gonic%2Fgin&unscoped_q=gin-gonic%2Fgin
-Detail:

github.com/gin-gonic/gin/go.mod

module github.com/gin-gonic/gin
go 1.13
require (
	github.com/gin-contrib/sse v0.1.0
	github.com/go-playground/validator/v10 v10.2.0
	…
)

github.com/gin-gonic/gin/binding/default_validator.go

package binding
import (
	"reflect"
	"sync"
	"github.com/go-playground/validator/v10"
)

This problem was introduced since gin-gonic/gin v1.6.0 . Now you used the version v1.4.0 . If you try to upgrade gin-gonic/gin to version v1.6.0 and above, you will get an error--- no package exists at "github.com/go-playground/validator/v10"

I investigated the libraries' (gin-gonic/gin >= v1.6.0) release information and found the root casue of this issue is that----

  1. These dependencies all added Go modules in the recent versions.

  2. They all comply with the specification of "Releasing Modules for v2 or higher" available in the Modules documentation. Quoting the specification:

A package that has migrated to Go Modules must include the major version in the import path to reference any v2+ modules. For example, Repo github.com/my/module migrated to Modules on version v3.x.y. Then this repo should declare its module path with MAJOR version suffix "/v3" (e.g., module github.com/my/module/v3), and its downstream project should use "github.com/my/module/v3/mypkg" to import this repo’s package.

  1. This "github.com/my/module/v3/mypkg" is not the physical path. So earlier versions of Go (including those that don't have minimal module awareness) plus all tooling (like dep, glide, govendor, etc) don't have minimal module awareness as of now and therefore don't handle import paths correctly See golang/dep#1962, golang/dep#2139.

Note: creating a new branch is not required. If instead you have been previously releasing on master and would prefer to tag v3.0.0 on master, that is a viable option. (However, be aware that introducing an incompatible API change in master can cause issues for non-modules users who issue a go get -u given the go tool is not aware of semver prior to Go 1.11 or when module mode is not enabled in Go 1.11+).
Pre-existing dependency management solutions such as dep currently can have problems consuming a v2+ module created in this way. See for example dep#1962.
https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher

Solution

1. Migrate to Go Modules.

Go Modules is the general trend of ecosystem, if you want a better upgrade package experience, migrating to Go Modules is a good choice.

Migrate to modules will be accompanied by the introduction of virtual paths(It was discussed above).

This "github.com/my/module/v3/mypkg" is not the physical path. So Go versions older than 1.9.7 and 1.10.3 plus all third-party dependency management tools (like dep, glide, govendor, etc) don't have minimal module awareness as of now and therefore don't handle import paths correctly.

Then the downstream projects might be negatively affected in their building if they are module-unaware (Go versions older than 1.9.7 and 1.10.3; Or use third-party dependency management tools, such as: Dep, glide, govendor…).

2. Maintaining v2+ libraries that use Go Modules in Vendor directories.

If link1st/gowebsocket want to keep using the dependency manage tools (like dep, glide, govendor, etc), and still want to upgrade the dependencies, can choose this fix strategy.
Manually download the dependencies into the vendor directory and do compatibility dispose(materialize the virtual path or delete the virtual part of the path). Avoid fetching the dependencies by virtual import paths. This may add some maintenance overhead compared to using modules.

As the import paths have different meanings between the projects adopting module repos and the non-module repos, materialize the virtual path is a better way to solve the issue, while ensuring compatibility with downstream module users. A textbook example provided by repo github.com/moby/moby is here:
https://github.com/moby/moby/blob/master/VENDORING.md
https://github.com/moby/moby/blob/master/vendor.conf
In the vendor directory, github.com/moby/moby adds the /vN subdirectory in the corresponding dependencies.
This will help more downstream module users to work well with your package.

3. Request upstream to do compatibility processing.

The gin-gonic/gin have 2104 module-unaware users in github, such as: yogaagungk/assets-management, aduermael/dockerblog, gdevillele/calvados…
https://github.com/search?q=gin-gonic%2Fgin+filename%3Avendor.conf+filename%3Avendor.json+filename%3Aglide.toml+filename%3AGodep.toml+filename%3AGodep.json

Summary

You can make a choice when you meet this DM issues by balancing your own development schedules/mode against the affects on the downstream projects.

For this issue, Solution 1 can maximize your benefits and with minimal impacts to your downstream projects the ecosystem.

References

Do you plan to upgrade the libraries in near future?
Hope this issue report can help you ^_^
Thank you very much for your attention.

Best regards,
Kate

关于掉线问题

测试的时候,短时间登录上200时候(测试机器8G内存) 突然就会有好几十账号突然掉线。而且用NGINX 配置wss,跑不上40个链接,到了40左右其他账户马上全部掉线。请问这个可能是什么问题呢

请问为什么使用 HTTP 方式发送消息?

请问为什么不直接通过 WebSocket 向服务器发送消息,而是由客户端调用 HTTP 接口将消息数据传送至服务器后,服务器再发送 WebSocket 到目标客户端?这样设计有什么用意吗?

一个用户重复登录的问题。

当用 userId 为同一个id 时,再次登录时,而先前登录的 则收不到信息。

不是知道 底层是否如下描述?

限制已经登录的 不能再次登录,必须执行在异地或本地另开网页,输入密码执行退出登录前面的, 然后再次登陆,先前登录的则收到自己被迫下线。

关于心跳包的问题

我看gorilla/websocket包使用的是SetReadDeadlineSetPongHandler实现的ping-pong,你这个项目是通过定时轮询整个clientIds+自定义heatbeat请求刷新心跳时间。
我想知道SetReadDeadlineSetPongHandler是不是更好的解决办法

这个项目可以分布式吗

我看您的架构图是可以部署多个gowebcoket的。 如果user1 分配到gowebsocket1登录,user2分配到gowebsocket2登录。 他们可以可以在同一个房间appid=102聊天吗。 我看的您的源码好像做不到,gowebsocket1的client不能发送消息到gowebsocket2的client中吧。

非常好的项目

这个项目文档真的是太详细了,对我这种刚学习的人来说,收益很大。强烈建议录制一些收费的教学视频。

如何和java通讯?

我们的业务后端是java,需求比较简单,就是把消息(相当于私信公告)推到前端去。
类似这个:
image

简单的业务流如下:
image

我的问题是:java怎么调用gowebsocket发消息,有现成的方法吗?还是说java要模拟websocket和gowebsocket通讯才可以?

多机部署时,rpcServer为空问题

rpcServer会定时注册,每60秒获取当前机器信息,并存入 redis hSet 中(acc:hash:servers)

        number, err := redisClient.Do("hSet", key, server.String(), value).Int()
	if err != nil {
		fmt.Println("SetServerInfo", key, number, err)

		return
	}
        // 如果字段是哈希表中的一个新建字段,并且值设置成功,返回 1 。 如果哈希表中域字段已经存在且旧值已被新值覆盖,返回 0
	if number != 1 {
		return
	}
        redisClient.Do("Expire", key, serversHashCacheTime)

问题在 number,如果机器固定,那么后续定时任务并不会执行 EXPIRE刷新redis键(acc:hash:servers)生命周期
导致在2小时后,rpcServer 是为空的状态,持续时间不固定(小于2分钟)
进而导致用户进入房间不会通知其它用户,收发消息也会有问题

建议删除 if number 判断语句

nginx会不会成为性能瓶颈?

你好,nginx做websocket代理转发要分别跟客户端和websocket服务维持长连接,对于websocket服务来说nginx也是客户端,一个客户端一个ip的话只能创建65535个长连接,那这是不是成了性能瓶颈了?

代码疑问

func (manager *ClientManager) GetUserList(appId uint32) (userList []string) {
userList = make([]string, 0)
clientManager.UserLock.RLock()
defer clientManager.UserLock.RUnlock()
for _, v := range clientManager.Users {
if v.AppId == appId {
userList = append(userList, v.UserId)
}
}
fmt.Println("GetUserList len:", len(clientManager.Users))
return
}

为什么使用 全局变量 clientManager 而不是 方法接收者变量 manager ,是手误还是有啥讲究?

func (manager *ClientManager) GetUsersLen() (userLen int) {
userLen = len(manager.Users)
return
}

这里的 len 需要加锁吗?

会加RabbitMQ和单聊/私有群聊么

会加RabbitMQ和单聊么,因为现在只有公共聊天的,但是对于私有群聊以及单聊的逻辑不是很清楚,请问下是否会加呢?想请教一下!

client manager 中两个小问题

client_manager.go中ClearTimeoutConnections
1.client manager遍历时没加锁;
2.client关闭的时候,client中的SendChan没关闭,clients的map中没有删除这个client。

不知道说的对不对。从你的项目吸收了不少东西,借此感谢!

关于监听消息的疑问

我们在浏览器前端要监听2类消息,

  • 私信
  • 群消息(具体来说是给某一类用户广播消息)

建立1个websocket连接能不能做同时监听这两类消息?

ClearTimeoutConnections定时清理超时连接 问题

作者你好,在这个函数中是不是要增加 如果心跳超时,就要删除对于的 map 如 delete (client,Client)防止key太多占内存, 同时设置对应的UserOnline 为nil ,已清空变量及其redis 中UserOnline 的相应的键名

maingo: run command at func open() failed

at main.go, command "open" out is "failed to call Output(): exec: "open": executable file not found in $PATH".
why run command "open httpurl" here?

func open() {

time.Sleep(1000 * time.Millisecond)

httpUrl := viper.GetString("app.httpUrl")
httpUrl = "http://" + httpUrl + "/home/index"

fmt.Println("访问页面体验:", httpUrl)

cmd := exec.Command("open", httpUrl)
cmd.Output()

}

有个疑问,为什么客户端不使用websocket send的方式发送消息

WebSocket 与客户端建立持久的双向通信连接,这样客户端可以直接通过 WebSocket 连接发送和接收实时的消息,而不需要每次都发起一个新的 HTTP 请求。这种实时性对于即时聊天应用非常重要,因为它允许消息的快速传递和实时更新。
使用 HTTP 发送消息需要建立一个新的请求-响应循环,每次发送消息都需要发起一个新的 HTTP 请求,这会引入较大的延迟,并且增加服务器的负载。使用 WebSocket 可以在客户端和服务器之间建立实时的双向通信,服务器可以直接将消息推送到客户端,而不需要等待客户端发起请求。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.