文档章节

构建多平台的Ignite集群:Java+.NET

李玉珏
 李玉珏
发布于 2016/11/24 22:41
字数 1633
阅读 2020
收藏 65

构建多平台的Ignite集群:Java+.NET

Ignite集群可以由它支持的任意平台启动的节点组成,包括Java、.NET和C++。本文会介绍如何通过NuGet和Maven运行一个.NET/Java集群,作为一个示例,本文会创建一个跨平台的点对点聊天系统。 1

前提条件

本文适用于对Java不熟悉的.NET开发人员,反之亦然,因此描述的会比较详细。 本文会使用如下的软件:

  • Visual Studio 2015(包括NuGet; 免费社区版);
  • IntelliJ IDEA (包括Maven; 免费社区版)。

本文的完整源代码位于GitHub上,github.com/ptupitsyn/ignite-multi-platform-demo。 为了简洁起见,下面的代码不是很完整(公共字段,没有命名空间等)。

目标

  • 连接Java和.NET节点;
  • 使用Java和.NET类,通过同样的名字和字段访问Ignite缓存中的共享数据;
  • 运行持续查询,观察来自另一个平台的实时数据更新。

Java工程设置

  • 启动IntelliJ IDEA,然后点击“Create New Project”: 2
  • 选择Maven然后点击“Next”: 3
  • 输入Maven信息,点击“Next”然后“Finish”: 4 5
  • 完成之后,会看到新项目打开的pom.xml文件: 6
  • project片段增加Ignite依赖:
<dependencies>
    <dependency>
        <groupId>org.apache.ignite</groupId>
        <artifactId>ignite-core</artifactId>
        <version>1.7.0</version>
    </dependency>
</dependencies>
  • IDEA可能会询问是否导入项目改变,点击任意的链接: 7
  • 在src\main\java中添加Demo类,代码如下:
import org.apache.ignite.Ignition;

public class Demo {
    public static void main(String[] args) {
        Ignition.start();
    }
}
  • 通过Shift+F10运行,然后在IDEA的控制台上确认节点是否启动:

8

  • 通过Ctrl+F2或者停止按钮终止程序。

.NET工程设置

  • 启动Visual Studio然后点击File -> New -> Project:
  • 选择Visual C# -> Windows -> Console Application:
  • 确保在上边选择了.NET Framework版本4及以上:

9

  • 点击“OK”,然后就会生成一个空的控制台工程;
  • 打开NuGet控制台:Menu -> Tools -> NuGet Package Manager -> Package Manager Console;
  • 输入Install-Package Apache.Ignite:

10

  • 点击回车,然后就会输出Successfully installed 'Apache.Ignite 1.7.0' to IgniteMultiPlatform这样的消息。
  • Program.cs的内容改成如下这样:
using System;
using Apache.Ignite.Core;
class Program
{
    static void Main(string[] args)
    {
        Ignition.Start();
        Console.ReadKey();
    }
}
  • 通过Ctrl-F5启动程序,然后在控制台中确认Ignite节点已经启动:

11

调整Java节点的配置以发现.NET节点

现在,就可以同时在IDEA中启动Java节点,在Visual Studio中启动.NET节点,这时会在他们中的一个发现如下的错误:

IgniteSpiException: Local node's binary configuration is not equal to remote node's binary configuration [locBinaryCfg={globSerializer=null, compactFooter=true, globIdMapper=org.apache.ignite.binary.BinaryBasicIdMapper}, rmtBinaryCfg=null]

这个错误是说,.NET节点在BinaryConfiguration中只支持BinaryBasicIdMapperBinaryBasicNameMapper,需要在Java中显式地进行设置,将Ignition.start();行改成如下的代码:

BinaryConfiguration binCfg = new BinaryConfiguration();

binCfg.setIdMapper(new BinaryBasicIdMapper());
binCfg.setNameMapper(new BinaryBasicNameMapper());

IgniteConfiguration cfg = new IgniteConfiguration().setBinaryConfiguration(binCfg);

Ignition.start(cfg);

这时同时启动Java和.NET节点,验证他们可以发现对方:

[15:04:17] Topology snapshot [ver=2, servers=2, clients=0, CPUs=8, heap=7.1GB]

通过Ignite缓存进行数据交换

现在各个节点已经联通,之后会在每个平台上写一个简单的聊天程序来演示数据的交换。代码非常简单,因为API是相同的,并且语言语法也差不多。 首先,定义名字和成员完全相同的类。

Java Message类

右击src\main\java项目文件夹然后选择New -> Java Class,输入Message名字,代码如下:

public class Message {
    public Message(String author, String text) {
        this.author = author;
        this.text = text;
    }
    final String author;
    final String text;
}

.NET Message类

右击Solution Explorer的项目节点,然后选择Add -> Class…,输入Message名字,代码如下:

class Message
{
    public Message(string author, string text)
    {
        Author = author;
        Text = text;
    }
    public string Author { get; }
    public string Text { get; }
}

Basic映射器是区分大小写的,并且会忽略命名空间(包),因此这两个类是可以互相映射的,可以在一个平台中将Message实例注入缓存,然后在另一个平台中获取。 现在开始写聊天程序本身,逻辑比较简单:用户输入一个聊天信息,然后将其注入缓存,持续查询会收到所有的缓存更新通知并且显示他们。

Java聊天程序

main方法的代码改成如下:

// Retrieve user name
System.out.print("Hi, enter your name: ");
Scanner consoleScanner = new Scanner(System.in);
String name = consoleScanner.nextLine();

// Get or create cache
IgniteCache<Long, Message> cache = ignite.getOrCreateCache("chat");

// Initialize unique ID sequence
IgniteAtomicSequence messageId = ignite.atomicSequence("chatId", 0, true);

// Set up continuous query

ContinuousQuery<Long, Message> qry = new ContinuousQuery<>();

qry.setLocalListener(iterable -> {
    // This will be invoked immediately on each cache update
    for (CacheEntryEvent<? extends Long, ? extends Message> evt : iterable)
        System.out.println(evt.getValue().author + ": " + evt.getValue().text);
});

cache.query(qry);

// Run the chat loop
while (true) {
    System.out.print("> ");
    
    String msgText = consoleScanner.nextLine();
    Long msgId = messageId.incrementAndGet();
    
    cache.put(msgId, new Message(name, msgText));
}

.NET聊天程序

在Ignite.NET中有两处不同(这些特性预计会在下一版本中实现):

  • 需要在BinaryConfiguration中注册一个用于缓存的类型(Java会自动做这个事);
  • API中还不支持Lambda表达式,需要单独地实现ICacheEntryEventListener<K, V>接口。

因此,创建一个单独的类,代码如下:

using System;
using System.Collections.Generic;
using Apache.Ignite.Core.Cache.Event;

class CacheListener : ICacheEntryEventListener<long, Message>
{
    public void OnEvent(IEnumerable<ICacheEntryEvent<long, Message>> evts)
    {
        foreach (var evt in evts)
            Console.WriteLine($"{evt.Value.Author}: {evt.Value.Text}");
    }
}

然后更新Main方法:

// Retrieve user name
Console.Write("Hi, enter your name: ");
var name = Console.ReadLine();

// Register Message type
var cfg = new IgniteConfiguration
{
    BinaryConfiguration = new BinaryConfiguration(typeof(Message))
};

// Start Ignite and retrieve cache
var ignite = Ignition.Start(cfg);
var cache = ignite.GetOrCreateCache<long, Message>("chat");

// Initialize unique ID sequence
var messageId = ignite.GetAtomicSequence("chatId", 0, true);

// Set up continuous query
cache.QueryContinuous(new ContinuousQuery<long, Message>(new CacheListener()));

// Run the chat loop
while (true)
{
    Console.Write("> ");

    var msgText = Console.ReadLine();
    var msgId = messageId.Increment();

    cache[msgId] = new Message(name, msgText);
}

结论

启动这两个节点,将两个窗口并排,输入一些消息,然后就会看到他们在另外一个窗口中立即显示。 12

完成!跨平台的点对点聊天程序已经创建完毕!这里没有中心服务器,任意数量的客户端都可以在任意时间加入或者离开。 作为一个练习,可以把这个做得更好:

  • 将缓存模式改为Replicated(参考缓存模式),这样每个聊天节点都会持有完整的聊天历史;
  • 设置ContinuousQuery.InitialQuery属性(参考初始查询),这样每个新的节点都会立即显示之前的消息。

这个方式就是说,只要有一个节点存活,整个聊天历史就会被保存,新的节点就会在加入时显示它们。

本文译自Pavel Tupitsyn的博客:Building a Multi-Platform Ignite Cluster: Java + .NET

© 著作权归作者所有

李玉珏

李玉珏

粉丝 384
博文 78
码字总数 148142
作品 0
沈阳
架构师
私信 提问
加载中

评论(4)

李玉珏
李玉珏 博主

引用来自“abcijkxyz”的评论

为了缓存用尽一切方法。圣战:为了缓存!

缓存只是一个例子而已,其实ignite的很多技术都可以使得异构的系统在不大改的情况下实现互联互通,资源共享,只要你能想象的到。
abcijkxyz
abcijkxyz
为了缓存用尽一切方法。圣战:为了缓存!
李玉珏
李玉珏 博主

引用来自“linapex”的评论

有么用?
异构系统共享缓存。
linapex
linapex
有么用?
Apache Ignite原生持久化概述

很多人会问,Ignite有没有持久化存储,或者说是不是一个单纯的内存存储? 答案是都有,Ignite的原生持久化可以打开,也可以关闭。这使得Ignite可以存储比可用内存量大得多的数据集,也就是说...

李玉珏
02/11
488
0
Apache Ignite的Node.js客户端使用入门

介绍 Ignite原生提供了若干种主要编程语言的支持,最近,还通过瘦客户端技术对其它的编程语言提供了支持,其中在2.7版本中新增加的瘦客户端包括Python、PHP和Node.js。 瘦客户端具有如下的特...

李玉珏
02/13
235
0
内存数据组织 - Apache Ignite

1.Ignite是什么? Apache Ignite是一个以内存为中心的分布式数据库、缓存和处理平台,支持事务、分析以及流式负载,可以在PB级数据上享有内存级的性能。 1.1.Ignite定位 Ignite是不是内存数据...

匿名
2015/01/10
28.8K
8
Ignite内存计算平台与Oracle TimesTen Scaleout对比

1.产品介绍 Ignite Ignite内存计算平台是一个高性能、集成化、混合式的企业级分布式架构解决方案,功能强大,有先进的集群管理功能,对于分布式内存数据库、流处理技术、分布式计算、分布式服...

李玉珏
2018/08/09
686
2
Apache Ignite 2.5.0 版本发布,千级节点伸缩性

Apache Ignite 2.5: 千级节点伸缩性 Apache Ignite的用户通常知道的两个关键点是-扩展性和性能。在很多分布式系统的整个生命周期中,通常会不停地改进性能,而对扩展性相关的改进次数,会比较...

李玉珏
2018/06/01
1K
10

没有更多内容

加载失败,请刷新页面

加载更多

JMM内存模型(一)&volatile关键字的可见性

在说这个之前,我想先说一下计算机的内存模型: CPU在执行的时候,肯定要有数据,而数据在内存中放着呢,这里的内存就是计算机的物理内存,刚开始还好,但是随着技术的发展,CPU处理的速度越...

走向人生巅峰的大路
22分钟前
45
0
你对AJAX认知有多少(2)?

接着昨日内容,我们几天继续探讨ajax的相关知识点 提到ajax下面几个问题又是必须要了解的啦~~~ 8、在浏览器端如何得到服务器端响应的XML数据。 通过XMLHttpRequest对象的responseXMl属性 9、 ...

理性思考
31分钟前
4
0
正则表达式基础(一)

1.转义 转义的作用: 当某个字符在表达式中具有特殊含义,例如字符串引号中出现了引号,为了可以使用这些字符本身,而不是使用其在表达式中的特殊含义,则需要通过转义符“\”来构建该字符转...

清自以敬
34分钟前
4
0
idea中@Data标签getset不起作用

背景:换电脑以后在idea中有@data注解都不生效 解决办法:idea装个插件 https://blog.csdn.net/seapeak007/article/details/72911529...

栾小糖
39分钟前
5
0
Apache Kudu 不能删除不存在的数据

使用Apache Kudu客户端,对KafkaConnect Sink 进行扩展。 使用的Apache Kudu 的Java 客户端。突然有天发现作业无法提交,一直报错。 后来才发现这是Kudu自身的一种校验机制。为了忽略这种校验...

吐槽的达达仔
50分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部