Building a multi-platform Ignite cluster: Java+.NET

Building a multi-platform Ignite cluster: Java+.NET

An Ignite cluster can consist of nodes launched on any platform it supports, including Java, .NET, and C++. This article will show you how to run a .NET/Java cluster with NuGet and Maven. As an example, this article will create a cross-platform peer-to-peer chat system.1

Preconditions

This article is intended for .NET developers unfamiliar with Java and vice versa, so it will be described in more detail. This article will use the following software:

  • Visual Studio 2015 (including NuGet; free community edition);
  • IntelliJ IDEA (including Maven; free community edition).

The full source code for this article is on GitHub, github.com/ptupitsyn/ignite-multi-platform-demo . For brevity, the code below is not very complete (public fields, no namespaces, etc.).

Target

  • Connect Java and .NET nodes;
  • Use Java and .NET classes to access shared data in the Ignite cache with the same names and fields;
  • Run continuous queries and watch real-time data updates from another platform.

Java project settings

  • Start IntelliJ IDEA and click "Create New Project":2
  • Select Maven and click "Next":3
  • Enter the Maven information, click "Next" and then "Finish":4 5
  • Once done, you will see the files opened for the new project pom.xml:6
  • projectAdd Ignite dependency to fragment:
<dependencies>
    <dependency>
        <groupId>org.apache.ignite</groupId>
        <artifactId>ignite-core</artifactId>
        <version>1.7.0</version>
    </dependency>
</dependencies>
  • IDEA may ask whether to import project changes, click on any link:7
  • Add the class to src\main\java with the Demofollowing code:
import org.apache.ignite.Ignition;

public class Demo {
    public static void main(String[] args) {
        Ignition.start();
    }
}
  • Confirm that the node is up by Shift+F10running and then on IDEA's console:

8

  • Terminate the program with the Ctrl+F2or stop button.

.NET Project Settings

  • Start Visual Studio and click File -> New -> Project:
  • Select Visual C# -> Windows -> Console Application:
  • Make sure .NET Framework version 4 and above is selected above:

9

  • Click "OK", then an empty console project will be generated;
  • Open the NuGet console: Menu -> Tools -> NuGet Package Manager -> Package Manager Console;
  • Enter Install-Package Apache.Ignite:

10

  • Hit enter and Successfully installed 'Apache.Ignite 1.7.0' to IgniteMultiPlatformthis message will be output.
  • Change the Program.cscontent to the following:
using System;
using Apache.Ignite.Core;
class Program
{
    static void Main(string[] args)
    {
        Ignition.Start();
        Console.ReadKey();
    }
}
  • Confirm in the console that the Ignite node is up by Ctrl-F5starting the program:

11

Adjust the configuration of Java nodes to discover .NET nodes

Now, you can start the Java node in IDEA and the .NET node in Visual Studio at the same time, and you will find the following error in one of them:

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]

The error is saying that .NET node BinaryConfigurationonly supports BinaryBasicIdMapperand in Java and BinaryBasicNameMapperneeds to be set explicitly in Java, change the Ignition.start();line to the following code:

BinaryConfiguration binCfg = new BinaryConfiguration();

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

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

Ignition.start(cfg);

Now start the Java and .NET nodes at the same time and verify that they can discover each other:

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

Data exchange via Ignite cache

Now that each node is connected, a simple chat program will be written on each platform to demonstrate data exchange. The code is very simple because the API is the same and the language syntax is similar. First, define a class with the exact same name and members.

Java Message类

Right-click the src\main\java project folder and select New -> Java Class, enter the Messagename, and the code is as follows:

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

.NET Message class

Right-click the project node of the Solution Explorer, then select Add -> Class..., enter the Messagename, and the code is as follows:

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

BasicThe mapper is case-sensitive and ignores namespaces (packages), so the two classes are mappable to each other, injecting a Message instance into the cache in one platform and fetching it in the other. Now to write the chat program itself, the logic is relatively simple: the user enters a chat message, then injects it into the cache, and the continuous query will receive all cache update notifications and display them.

Java chat program

mainChange the code of the method to the following:

// 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 chat program

There are two differences in Ignite.NET (these features are expected to be implemented in the next version):

  • Need to register a type for caching in BinaryConfiguration (Java will do this automatically);
  • Lambda expressions are not yet supported in the API, and ICacheEntryEventListener<K, V>interfaces need to be implemented separately.

So create a separate class with the following code:

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}");
    }
}

Then update the Mainmethod:

// 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);
}

in conclusion

Start these two nodes, put the two windows side by side, type some messages, and you'll see them immediately appear in the other window.12

Finish! A cross-platform peer-to-peer chat program has been created! There is no central server, and any number of clients can join or leave at any time. As an exercise, this can be done better:

  • Change the cache mode to Replicated(refer to cache mode ), so that each chat node will hold the complete chat history;
  • Set the ContinuousQuery.InitialQueryproperty (see Initial Query ) so that each new node immediately displays the previous message.

This way, as long as one node is alive, the entire chat history will be saved, and new nodes will show them as they join.

This article is translated from Pavel Tupitsyn's blog: Building a Multi-Platform Ignite Cluster: Java + .NET

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324539790&siteId=291194637