grain

组件式 RPC 框架
授权协议 MIT
开发语言 Java
所属分类 Web应用开发、 RPC/XMLRPC项目
软件类型 开源软件
地区 国产
投 递 者 羊舌和安
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

grain 是一个极简的、组件式的 RPC 框架,灵活且适合渐进学习,可与任何框架整合。同时包含(系统通用多线程模型与消息通讯、多对多关系的分布式锁、基于 Servlet 的 HTTP 框架、基于系统通用多线程模型的 Websocket 框架、支持行级锁的多线程锁)等组件,按需选择组件,不绑架开发者。

grain 架构图及其依赖关系(深颜色的是核心组件强烈推荐)

核心组件介绍

1、grain-thread(系统通用多线程模型)

介绍:完美抽象了客观事物,包含:1、活跃于线程之间的活物,进入动作离开动作轮训动作(例如:人可以在线程间切换),2、处理完即销毁的非活物,处理动作(例如:各类消息包处理后即可销毁)。3、优秀的多线程轮训机制,队列机制(生产者与消费者),服务器掌握绝对的控制权。

使用场景:grain-rpc、grain-distributedlock、grain-threadwebsocket,都是基于此系统通用多线程模型。任何需要多线程的业务都可以使用:例如MMORPG即时通讯等。

示例代码

1、启动示例,创建10条线程,每条线程3个优先级,每次轮训间隔100毫秒,通过ILog实现类的对象打印日志,锁定线程0条。

AsyncThreadManager.init(100, 10, 3, 0, ILog实现类的对象);
AsyncThreadManager.start();

2、将活物加入线程1、优先级1的进入队列(之后会触发进入动作、之后不断触发轮训动作

AsyncThreadManager.addCycle(ICycle实现类的对象, 1, 1);

3、将活物加入线程1、优先级1的离开队列(之后会触发离开动作

AsyncThreadManager.removeCycle(ICycle实现类的对象, 1, 1);

4、将非活物加入线程1、优先级1的处理队列(之后会触发处理动作,处理完即销毁)

AsyncThreadManager.addHandle(IHandle实现类的对象, 1, 1);

2、grain-threadmsg(系统通用多线程模型与消息通讯)。

介绍:支持与系统通用多线程模型系统通用多线程模型之间进行消息通讯。可以进行消息配置消息注册消息分发消息回调

使用场景:需要系统通用多线程模型的场景,一般都需要进行消息通讯。可以一直跟grain-thread绑定使用。

示例代码

1、初始化,通过ILog实现类的对象打印日志

MsgManager.init(true, Ilog日志);

2、设置所有关注createuser消息的处理函数在线程1、优先级1进行处理(如果不设置,则随机线程随机优先级处理)

ThreadMsgManager.addMapping("createuser", new int[] { 1, 1 });

3、注册关注某消息及对应处理函数(第2步消息设置归属哪个线程,对应处理函数就在哪个线程回调)

MsgManager.addMsgListener(IMsgListener实现类对象);

4、派发createuser消息,携带数据111与额外数据222(第3步所有关注此消息的处理函数,进行回调)

ThreadMsgManager.dispatchThreadMsg("createuser", 111, 222);

3、grain-rpc(支持多对多关系的RPC框架,含:RPC客户端与RPC服务器)。

介绍:基于Mina网络层及Protobuf序列化开发的RPC通讯框架,相比7层HTTP通讯,4层TCP通讯消息包更小、传输速度更快、队列化处理消息包、消息包与线程可一一映射配置化,支持多对多关系、断线重连等。

 

 

使用场景:生产环境内部网络的服务器之间进行消息通讯。

示例代码

1、RPC客户端(启动类test.RPCClientTest.java,直接启动即可连接下面的RPC服务器)

>>>>>>RPC客户端Demo

2、RPC服务器(启动类test.RPCServerTest.java,直接启动即可接受上面的RPC客户端连接请求)

>>>>>>RPC服务器Demo

3、RPC方式获取数据示例

//创建消息包
RPCTestC.Builder builder = RPCTestC.newBuilder();
builder.setName("RPC服务器你好啊");
TcpPacket pt = new TcpPacket("TEST_RPC_C", builder.build());
//RPC远程调用,返回结果
TcpPacket ptReturn = WaitLockManager.lock(session, pt);

4、grain-distributedlock(支持多对多关系的分布式锁,含:分布式锁客户端与分布式锁服务器)。

介绍:去中心化,支持行级锁(锁某类型的单键值)。不同类型互不影响,相同类型不同键值互不影响。仅当类型与键值都相等时会进行分布式阻塞。

注意:如果一台服务器已经承担了分布式锁服务器的角色,就不要用该服务器承担别的角色,因为这台服务器的大多数线程都会不时进行线程阻塞,等待锁客户端释放锁。

 

 

使用场景:在无中心化的服务器集群中,有很大的意义。不用依赖数据库Mysql,即可保障服务器集群业务的原子性,又大幅度提高服务器集群性能,减少错误的数据库提交。

示例代码

1、分布式锁客户端(启动类test.DistributedlockClientTest.java,直接启动即可连接下面的分布式锁服务器)

>>>>>>分布式锁客户端Demo

2、分布式锁服务器(启动类test.DistributedlockServerTest.java,直接启动即可接受上面的分布式锁客户端连接请求)

>>>>>>分布式锁服务器Demo

3、分布式客户端获取锁,释放锁示例

// 获取类型为user,键值为111的锁
int lockId = DistributedLockClient.getLock("111", "user");
if (lockId == 0) {
	return;
}
/***********执行分布式锁业务逻辑开始*********/
/***********执行分布式锁业务逻辑结束*********/
// 释放类型为user,键值为111的锁
DistributedLockClient.unLock("111", "user", lockId);

5、grain-threadwebsocket(基于系统通用多线程模型的Websocket框架)。

介绍:websocket消息不在tomcat默认线程处理,分发至系统通用多线程模型进行队列化处理。更加可定制化,支持websocket消息与线程ID一一映射,服务器绝对的处理控制权。

使用场景:在网站需要进行长连接通讯时,可以使用此框架。

示例代码

1、Websocket服务器(直接用tomcat8.5启动即可,直接访问地址http://localhost:8080/grain-threadwebsocket-test/index.html,即可与服务器建立websocket连接)

>>>>>>Websocket服务器Demo

2、处理业务示例

public void onTestC(WsPacket wsPacket) throws IOException, EncodeException {
	//客户端发来的数据
	TestC testc = (TestC) wsPacket.getData();
	//构建返回数据
	TestS.Builder tests = TestS.newBuilder();
	tests.setWsOpCode("tests");
	tests.setMsg("你好客户端,我是服务器");
	WsPacket pt = new WsPacket("tests", tests.build());
	//获取session
	Session session = (Session) wsPacket.session;
	//推送数据
	session.getBasicRemote().sendObject(pt);
}

6、grain-httpserver(基于Servlet的HTTP框架)。

介绍:一个非常轻量级的基于Servlet的HTTP框架,只有1318行代码。小身材,五脏齐全,扩展性强。支持各种请求方式,支持文件与数据包分离,支持扩展请求过滤器,支持扩展请求回复类型。

使用场景:开发HTTP项目,不想使用Spring、struts2,可以选择此框架,真的轻量到不能再轻量了(除非你想直接用Servlet)。

示例代码

1、HTTP服务器(直接用tomcat8.5启动即可,直接访问地址http://localhost:8080/grain-httpserver-test/index.html,发送纯数据请求、发送携带文件的表单请求)

>>>>>>HTTP服务器Demo

2、6种返回类型示例(可扩展)

//返回json
public HttpPacket onTestC(HttpPacket httpPacket) throws HttpException {
	GetTokenS.Builder builder = GetTokenS.newBuilder();
	builder.setHOpCode(httpPacket.gethOpCode());
	builder.setTokenId("111111");
	builder.setTokenExpireTime("222222");
	HttpPacket packet = new HttpPacket(httpPacket.gethOpCode(), builder.build());
	return packet;
}
//返回文件
public ReplyFile onFileC(HttpPacket httpPacket) throws HttpException {
	File file = new File("k_nearest_neighbors.png");
	ReplyFile replyFile = new ReplyFile(file, "你好.png");
	return replyFile;
}
//返回图片
public ReplyImage onImageC(HttpPacket httpPacket) throws HttpException {
	File file = new File("k_nearest_neighbors.png");
	ReplyImage image = new ReplyImage(file);
	return image;
}
//返回字符串
public String onStringC(HttpPacket httpPacket) throws HttpException {
	return "<html><head></head><body><h1>xxxxxxxxxxxx<h1></body></html>";
}
//返回字符串(自定义头消息)
public ReplyString onReplyStringC(HttpPacket httpPacket) throws HttpException {
	String str = "<html><head></head><body><h1>xxxxxxxxxxxx<h1></body></html>";
	ReplyString replyString = new ReplyString(str, "text/html");
	return replyString;
}
//抛自定义错误,进行返回
public void onException(HttpPacket httpPacket) throws HttpException {
	GetTokenS.Builder builder = GetTokenS.newBuilder();
	builder.setHOpCode("0");
	builder.setTokenId("111111");
	builder.setTokenExpireTime("222222");
	throw new HttpException("0", builder.build());
}

7、grain-threadkeylock(支持行级锁的多线程锁)。

介绍:支持锁类型的单键值与双键值的多线程锁,精细化至行级锁,提高并发能力。

注意单服务器架构有价值,集群架构没任何意义,集群架构请使用分布式锁grain-distributedlock。

使用场景:在单服务器架构时,可以在不依赖数据库的情况下,支持到行级锁。

示例代码

1、初始化类型为TEST1TEST2的多线程锁,锁等待最大时间为2分钟,每100毫秒醒来重试,通过ILog实现类的对象打印日志

KeyLockManager.init(new String[] { "TEST1", "TEST2" }, 120000, 100, ILog实现类的对象);

2、锁定TEST1类型,键值为222,同时调用lockFunction函数,传递两个参数str与111。(lockFunction没执行完成,同一时刻如果还是TEST1类型,键值222,会被阻塞)

//锁定函数
public String lockFunction(Object... params) {}
//加锁调用
String str = (String) KeyLockManager.lockMethod("222", "TEST1", 
(params) -> lockFunction(params), new Object[] { "str", 111 });

3、锁定TEST1类型,键值为222与111,同时调用lockFunction函数,传递两个参数str与111。(lockFunction没执行完成,同一时刻如果还是TEST1类型,键值222111,会被阻塞)

//锁定函数
public String lockFunction(Object... params) {}
//加锁调用
String str = (String) KeyLockManager.lockMethod("111", "222", "TEST1", 
(params) -> lockFunction(params), new Object[] { "str", 111 });
  • 设置 在编写实现grain类的代码之前,请新建一个面向.NET Standard(首选)、或.NET Framework 4.6.1或更高版本的类库项目(如果由于依赖性而无法使用.NET Standard)。grain接口和grain类可以在同一个类库项目中定义,也可以在两个不同的项目中定义,以便更好地分离接口和实现。无论哪种情况,项目都需要引用Microsoft.Orleans.Core.Abs

  • grain的标识 在面向对象的环境中,对象的标识很难与对它的引用区分开来。因此,当使用new创建对象时,返回的引用,表示其标识的所有方面——除了那些将对象映射到它所表示的某个外部实体的方面。 在分布式系统中,对象引用不能表示实例标识,因为引用通常仅限于单个地址空间。对于.NET引用来说,情况当然如此。此外,一个grain必须有一个标识,不管它是否被激活,这样我们可以根据需要激活它。因此,grain

  • 扩展组件 <script charset="utf-8" src="https://player.alicdn.com/aliplayer/presentation/js/aliplayercomponents.min.js"> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="v

  • 英文谚语:Take that with a grain of salt take sth. with a grain of salt 这个习语的字面意思是“和一撮盐一起吃下去”,为什么要与盐一起吃呢? 据说这个习语要追溯到罗马时代,罗马将军庞培曾发现一种解毒剂,必须和着一小把盐才服得下去。解毒剂难咽,加了盐也许好咽些,于是这句习语用于描述对一些不靠谱的,值得怀疑的东西,得“和着盐”才能勉强接受。

  • 【英语习语】take sth. with a grain of salt take sth. with a grain of salt 这个习语的字面意思是“和一撮盐一起吃下去”,为什么要与盐一起吃呢?据说这个习语要追溯到罗马时代,罗马将军庞培曾发现一种解毒剂,必须和着一小把盐才服得下去。解毒剂难咽,加了盐也许好咽些,于是这句习语用于描述对一些不靠谱的,值得怀疑的东西,得“和着盐”才能勉强接受。

  • 一、详细释义: n. 谷物,谷类;谷粒 [U,C] 例句: A windmill is used to crush grain into flour. 风车被用来把谷粒轧成面粉。 例句: This year we have a bumper harvest in grain. 今年我们谷物丰收。 粒子;颗粒 [C] 例句: There is a grain of sand in his eye.

  • Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 295    Accepted Submission(s): 66 Problem Description The soil is cracking up b

  • grain持久化的目标 允许不同的grain类型,使用不同类型的存储提供程序(例如,一个使用Azure表,一个使用ADO.NET),或相同类型的存储提供程序但具有不同的配置(例如,两者都使用Azure表,但一个使用存储帐户#1和一个使用存储帐户#2) 允许只更改配置文件而不需要更改代码,就能交换存储提供程序实例(例如,Dev-Test-Prod)。 提供一个框架,以便以后可以由Orleans团队或

  • 1.什么是grains:(静态数据,minion启动时采集)   Grains Static bits of information that a minioncollects about the system when the minion first starts. The grains interface is made available toSalt modules and compon

  • 外部的任务和grain 根据设计,从grain代码中生成的任何子任务(例如,通过使用await或ContinueWith或Task.Factory.StartNew),将在与父任务相同的每个激活的TPL Task Sheduler上调度,因此继承了与grain代码的其余部分相同的单线程执行模型。这是基于grain回合制的并发性背后的要点。 在某些情况下,grain代码可能需要“突破”Orleans

 相关资料
  • EasySwoole 提供开放式的RPC服务。RPC服务分为三级模式:服务=>服务组=>行为。每个服务可以单独现在Openssl加密。 支持超时、成功、失败回调(即最基础的熔断保护和服务降级) 示例代码 服务端 服务A namespace App\RpcController\A; use EasySwoole\Core\Component\Rpc\AbstractInterface\Abstrac

  • 主要内容:1.RPC流水线工程,2.RPC 技术选型,3.如何设计 RPC1.RPC流水线工程 ① Client以本地调用的方式调用服务 ② Client Stub接收到调用后,把服务调用相关信息组装成需要网络传输的消息体,并找到服务地址(host:port),对消息进行编码后交给Connector进行发送 ③ Connector通过网络通道发送消息给Acceptor ④ Acceptor接收到消息后交给Server Stub ⑤ Server Stub对消息进行解码,

  • EasySwoole 同样可以做串行、并行化的SOA服务调用,底层基于SWOOLE_TCP实现,支持自定义消息加解密,为方便多种客户端(不同语言)调用,服务交互采用json格式传递,开发者可以快速以其他语言实现。 场景描述 例如,某个应用中,A为前端承载机器,B与C分别部署着不同的服务。一个用户请求进来,A同时向BC发起请求获取,并汇集两个结果返回给用户。 在EasySwoole中,RPC服务以服

  • 一种流式RPC的实现,RPC基于命令式调用,对于大量数据的传输没有流式调用来得高效! 该SRPC既支持单通道也支持双通道。 单通道:客户端传入参数,服务端返回大量数据。 双通道:客户端传入大量数据,服务端返回大量数据。 该组件受Hadoop IPC启发而创建,参考Hadoop序列化机制,简单高效。 声明:OSCHINA 博客文章版权属于作者,受法律保护。未经作者同意不得转载。 注意:下载时需要SVN客户端!

  • 有两种类型的框,信息框和小框。两个框均用于显示统计摘要。 信息框 <div class="info-box"> <span class="info-box-icon bg-info"><i class="far fa-envelope"></i></span> <div class="info-box-content"> <span class="info-box-text"

  • 随着分布式技术和微服务思想流行,技术公司逐步将服务拆分为独立运行的小模块,提高系统整体的健壮性,加快特性的演进速度。微服务通过定义完善的接口进行交互,解耦系统、敏捷迭代、方便服务治理。RPC是目前微服务最广泛的通信方式。然而,众多团队各自研发具备服务治理功能的RPC通信框架,一方面增加开发成本,消耗人力重复造轮子;另一方面不同序列化协议的RPC服务,无法互相通信,影响可用性。因此,通用的RPC通信