zooland 我叫它动物园地,一个构思很长时间的一个项目。起初只是觉得各种通信框架都封装的很好了,但是就是差些兼容,防错,高可用。同时在使用上,不希望有多余的代码,像普通接口一样使用就可以了。

基于这些想法,看了很多资料,有了很多启发;也开发出这样一个版本,而且也在实际项目中应用起来了,算是小有成就吧。但同时深知一个人的力量有限,希望得到整个社区帮助。帮助我完善它,让它成为.net 平台下一个不错的选择。

首先,介绍一下这个项目。

项目中没有实现自己的通信层代码,因为大厂为我们提供了 比如 thrift、grpc、HTTP、wcf、akka.net、netty.net 等等。

其次既然我都支持了这么多种通信框架了,那么他们在同一个项目中进行混用也是可以的。比如你的.net 项目内使用wcf 或 netty通信,这个时候elk或者搜索引擎为你提供了thrift的接口,那么用这个框架会是不错的选择。

项目中 主要的精力放在了LoadBalace、调用错误隔离、重试、缓存,多种形式的Cluster、以及如何以最简单的方式让队员通过直链的方式进行开发。

服务注册和发现,现在还没有很好的实现想法,希望社区能帮忙,当然有接口性能监控的能手,和调用链或熟悉dapper的能加入我,那么我会更高兴。

ioc上无赖选择了Spring.net,希望spring.net 早点出.net core版本的,这样我会很省心的去开发.net core 版的zooland;

autofac 我正在尝试,希望能作为spring.net 的替代版本,可能是因为习惯了spring.net 感觉autofac我增加我的配置文档的数量,这是我不喜欢的

ioc 我也不喜欢对框架内部侵入太多的,它会让我觉得我的架构很臃肿,让我觉得ioc 不过是虚拟工厂来生产真正的实例,而且还要让我到处引用虚拟工厂的类库,想想都觉得烦。

计划还是有的:

准备在框架层加入过滤器,这样CAS 做分布式事务的开源框架也能整合进来,缓存也能独立成一个Filter 的实现

比较麻烦的是调用链,需要埋点,由于支持了多种通信框架,而基于dapper论文的追踪访问链条的方式,可能导致有些通信框架不支持,比较麻烦,一直在想,tcp/ip协议是不是也有想http一样的,可以在访问header里面添加调用链的内容。也希望社区有好的办法。当然能推动大厂们提供的通信框架的改进,那就更好了。

有代码有真相,下面是用于调用的代码,对使用来说绝对easy

static void Main(string[] args)
{
var context = ContextRegistry.GetContext();
var helloServiceThrift = context.GetObject<RpcContractThrift.IHelloService>();
var helloServiceGrpc = context.GetObject<RpcContractGrpc.IHelloService>();
var helloServiceWcf = context.GetObject<RpcContractWcf.IHelloService>();
var helloServiceHttp = context.GetObject<RpcContractHttp.IHelloService>();
var helloServiceAkka = context.GetObject<RpcContractAkka.IHelloService>();
var helloServiceRemoting = context.GetObject<RpcContractRemoting.IHelloService>();
while (true)
{
Console.WriteLine("请选择:wcf | grpc | thrift | http | akka | remoting");
var mode = Console.ReadLine().ToLower();
switch (mode)
{
case "wcf":
CallWhile((helloword) => { WcfHello(helloServiceWcf, helloword); });
break;
case "grpc":
CallWhile((helloword) => { GrpcHello(helloServiceGrpc, helloword); });
break;
case "thrift":
CallWhile((helloword) => { ThriftHello(helloServiceThrift, helloword); });
break;
case "http":
CallWhile((helloword) => { HttpHello(helloServiceHttp, helloword); });
break;
case "akka":
CallWhile((helloword) => { AkkaHello(helloServiceAkka, helloword); });
break;
case "remoting":
CallWhile((helloword) => { RemotingHello(helloServiceRemoting, helloword); });
break;
case "all":
for (int i = ; i < ; i++)
{
Task.Run(() =>
{
try
{
WcfHello(helloServiceWcf);
}
catch (Exception ex)
{
throw ex;
}
});
Task.Run(() =>
{
try
{
GrpcHello(helloServiceGrpc);
}
catch (Exception ex)
{
throw ex;
} });
Task.Run(() =>
{
try
{
ThriftHello(helloServiceThrift);
}
catch (Exception ex)
{
throw ex;
} });
Task.Run(() =>
{
try
{
HttpHello(helloServiceHttp);
}
catch (Exception ex)
{ throw ex;
} });
Task.Run(() =>
{ try
{
AkkaHello(helloServiceAkka);
}
catch (Exception ex)
{ throw ex;
}
});
}
break;
} if (mode == "end")
{
break;
}
} }
private static void ThriftHello(RpcContractThrift.IHelloService helloServiceThrift, string helloword = "world")
{
var callNameVoid = helloServiceThrift.CallNameVoid();
Console.WriteLine(callNameVoid);
helloServiceThrift.CallName(helloword);
Console.WriteLine("CallName called");
helloServiceThrift.CallVoid();
Console.WriteLine("CallVoid called");
var hello = helloServiceThrift.Hello(helloword);
Console.WriteLine(hello);
var helloResult = helloServiceThrift.SayHello(helloword + "perfect world");
Console.WriteLine($"{helloResult.Name},{helloResult.Gender},{helloResult.Head}");
helloResult.Name = helloword + "show perfect world";
var showResult = helloServiceThrift.ShowHello(helloResult);
Console.WriteLine(showResult);
}
private static void GrpcHello(RpcContractGrpc.IHelloService helloServiceGrpc, string helloword = "world")
{
var callNameVoid = helloServiceGrpc.CallNameVoid(new RpcContractGrpc.Void());
Console.WriteLine(callNameVoid);
helloServiceGrpc.CallName(new RpcContractGrpc.NameResult { Name = helloword });
Console.WriteLine("CallName called");
helloServiceGrpc.CallVoid(new RpcContractGrpc.Void());
Console.WriteLine("CallVoid called");
var hello = helloServiceGrpc.Hello(new RpcContractGrpc.NameResult { Name = helloword });
Console.WriteLine(hello.Name);
var helloResult = helloServiceGrpc.SayHello(new RpcContractGrpc.NameResult { Name = $"{helloword} perfect world" });
Console.WriteLine($"{helloResult.Name},{helloResult.Gender},{helloResult.Head}");
helloResult.Name = helloword + "show perfect world";
var showResult = helloServiceGrpc.ShowHello(helloResult);
Console.WriteLine(showResult.Name);
}
private static void WcfHello(RpcContractWcf.IHelloService helloServiceWcf, string helloword = "world")
{
var callNameVoid = helloServiceWcf.CallNameVoid();
Console.WriteLine(callNameVoid);
helloServiceWcf.CallName(helloword);
Console.WriteLine("CallName called");
helloServiceWcf.CallVoid();
Console.WriteLine("CallVoid called");
var helloWcf = helloServiceWcf.Hello(helloword);
Console.WriteLine(helloWcf);
var helloResultWcf = helloServiceWcf.SayHello($"{helloword} perfect world");
Console.WriteLine($"{helloResultWcf.Name},{helloResultWcf.Gender},{helloResultWcf.Head}");
helloResultWcf.Name = helloword + "show perfect world";
var showResultWcf = helloServiceWcf.ShowHello(helloResultWcf);
Console.WriteLine(showResultWcf);
}
private static void HttpHello(RpcContractHttp.IHelloService helloServiceHttp, string helloword = "world")
{
var callNameVoid = helloServiceHttp.CallNameVoid();
Console.WriteLine(callNameVoid);
helloServiceHttp.CallName(helloword);
Console.WriteLine("CallName called");
helloServiceHttp.CallVoid();
Console.WriteLine("CallVoid called");
var helloWcf = helloServiceHttp.Hello(helloword);
Console.WriteLine(helloWcf);
var helloResultWcf = helloServiceHttp.SayHello($"{helloword} perfect world");
Console.WriteLine($"{helloResultWcf.Name},{helloResultWcf.Gender},{helloResultWcf.Head}");
helloResultWcf.Name = helloword + "show perfect world";
var showResultWcf = helloServiceHttp.ShowHello(helloResultWcf);
Console.WriteLine(showResultWcf);
}
private static void AkkaHello(RpcContractAkka.IHelloService akkaServiceHttp,string helloword = "world")
{
var callNameVoid = akkaServiceHttp.CallNameVoid();
Console.WriteLine(callNameVoid);
akkaServiceHttp.CallName(new RpcContractAkka.NameResult { Name = helloword });
Console.WriteLine("CallName called");
akkaServiceHttp.CallVoid();
Console.WriteLine("CallVoid called");
var hello = akkaServiceHttp.Hello(new RpcContractAkka.NameResult { Name = helloword });
Console.WriteLine(hello.Name);
var helloResult = akkaServiceHttp.SayHello(new RpcContractAkka.NameResult { Name = $"{helloword} perfect world" });
Console.WriteLine($"{helloResult.Name},{helloResult.Gender},{helloResult.Head}");
helloResult.Name = helloword + "show perfect world";
var showResultWcf = akkaServiceHttp.ShowHello(helloResult);
Console.WriteLine(showResultWcf.Name); }
private static void RemotingHello(RpcContractRemoting.IHelloService remotingServiceHttp, string helloword = "world")
{
var callNameVoid = remotingServiceHttp.CallNameVoid();
Console.WriteLine(callNameVoid);
remotingServiceHttp.CallName(helloword);
Console.WriteLine("CallName called");
remotingServiceHttp.CallVoid();
Console.WriteLine("CallVoid called");
var hello = remotingServiceHttp.Hello(helloword);
Console.WriteLine(hello);
var helloResult = remotingServiceHttp.SayHello($"{helloword} perfect world");
Console.WriteLine($"{helloResult.Name},{helloResult.Gender},{helloResult.Head}");
helloResult.Name = helloword + "show perfect world";
var showResult = remotingServiceHttp.ShowHello(helloResult);
Console.WriteLine(showResult); } private static void CallWhile(Action<string> map)
{
var helloword = "world";
while (true)
{
try
{
map(helloword);
var mode = Console.ReadLine().ToLower();
helloword = mode;
if (helloword == "end")
{
break;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
}
}

目前只支持了spring.net ,有autofac的高手,欢迎加入

希望为一部分使用.net framework 的WCF做通信层框架,转微服务架构,作为一个不错的并且平滑的升级选择。

新技术不要怕不稳定,源码都有了,而且框架结构这么简单,大胆用,有问题了,可以联系技术支持啥。

奉上项目开源地址:

https://github.com/wutao0315/zooland

现在还没有搞明白怎么编译好一个版本怎么弄到nuget上,而且版本管理经验也欠缺,也需要依赖社区了。

联系作者

mail:wutao0315@qq.com

qq:1164636434

想加入我的,邮件给我吧,欢迎每一个热爱编程的同学。

zooland 新开源的RPC项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。的更多相关文章

  1. Thrift 个人实战--RPC服务的发布订阅实现(基于Zookeeper服务)

    前言: Thrift作为Facebook开源的RPC框架, 通过IDL中间语言, 并借助代码生成引擎生成各种主流语言的rpc框架服务端/客户端代码. 不过Thrift的实现, 简单使用离实际生产环境还 ...

  2. 【OF框架】使用OF.WinService项目,添加定时服务,进行创建启动停止删除服务操作

    准备 使用框架搭建完成项目,包含OF.WinService项目. 了解Window Service 和定时服务相关知识. 一.添加一个定时服务 第一步:了解项目结构 第二步:创建一个新的Job 第三步 ...

  3. 通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数--菜单功能'menufile

      通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁 ...

  4. 通过游戏学python 3.6 第一季 第八章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数

    通过游戏学python 3.6 第一季 第八章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账 ...

  5. .NET Core/.NET5/.NET6 开源项目汇总6:框架与架构设计(DDD、云原生/微服务/容器/DevOps/CICD等)项目

    系列目录     [已更新最新开发文章,点击查看详细] 开源项目是众多组织与个人分享的组件或项目,作者付出的心血我们是无法体会的,所以首先大家要心存感激.尊重.请严格遵守每个项目的开源协议后再使用.尊 ...

  6. JAVAEE——BOS物流项目07:WebService入门、apache CXF入门、基于CXF发布CRM服务

    1 学习计划 1.WebService入门 n 什么是WebService n 调用网络上的WebService服务 n SOAP和WSDL概念 n 基于JDK1.7发布一个简单的WebService ...

  7. Captcha服务(后续2)— 改造Captcha服务之Asp.Net Core项目中如何集成TypeScript

    环境准备 .Net Core 版本:下载安装.Net Core SDK,安装完成之后查看sdk版本 ,查看命令dotnet --version,我的版本是2.2.101 IDE: Visual Stu ...

  8. 002-Spring4 快速入门-项目搭建、基于注解的开发bean,Bean创建和装配、基于注解的开发bean,Bean初始化销毁、Bean装配,注解、Bean依赖注入

    一.项目搭建 1.项目创建 eclipse→project explorer→new→Project→Maven Project 默认配置即可创建项目 2.spring配置 <dependenc ...

  9. 「微前端实践」使用Vue+qiankun微前端方案重构老项目的本地验证

    10月份换了新的工作,参与完一个月的需求迭代后,接到了项目重构的任务.简单来说,需要在短时间内提出方案设想,同时进行本地验证,最终需要拿出一套技术替换方案来.于是,埋头苦干了一个月,总算干了点成绩出来 ...

随机推荐

  1. Microsoft SQL 关系数据库的使用指南

    Microsoft SQL 关系数据库的使用指南 https://docs.microsoft.com/zh-cn/sql/relational-databases/database-features

  2. ngrep命令用法

    ngrep 是grep(在文本中搜索字符串的工具)的网络版,他力求更多的grep特征,用于搜寻指定的数据包.正由于安装ngrep需用到libpcap库, 所以支持大量的操作系统和网络协议.能识别TCP ...

  3. 【转】为什么Github没有记录你的Contributions

    【转】为什么Github没有记录你的Contributions 字数985 阅读0 评论0 喜欢0 记录下为什么github 提交的时候,没有记录到 github 的那个日历上。 Paste_Imag ...

  4. Linux vsftpd 配置文件详解

    .默认配置: >允许匿名用户和本地用户登陆. anonymous_enable=YES local_enable=YES >匿名用户使用的登陆名为ftp或anonymous,口令为空:匿名 ...

  5. 🈲Eclipse通过jdbc连接数据库制作简单登陆界面【新手必看】

    一.前言: 做网站开发,要求有多种搭配方式,前台技术可以使用PHP.ASP.JSP.ASP.NET.CGI等任何一种: 需要用到的基础语言用的最多的就是HTML/CSS.JS.JAVA.XML这些了, ...

  6. MP实战系列(十八)之XML文件热加载

    你还在为每次修改XML文件中的SQL重新启动服务器或者是等待几分钟而烦恼吗? 配置了热加载即可解决你的这个问题. 这就是XML文件热加载的目的,减少等待时间成本,提高开发效率. SSM框架配置(Spr ...

  7. tomcat:8080/返回404;/etc/hosts(identifier-Namespace-scope)

    我以为 就oracle 的 oracle db ,weblogic喜欢和 hostname 死磕: 没想到开源的tomcat也是如出一辙,名不正则言不顺,为什么,“名”的力量这么大呢?命名空间. 有个 ...

  8. Android String.xml中的符号总结

    <b></b>加粗字体 <i></i> 斜体字体 <u></u> 给字体加下划线 \n 换行 \u0020表示空格 \u2026 ...

  9. A - Zebras

    Oleg writes down the history of the days he lived. For each day he decides if it was good or bad. Ol ...

  10. POJ 1904 King's Quest(SCC的巧妙应用,思维题!!!,经典题)

    King's Quest Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 10305   Accepted: 3798 Ca ...