{"id":15272423,"url":"https://github.com/moqsien/niogin","last_synced_at":"2026-01-04T21:48:33.745Z","repository":{"id":61626817,"uuid":"524848788","full_name":"moqsien/niogin","owner":"moqsien","description":"NioGin is a Non-blocking implementation of Gin. All functionalities from Gin are supported by NioGin. 异步gin框架。","archived":false,"fork":false,"pushed_at":"2022-08-15T12:41:46.000Z","size":61,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-27T19:28:49.897Z","etag":null,"topics":["epoll","eventloop","gin","gin-gonic","go","http-server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moqsien.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-15T03:55:08.000Z","updated_at":"2022-08-24T15:10:34.000Z","dependencies_parsed_at":"2022-10-18T17:30:43.794Z","dependency_job_id":null,"html_url":"https://github.com/moqsien/niogin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moqsien%2Fniogin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moqsien%2Fniogin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moqsien%2Fniogin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moqsien%2Fniogin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moqsien","download_url":"https://codeload.github.com/moqsien/niogin/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244990069,"owners_count":20543614,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["epoll","eventloop","gin","gin-gonic","go","http-server"],"created_at":"2024-09-30T09:06:47.069Z","updated_at":"2026-01-04T21:48:33.705Z","avatar_url":"https://github.com/moqsien.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"### NioGin\n\n--------------\n\nNioGin is a Non-blocking implementation of Gin.\nAll functionalities from Gin are supported by NioGin.\nOnly epoll is supported by Now, kqueue is on the way.\n\nNioGin是一个异步http server，http协议处理、路由查找、中间件等都使用Gin框架的实现，只是底层的套接字管理替换为non-blocking io模式，即eventloop。所有的使用习惯与Gin均一致。\n\n本项目主要参考和使用了Thanks To中的项目，适用于学习eventloop的实现，以及对单机性能要求较高的场景。代码注释和实现逻辑描述比较清楚，比nbio和gev学习起来更方便。性能理论上比gev要强，没有nbio混乱的engine，request读取使用的是官方包的方法，比较清晰；因此可以方便地利用Gin的router、middleware、Context封装，得到一个功能完善的http server。\n\n--------------\n\n### Install\n\ngo get github.com/moqsien/niogin\n\n--------------\n\n### Usage\nSome simple examples as follows:\n- nonTLS\n```go\npackage main\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/moqsien/niogin/httpserver\"\n)\n\nfunc main() {\n\trouter := httpserver.New()\n\trouter.SetPoll(true) // use epoll, otherwise use official http server\n\trouter.GET(\"/test\", func(c *gin.Context) {\n\t\tc.JSON(http.StatusOK, gin.H{\"test\": \"hello\"})\n\t})\n\trouter.POST(\"/p\", func(c *gin.Context) {\n\t\ta, _ := c.GetPostForm(\"t\")\n\t\tc.JSON(http.StatusOK, gin.H{\"test\": a})\n\t})\n\terr := router.Start(\"localhost:8080\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t\treturn\n\t}\n}\n```\n\n- TLS\n```go\npackage main\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/moqsien/niogin/httpserver\"\n)\n\nfunc main() {\n\tcertFile, keyFile string := \"\", \"\"\n\trouter := httpserver.New()\n\trouter.SetPoll(true)  // use epoll, otherwise use official http server which is similar to Gin.\n\trouter.GET(\"/test\", func(c *gin.Context) {\n\t\tc.JSON(http.StatusOK, gin.H{\"test\": \"hello\"})\n\t})\n\trouter.POST(\"/p\", func(c *gin.Context) {\n\t\ta, _ := c.GetPostForm(\"t\")\n\t\tc.JSON(http.StatusOK, gin.H{\"test\": a})\n\t})\n\terr := router.StartTLS(\"localhost:8080\", certFile, keyFile)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t\treturn\n\t}\n}\n```\n--------------\n\n### ToDos\n- [x] http\n- [x] tls \n- [x] epoll\n- [ ] kqueue\n- [ ] websocket\n- [ ] rpc\n- [ ] jwt\n- [ ] limiter\n\n--------------\n\n### Design\n\n![eventloop](https://github.com/moqsien/niogin/blob/main/docs/design.png)\n\n1、Listener放在独立的epoll_wait中，监听新的连接请求，accept获得新的连接后，分发到workers(工作循环)监听新连接的读写事件；\n\n2、工作循环(workers)分为两类，即非共享型和共享型；\n\n3、非共享型worker，在一个时刻只绑定和监听一个新连接；\n\n4、共享型worker，在同一个时刻可以绑定和监听多个新连接，允许同时处理固定多个读写事件任务；\n\n5、新连接分发逻辑是：优先分发到空闲的非共享型worker上，如果没有空闲的非共享型worker，则会优先分发到已绑定的连接数最少的共享型worker上；\n\n6、每个连接在触发读事件时，该连接的请求数+1；会通过调度来把共享型worker上请求数排名靠前的连接交换到非共享型worker上；这样可以优先用性能更好的非共享型worker处理请求频繁的连接；\n\n--------------\n\n### Thanks To\n[Meng Huang(hslam)](https://github.com/hslam/netpoll)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoqsien%2Fniogin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoqsien%2Fniogin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoqsien%2Fniogin/lists"}