{"id":21968465,"url":"https://github.com/duyanming/viper","last_synced_at":"2025-05-15T05:08:01.970Z","repository":{"id":49391277,"uuid":"298792119","full_name":"duyanming/Viper","owner":"duyanming","description":"Viper 是一个基于Anno微服务引擎开发的Dashboard示例项目。Anno 底层通讯采用 grpc、thrift。自带服务发现、调用链追踪、Cron 调度、限流、事件总线等等","archived":false,"fork":false,"pushed_at":"2023-12-23T13:56:11.000Z","size":2544,"stargazers_count":733,"open_issues_count":0,"forks_count":176,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-05-15T05:07:49.367Z","etag":null,"topics":["anno","apigateway","cqrs","dashboard","ddd","grpc","microservice","thrift","viper"],"latest_commit_sha":null,"homepage":"http://anno.liqingxi.cn/","language":"C#","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/duyanming.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-26T10:40:33.000Z","updated_at":"2025-05-07T08:00:11.000Z","dependencies_parsed_at":"2023-12-23T16:13:31.559Z","dependency_job_id":null,"html_url":"https://github.com/duyanming/Viper","commit_stats":{"total_commits":190,"total_committers":4,"mean_commits":47.5,"dds":"0.22631578947368425","last_synced_commit":"c93c07ac4f47cf4d5f2386bea921bf954f403832"},"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duyanming%2FViper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duyanming%2FViper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duyanming%2FViper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duyanming%2FViper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/duyanming","download_url":"https://codeload.github.com/duyanming/Viper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254276447,"owners_count":22043867,"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":["anno","apigateway","cqrs","dashboard","ddd","grpc","microservice","thrift","viper"],"created_at":"2024-11-29T13:56:04.358Z","updated_at":"2025-05-15T05:07:56.961Z","avatar_url":"https://github.com/duyanming.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🎄Viper\n​\t\tViper 是一个基于[Anno](https://github.com/duyanming/Anno.Core)微服务引擎开发的Dashboard项目、示例项目。Anno 底层通讯可选用grpc、thrift。自带服务发现、调用链追踪、Cron 调度、限流、事件总线等等\n\n![Dashboard](https://s1.ax1x.com/2023/03/19/ppYj8ED.png)\n![Dashboard](https://s1.ax1x.com/2023/03/19/ppYjsUg.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/RawXSs.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/Ra0FfJ.png)\n![Dashboard](https://s1.ax1x.com/2023/03/19/ppYj22n.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/RadWrV.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/RadXqK.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/RawPxI.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/RaweIg.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/RawhQI.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/Ra0tnP.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/Ra0ocR.png)\n![Dashboard](https://z3.ax1x.com/2021/06/29/RaBkE8.png)\n\n##  🎩[Java 实现 ](https://github.com/duyanming/anno.thrift-parent) : https://github.com/duyanming/anno.thrift-parent\n\n##  🔥[在线演示地址](http://anno.liqingxi.cn) :http://anno.liqingxi.cn\n    账号：anno\n    密码：123456\n# 🎃Anno 分布式开发框架\n\n​\t\t\tAnno 是一个分布式开发框架，支持 .net core3.1 、.net frameworker4.5 、 java\n\n## 🎯1、运行Viper\n\n### 🔫MySQL 数据库\n\n```xml\n运行数据库脚本创建数据库\n\n\t1、Viper\\database\\viper20210617_01.sql\n\n\t2、修改viperService 数据库连接字符串\n\t\tViper\\ViperService\\bin\\Debug\\net6.0\\Anno.config\n```\n\n```xml\n\u003cappSettings\u003e\n    \u003c!-- 数据库连接字符串 Mysql--\u003e\n    \u003cadd key=\"ConnStr\" value=\"server=127.0.0.1;database=viper;uid=bif;pwd=123456;SslMode=None;\"/\u003e\n\u003c/appSettings\u003e\n```\n\n\n```\n第一步：启动注册中心\n\tViper\\ViperCenter\\bin\\Debug\\net6.0\\Anno.config\n```\n\n``` xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cconfiguration\u003e\n  \u003c!--ViperCenter 端口--\u003e\n  \u003cPort\u003e7010\u003c/Port\u003e\n    \u003c!--ViperCenter 超时时间--\u003e\n  \u003cTimeOut\u003e120000\u003c/TimeOut\u003e\n  \u003cServers\u003e\n       \u003c!--dc 注册到注册中心的 服务节点 （下面的内容是ViperService 启动后自动写入的内容）--\u003e\n    \u003cdc name=\"Anno.Plugs.LogicService,Anno.Plugs.TraceService,Anno.Plugs.ViperService\" nickname=\"ViperService-01\" ip=\"100.100.100.9\" port=\"7011\" timeout=\"20000\" weight=\"1\" /\u003e\n  \u003c/Servers\u003e\n\u003c/configuration\u003e\n```\n\n\n\n### 进入项目文件夹 \n\nViper\\ViperCenter\\bin\\Debug\\net6.0\n运行命令 dotnet ViperCenter.dll\n看到下图 说明运行成功\n![第一步](https://z3.ax1x.com/2021/04/01/cE4a5T.png)\n\n```\n第二步：启动 ViperService\n\tViper\\ViperService\\bin\\Debug\\net6.0\\Anno.config\n```\n\n``` xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\" ?\u003e\n\u003cconfiguration\u003e\n  \u003c!--0,0 第一位是 工作站，第二位数据中心\n  （所有的 AnnoService 的 两位数不能重复例如不能存在【1,2】【1,2】）\n  可以存在【1,2】【2,1】\n  --\u003e\n  \u003cIdWorker\u003e0,0\u003c/IdWorker\u003e\n  \u003c!--App名称--\u003e\n  \u003cAppName\u003eViperService-01\u003c/AppName\u003e\n  \u003c!--监听端口--\u003e\n  \u003cPort\u003e7011\u003c/Port\u003e\n  \u003c!--权重--\u003e\n  \u003cWeight\u003e1\u003c/Weight\u003e\n  \u003c!--功能 非Anno.Plugs  加入方式--\u003e\n  \u003cFuncName\u003e\u003c/FuncName\u003e\n  \u003c!--忽略的功能 Trace,Logic--\u003e\n  \u003cIgnoreFuncName\u003e\u003c/IgnoreFuncName\u003e\n  \u003c!--超时时间毫秒--\u003e\n  \u003cTimeOut\u003e20000\u003c/TimeOut\u003e\n  \u003c!--注册到的目标--\u003e\n  \u003cTs Ip=\"127.0.0.1\" Port=\"7010\"/\u003e\n  \u003cIocDll\u003e\n    \u003c!-- IOC 仓储--\u003e\u003c!--\n    \u003cAssembly\u003eAnno.Repository\u003c/Assembly\u003e\n    --\u003e\u003c!-- 领域--\u003e\u003c!--\n    \u003cAssembly\u003eAnno.Domain\u003c/Assembly\u003e\n    --\u003e\u003c!-- 查询服务--\u003e\u003c!--\n    \u003cAssembly\u003eAnno.QueryServices\u003c/Assembly\u003e\n    --\u003e\u003c!--事件Handler--\u003e\u003c!--\n    \u003cAssembly\u003eAnno.Command.Handler\u003c/Assembly\u003e--\u003e\n  \u003c/IocDll\u003e\n  \u003cappSettings\u003e\n    \u003c!-- 数据库连接字符串 Mysql--\u003e\n    \u003cadd key=\"ConnStr\" value=\"server=127.0.0.1;database=viper;uid=bif;pwd=123456;SslMode=None;\"/\u003e\n    \u003c!--\n    redisConn Redis 连接字符串 127.0.0.1:6379,abortConnect=false,allowAdmin =true,keepAlive=180\n    redisPrefix Key 前缀 Anno:\n    redisExpiryDate Key 有效期  单位（分钟） 20\n    redisSwitch 是否开启数据库 false 不开启 false\n    \u003cadd key=\"redisConn\" value=\"\"/\u003e\n    \u003cadd key=\"redisPrefix\" value=\"SW:\"/\u003e\n    \u003cadd key=\"redisExpiryDate\" value=\"20\"/\u003e\n    \u003cadd key=\"redisSwitch\" value=\"false\"/\u003e\n    --\u003e\n  \u003c/appSettings\u003e\n\u003c/configuration\u003e\n\n```\n\n一般情况下只用修改\n\n```xml\n \u003c!--注册到的目标--\u003e\n  \u003cTs Ip=\"127.0.0.1\" Port=\"7010\"/\u003e\n\n \u003c!-- 数据库连接字符串 Mysql--\u003e\n    \u003cadd key=\"ConnStr\" value=\"server=127.0.0.1;database=viper;uid=bif;pwd=123456;SslMode=None;\"/\u003e\n```\n\n\n\n    ViperService 可以和 ViperCenter 不在同一台电脑，也可以运行多个server 也可以负载均衡，高级用法随后介绍\n    进入项目文件夹 Viper\\ViperService\\bin\\Debug\\net6.0 \n    运行命令 dotnet ViperService.dll\n    看到下图 说明 ViperService 成功运行 并且已经注册到 注册中心（ViperCenter）运行成功\n![第二步](https://z3.ax1x.com/2021/04/01/cE5PZq.png)\n\n启动 Viper.GetWay\n\n    第三步：调用链追踪\n    \tViper\\Viper\\appsettings.json\n\n```json\n\n{\n  \"Target\": {\n    \"AppName\": \"ApiGateway\",\n    \"IpAddress\": \"127.0.0.1\",\n    \"Port\": 7010,\n    \"TraceOnOff\": true\n  },\n  \"Limit\": {\n    \"Enable\": true,\n    \"TagLimits\": [\n      {\n        \"channel\": \"*\",\n        \"router\": \"*\",\n        \"timeSpan\": \"1\",\n        \"rps\": 100,\n        \"limitSize\": 100\n      }\n    ],\n    \"DefaultIpLimit\": {\n      \"timeSpan\": 1,\n      \"rps\": 200,\n      \"limitSize\": 200\n    },\n    \"IpLimits\": [\n      {\n        \"ipMatch\": \"0.0.0.1\",\n        \"timeSpan\": 1,\n        \"rps\": 100,\n        \"limitSize\": 100\n      },\n      {\n        \"ipMatch\": \"192.168.0.10 - 192.168.10.20\",\n        \"timeSpan\": 1,\n        \"rps\": 100,\n        \"limitSize\": 100\n      }\n    ],\n    \"White\": [\n      \"0.0.0.1\",\n      \"192.168.1.2\",\n      \"192.168.2.18\"\n    ],\n    \"Black\": [\n      \"0.0.0.2\",\n      \"192.168.3.18\"\n    ]\n  }\n}\n\n\n```\n\n\n\n![第三步](https://z3.ax1x.com/2021/04/01/cE5gyj.png)\n\n```\n调用链详情\n```\n\n![第三步](https://z3.ax1x.com/2021/04/01/cE5fwq.png)\n\n 第四步：集群路由信息\n\n![第三步](https://z3.ax1x.com/2021/04/01/cE5Hl4.png)\n\n   ![第三步](https://z3.ax1x.com/2021/04/01/cEIiXd.png)\n\n```\n调试邮件接口成功\n```\n\n![第三步](https://s1.ax1x.com/2020/07/30/anJipn.png)\n\n\n\n第五步：服务性能监控\n       \n![第四步](https://z3.ax1x.com/2021/06/29/Rade3R.png)\n\n\n# 👒Anno EventBus\n    Eventbus Support  InMemory and Rabbitmq\n## ⛳1、Server配置\n\n```c#\n\t//指定EventHandler的 所在程序集\n\tvar funcs = Anno.Const.Assemblys.Dic.Values.ToList();\n                #region RabbitMQEventBus\n                //消费失败通知\n                EventBusSetting.Default.RabbitConfiguration = new RabbitConfiguration()\n                {\n                    HostName = \"192.168.100.173\",\n                    VirtualHost = \"dev\",\n                    UserName = \"dev\",\n                    Password = \"dev\",\n                    Port = 5672\n                };\n                RabbitMQEventBus.Instance.ErrorNotice += (string exchange, string routingKey, Exception exception, string body) =\u003e\n                        {\n                            Log.Fatal(new { exchange, routingKey, exception, body }, typeof(RabbitMQEventBus));\n                        };\n                RabbitMQEventBus.Instance.SubscribeAll(funcs);\n\n                #endregion\n                #region InMemory EventBus\n                EventBus.Instance.ErrorNotice += (string exchange, string routingKey, Exception exception, string body) =\u003e\n                {\n                    Log.Fatal(new { exchange, routingKey, exception, body }, typeof(EventBus));\n                };\n                EventBus.Instance.SubscribeAll(funcs);\n\n```\n\n## ⚾2、EventData配置\n\n```c#\n\n\tusing Anno.EventBus;\n\t\n\tnamespace Events\n\t{\n\t    public class FirstMessageEvent:EventData\n\t    {\n\t        public string Message { get; set; }\n\t    }\n\t}\n\n```\n\n\n## 🎳3、EventHandler配置\n\n```c#\n\t\n\tnamespace Anno.Plugs.SamsundotService.EventHandler\n\t{\n\t    using Anno.EventBus;\n\t    using Events;\n\t\n\t    class FirstMessageEventHandler : IEventHandler\u003cFirstMessageEvent\u003e\n\t    {\n\t        public void Handler(FirstMessageEvent entity)\n\t        {\n\t            Log.Log.Info(new { Plugs= \"Samsundot\",Entity=entity },typeof(FirstMessageEventHandler));\n\t        }\n\t    }\n\t}\n\n```\n\n ```c#\n\t\n\tnamespace Anno.Plugs.YYTestService.EventHandler\n\t{\n\t    using Anno.EventBus;\n\t    using Events;\n\t\n\t    class FirstMessageEventHandler : IEventHandler\u003cFirstMessageEvent\u003e\n\t    {\n\t        public void Handler(FirstMessageEvent entity)\n\t        {\n\t            Log.Log.Info(new { Plugs = \"YYTest\", Entity = entity },               typeof(FirstMessageEventHandler));\n\t        }\n\t    }\n\t    /// \u003csummary\u003e\n\t    /// 异常消费演示，测试 消费失败通知\n\t    /// \u003c/summary\u003e\n\t    class FirstMessageExceptionEventHandler : IEventHandler\u003cFirstMessageEvent\u003e\n\t    {\n\t        public void Handler(FirstMessageEvent entity)\n\t        {\n\t            Log.Log.Info(new { Plugs = \"YYTest\",Handle= \"FirstMessageExceptionEventHandler\", Entity = entity }, typeof(FirstMessageEventHandler));\n\t            throw new Exception(\"异常消费演示，测试 消费失败通知 From FirstMessageExceptionEventHandler!\");\n\t        }\n\t    }\n\t}\n\n ```\n\n## 🐎4、中间件\n### 💥4.1 缓存中间件\n#### 💪Install-Package Anno.EngineData.Cache\n\n```shell\n\nInstall-Package Anno.EngineData.Cache\n\n```\n\n ```c#\n\t\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing Anno.EngineData;\nusing Anno.EngineData.Cache;\n\n\nnamespace Anno.Plugs.CacheRateLimitService\n{\n    public class CacheModule : BaseModule\n    {\n        /*\n        参数1：缓存长度\n        参数2：缓存存活时间\n        参数3：缓存存活时间是否滑动\n        */\n        [CacheLRU(5,6,true)]\n        public ActionResult Cache(string msg)\n        {\n            Console.WriteLine(msg);\n            return new ActionResult(true, null,null,msg);\n        }\n    }\n}\n\n ```\n\n ### 🔰4.2 限流中间件\n#### 💄Install-Package Anno.EngineData.RateLimit\n\n```shell\n\nInstall-Package Anno.EngineData.RateLimit\n\n```\n\n ```c#\n\t\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing Anno.EngineData;\nusing Anno.RateLimit;\n\nnamespace Anno.Plugs.CacheRateLimitService\n{\n    public class LimitModule : BaseModule\n    {\n        /*\n        参数1：限流算法是令牌桶还是漏桶\n        参数2：限流时间片段单位秒\n        参数3：单位时间可以通过的请求个数\n        参数4：桶容量\n        */\n        [EngineData.Limit.RateLimit(LimitingType.TokenBucket,1,5,5)]\n        public ActionResult Limit(string msg)\n        {\n            Console.WriteLine(msg);\n            return new ActionResult(true, null, null, msg);\n        }\n    }\n}\n\n ```\n\n\n\n\n#dotnet\ndotnet publish \"E:\\gitProject\\Anno\\DCS\\AppCenter\\AppCenter.csproj\" -c Release -r linux-x64 -o \"E:\\gitProject\\Anno\\DCS\\AppCenter\\bin\"\n\n#配置文件说明\n```json\n{\n  \"Target\": {\n    \"AppName\": \"traceWeb\",--服务名称\n    \"IpAddress\": \"127.0.0.1\",--注册中心地址\n    \"Port\": 6660,--注册中心端口\n    \"TraceOnOff\": true--启用调用链追踪\n  },\n  \"Limit\": {--限流\n    \"Enable\": true,--是否启用限流\n    \"TagLimits\": [--标签限流\n      {\n        \"channel\": \"*\",--管道\n        \"router\": \"*\",--路由\n        \"timeSpan\": \"10\",--时间片单位秒\n        \"rps\": 1,--时间片内的 有效请求个数\n        \"limitSize\": 2--漏桶容量大小 做缓冲用\n      }\n    ],\n    \"DefaultIpLimit\": {--默认IP限流策略\n      \"timeSpan\": 1,\n      \"rps\": 20,\n      \"limitSize\": 200\n    },\n\t\"IpLimits\": [--IP限流策略（ipMatch参考IPAddressRange）\n      {\n        \"ipMatch\": \"0.0.0.1\",\n        \"timeSpan\": 1,\n        \"rps\": 100,\n        \"limitSize\": 100\n      },\n      {\n        \"ipMatch\": \"192.168.0.10 - 192.168.10.20\",\n        \"timeSpan\": 1,\n        \"rps\": 100,\n        \"limitSize\": 100\n      }\n    ],\n    \"White\": [--白名单\n      \"0.0.0.1\",\n      \"192.168.1.2\",\n      \"192.168.2.18\"\n    ],\n    \"Black\": [--黑名单\n      \"0.0.0.2\",\n      \"192.168.3.18\"\n    ]\n  }\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduyanming%2Fviper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fduyanming%2Fviper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduyanming%2Fviper/lists"}