zooland 新开源的RPC项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。
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项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。的更多相关文章
- Thrift 个人实战--RPC服务的发布订阅实现(基于Zookeeper服务)
前言: Thrift作为Facebook开源的RPC框架, 通过IDL中间语言, 并借助代码生成引擎生成各种主流语言的rpc框架服务端/客户端代码. 不过Thrift的实现, 简单使用离实际生产环境还 ...
- 【OF框架】使用OF.WinService项目,添加定时服务,进行创建启动停止删除服务操作
准备 使用框架搭建完成项目,包含OF.WinService项目. 了解Window Service 和定时服务相关知识. 一.添加一个定时服务 第一步:了解项目结构 第二步:创建一个新的Job 第三步 ...
- 通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数--菜单功能'menufile
通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁 ...
- 通过游戏学python 3.6 第一季 第八章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数
通过游戏学python 3.6 第一季 第八章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账 ...
- .NET Core/.NET5/.NET6 开源项目汇总6:框架与架构设计(DDD、云原生/微服务/容器/DevOps/CICD等)项目
系列目录 [已更新最新开发文章,点击查看详细] 开源项目是众多组织与个人分享的组件或项目,作者付出的心血我们是无法体会的,所以首先大家要心存感激.尊重.请严格遵守每个项目的开源协议后再使用.尊 ...
- JAVAEE——BOS物流项目07:WebService入门、apache CXF入门、基于CXF发布CRM服务
1 学习计划 1.WebService入门 n 什么是WebService n 调用网络上的WebService服务 n SOAP和WSDL概念 n 基于JDK1.7发布一个简单的WebService ...
- Captcha服务(后续2)— 改造Captcha服务之Asp.Net Core项目中如何集成TypeScript
环境准备 .Net Core 版本:下载安装.Net Core SDK,安装完成之后查看sdk版本 ,查看命令dotnet --version,我的版本是2.2.101 IDE: Visual Stu ...
- 002-Spring4 快速入门-项目搭建、基于注解的开发bean,Bean创建和装配、基于注解的开发bean,Bean初始化销毁、Bean装配,注解、Bean依赖注入
一.项目搭建 1.项目创建 eclipse→project explorer→new→Project→Maven Project 默认配置即可创建项目 2.spring配置 <dependenc ...
- 「微前端实践」使用Vue+qiankun微前端方案重构老项目的本地验证
10月份换了新的工作,参与完一个月的需求迭代后,接到了项目重构的任务.简单来说,需要在短时间内提出方案设想,同时进行本地验证,最终需要拿出一套技术替换方案来.于是,埋头苦干了一个月,总算干了点成绩出来 ...
随机推荐
- Vue组件学习
根据Vue官方文档学习的笔记 在学习vue时,组件学习比较吃力,尤其是组件间的通信,所以总结一下,官方文档的组件部分. 注册组件 全局组件 语法如下,组件模板需要使用一个根标签包裹起来.data必须是 ...
- python编写脚本
#!/usr/bin/env python #-*- coding:utf-8 -*- import sys import os from subprocess import Popen,PIPE c ...
- Oracle EBS OPM 发放生产批
--发放生产批 --created by jenrry DECLARE x_return_status VARCHAR2 (1); l_exception_material_tbl gme_commo ...
- 【JAVA】什么是冒泡排序?——面试加分题
冒泡排序是一种计算机科学领域的较简单的排序算法,有心人将代码不断优化改良,本人特摘抄部分代码进行学习. 文章来自开源中国,转载自:程序员小灰.原文:漫画:什么是冒泡排序? 冒泡排序第一版 public ...
- 转:C# 读取EXCEL文件的三种经典方法
1.方法一:采用OleDB读取EXCEL文件: 把EXCEL文件当做一个数据源来进行数据的读取操作,实例如下: public DataSet ExcelToDS(string Path) { stri ...
- Linux 配置 hosts
1. hosts 是什么 维基百科对 hosts 的介绍如下: hosts文件(域名解析文件)是一个用于储存计算机网络中各节点信息的计算机文件. 这个文件负责将主机名称映射到相应的IP地址. host ...
- redis 配置文件示例
# redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位,# 通常的格式就是 1k 5gb 4m 等酱紫:## 1k => 1000 bytes# 1kb =& ...
- mnist手写数字检测
# -*- coding: utf-8 -*- """ Created on Tue Apr 23 06:16:04 2019 @author: 92958 " ...
- 极限编程核心价值:沟通(Communication)
原文:https://deviq.com/communication 极限编程核心价值:简单(Simplicity) 极限编程核心价值:沟通(Communication) 极限编程核心价值:反馈(Fe ...
- python第四十课——构造函数
1.动态给对象添加属性: 在对象创建完毕后,单独为其添加需要的属性:可以理解为:私人定制 [注意]: 添加的属性只有此对象能够使用,别的对象如果用了,直接报错; 2.构造函数/构造方法/构造器: 格式 ...