I was wondering if there is an example usage of the AddressResolver interface in apache ignite.
I was trying to 'bind' my local IP addresses (e.g. 192.168.10.101) to my external IP address using the AddressResolver interface, but without luck.
When I do that the Ignite server just hangs (no output from the debug either)
My code for starting the server is:
TcpDiscoverySpi spi = new TcpDiscoverySpi();
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
ipFinder.setAddresses(ipaddresses);
spi.setIpFinder(ipFinder);
spi.setAddressResolver(new IotAddressResolver());
IgniteConfiguration cfg = new IgniteConfiguration();
// Override default discovery SPI.
cfg.setDiscoverySpi(spi);
System.setProperty("IGNITE_QUIET", "false");
// Start Ignite node.
ignite = Ignition.start(cfg);
My implementation for AddressResolver is:
public class IotAddressResolver implements AddressResolver {
#Override
public Collection<InetSocketAddress> getExternalAddresses(
InetSocketAddress internalAddresses) throws IgniteCheckedException {
String host = "XX.XX.XX.XX";
Collection<InetSocketAddress> result = new ArrayList<InetSocketAddress>();
result.add(new InetSocketAddress(host, internalAddresses.getPort()));
return result;
}
}
The last line of the ignite debug log is:
WARNING: Timed out waiting for message to be read (most probably, the reason is in long GC pauses on remote node) [curTimeout=9989]
I will appreciate any help. Thank you
Can you provide more details about your deployment and what you're trying to achieve with the help of address resolver? How many physical hosts and Ignite nodes do you have? Are they located in different networks with the router between them?
I dont know if this is the best way to handle this but I managed to start igntie as local server. I am setting my local ip and port like this:
System.setProperty("IGNITE_QUIET", "false");
TcpDiscoverySpi spi = new TcpDiscoverySpi();
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
TcpCommunicationSpi commSpi = new TcpCommunicationSpi();
// Set initial IP addresses.
ipFinder.setAddresses(ipaddresses);
spi.setIpFinder(ipFinder);
// Override local port.
commSpi.setLocalPort(47501);
commSpi.setLocalAddress("XX.XX.XX.XX");
commSpi.setLocalPortRange(50);
IgniteConfiguration cfg = new IgniteConfiguration();
// Override default communication SPI.
cfg.setCommunicationSpi(commSpi);
cfg.setDiscoverySpi(spi);
cfg.setAddressResolver(new IotAddressResolver());
cfg.setClientMode(true);
// Start Ignite node
ignite = Ignition.start(cfg);
Where XX.XX.XX.XX is my local IP address
Related
I have installed 3 nodes of elastic search from Azure marketplace and any node can act as master node. Now how do I connect to the cluster ? If I had one node, I could simply use its IP with Port(9200) but here I have 3 nodes so how do I get the cluster endpoint ? Thanks
This how I did it and it worked well for me:
public class ElasticsearchConfig {
private Vector<String> hosts;
public void setHosts(String hostString) {
if(hostString == null || hostString.trim().isEmpty()) {
return;
}
String[] hostParts = hostString.split(",");
this.hosts = new Vector<>();
Collections.addAll(this.hosts, hostParts);
}
}
public class ElasticClient {
private final ElasticsearchConfig config;
private RestHighLevelClient client;
public ElasticClient(ElasticsearchConfig config) {
this.config = config;
}
public void start() throws Exception {
HttpHost[] httpHosts = new HttpHost[config.getHosts().size()];
config.getHosts()
.stream()
.map(host -> new HttpHost(host.split(":")[0], Integer.valueOf(host.split(":")[1])))
.collect(Collectors.toList())
.toArray(httpHosts);
client = new RestHighLevelClient(RestClient.builder(httpHosts));
System.out.println("Started ElasticSearch Client");
}
public void stop() throws Exception {
if (client != null) {
client.close();
}
client = null;
}
}
Set the ElasticsearchConfig as below:
ElasticsearchConfig config = new ElasticsearchConfig();
config.setHosts("ip1:port,ip2:port,ip3:port");
If all three nodes are part of same cluster than no need to specify all the nodes and even one single node ip is enough to connect to the cluster.
But above approach has some disadvantage and in small cluster with less workload its fine as in this case only one node which you configure in your elasticsearch client will act as co-ordinating node and can become a hot-spot in your cluster, its better to have all the nodes configured in your client so for every request any one node can act co-ordinating node and if you have huge workload you might also consider to have dedicated co-ordinating nodes for even better performance.
Hope this answer your question and I didn't provide the code snippet as don't know which language and client you are using and in your question I felt code is not issue but you want to understand the concept in detail.
Appreciate everyone's time and all those who replied; Turns out that by default, Azure marketplace copy of self managed ES, sets up only "Internal Load Balancer". I was able to get the cluster end point as soon as I configured "External Load Balancer". All set now.
I am new to Ignite and Kubernetes. I have a.Net Core 3.1 web application which is hosted Azure Linux App Service.
I followed the instructions (Apache Ignite Instructions Offical Site) and Apache Ignite could run on Azure Kubernetes. I could create a sample table and read-write actions worked successfully. Here is the screenshot of my success tests on PowerShell.
Please see the success test
Now, I try to connect Apache Ignite from my .net core web app but I couldn't make it.
My code is as below. I try to connect with IgniteConfiguration and SpringCfgXml, but both of them getting error.
private void Initialize()
{
var cfg = GetIgniteConfiguration();
_ignite = Ignition.Start(cfg);
InitializeCaches();
}
public IgniteConfiguration GetIgniteConfiguration()
{
var appSettingsJson = AppSettingsJson.GetAppSettings();
var igniteNodes = appSettingsJson["AppSettings:IgniteNodes"];
var nodeList = igniteNodes.Split(",");
var config = new IgniteConfiguration
{
Logger = new IgniteLogger(),
DiscoverySpi = new TcpDiscoverySpi
{
IpFinder = new TcpDiscoveryStaticIpFinder
{
Endpoints = nodeList
},
SocketTimeout = TimeSpan.FromSeconds(5)
},
IncludedEventTypes = EventType.CacheAll,
CacheConfiguration = GetCacheConfiguration()
};
return config;
}
The first error I get:
Apache.Ignite.Core.Common.IgniteException HResult=0x80131500
Message=Java class is not found (did you set IGNITE_HOME environment
variable?):
org/apache/ignite/internal/processors/platform/PlatformIgnition
Source=Apache.Ignite.Core
Also, I have no idea what I am gonna set for IGNITE_HOME, and username and secret to authentication.
Solution :
I finally connect the Ignite on Azure Kubernetes.
Here is my connection method.
public void TestConnection()
{
var cfg = new IgniteClientConfiguration
{
Host = "MyHost",
Port = 10800,
UserName = "user",
Password = "password"
};
using (IIgniteClient client = Ignition.StartClient(cfg))
{
var employeeCache1 = client.GetOrCreateCache<int, Employee>(
new CacheClientConfiguration(EmployeeCacheName, typeof(Employee)));
employeeCache1.Put(1, new Employee("Bilge Wilson", 12500, 1));
}
}
To find to host IP, user name and client secret please check the below images.
Client Id and Secret
IP Addresses
Note: I don't need to set any IGNITE_HOME ana JAVA_HOME variable.
The simplest way is to download Apache Ignite binary distribution (of the same version as one that you use), unzip it to a directory, and point IGNITE_HOME environment variable or IgniteConfiguration.IgniteHome configuration property to unzipped apache-ignite-n.n.n-bin/ directory absolute path.
We support doing that automatically for Windows-hosted apps but not for Linux-based deployments.
We have a 3 nodes cluster with a RF 3.
As soon as we drain one node from the cluster we see many:
All host(s) tried for query failed (no host was tried)
com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (no host was tried)
at com.datastax.driver.core.exceptions.NoHostAvailableException.copy(NoHostAvailableException.java:84)
at com.datastax.driver.core.DriverThrowables.propagateCause(DriverThrowables.java:37)
at com.datastax.driver.core.DefaultResultSetFuture.getUninterruptibly(DefaultResultSetFuture.java:214)
at com.datastax.driver.core.AbstractSession.execute(AbstractSession.java:52)
All our writes and read are with a Consistency Level QUORUM or ONE so with one node down everything should work perfectly. But as long as the node is down, exceptions are thrown.
We use Cassandra 2.2.4 + Java Cassandra Driver 2.1.10.2
Here's how we create our cluster:
new Cluster.Builder()
.addContactPoints(CONTACT_POINTS)
.withCredentials(USERNAME, PASSWORD)
.withRetryPolicy(new LoggingRetryPolicy(DefaultRetryPolicy.INSTANCE))
.withReconnectionPolicy(new ExponentialReconnectionPolicy(10, 10000))
.withLoadBalancingPolicy(new TokenAwarePolicy(new RoundRobinPolicy()))
.withSocketOptions(new SocketOptions().setReadTimeoutMillis(12_000))
.build();
CONTACT_POINTS is a String array of the 3 public ips of the nodes.
A few months ago, the cluster was working fine with temporarily only 2 nodes but for an unknown reason it's not the case anymore and I'm running out of ideas :(
Thanks a lot for your help!
Problem solved.
More analysis showed that the issue was coming from an IP problem. Our cassandra servers use private local IPs (10.0.) to communicate together while our app servers have their public IPs in their config.
When they were in the same network it was working properly but as they moved to a different network, they were able to connect to only one machine of the cluster and the other two were considered as down as they were trying to connect to the private local IPs instead of the public one for the other two.
The solution was to add an IPTranslater in the cluster builder:
.withAddressTranslater(new ToPublicIpAddressTranslater())
With the following code:
private static class ToPublicIpAddressTranslater implements AddressTranslater {
private Map<String, String> internalToPublicIpMap = new HashMap<>();
public ToPublicIpAddressTranslater() {
for (int i = 0; i < CONTACT_POINT_PRIVATE_IPS.length; i++) {
internalToPublicIpMap.put(CONTACT_POINT_PRIVATE_IPS[i], CONTACT_POINTS[i]);
}
}
#Override
public InetSocketAddress translate(InetSocketAddress address) {
String publicIp = internalToPublicIpMap.get(address.getHostString());
if (publicIp != null) {
return new InetSocketAddress(publicIp, address.getPort());
}
return address;
}
}
I have defined "static" hazelcast configuration:
#Bean
public Config getHazelcastConfig() {
final Config config = new Config();
config.setProperty("hazelcast.logging.type", "slf4j");
final GroupConfig groupConfig = new GroupConfig();
groupConfig.setName("projectName");
groupConfig.setPassword("projectPassword");
config.setGroupConfig(groupConfig);
final NetworkConfig networkConfig = new NetworkConfig();
final TcpIpConfig tcpIpConfig = new TcpIpConfig();
final String[] members = "10.0.0.2".split(",");
for (String member : members) {
tcpIpConfig.addMember(member);
}
tcpIpConfig.setConnectionTimeoutSeconds(5);
final JoinConfig joinConfig = networkConfig.getJoin();
joinConfig.getAwsConfig().setEnabled(false);
joinConfig.getMulticastConfig().setEnabled(false);
joinConfig.setTcpIpConfig(tcpIpConfig);
joinConfig.getTcpIpConfig().setEnabled(true);
joinConfig.getTcpIpConfig().setConnectionTimeoutSeconds(5);
config.setNetworkConfig(networkConfig);
config.setInstanceName("projectInstanceName");
return config;
}
Where "10.0.0.2" is my localhost ip. I want only one instance of hazelcast added to my tcpIpConfig members. My friend is sitting in the same network and has IP with number "10.0.0.3". He is lazy to change password and group name from property file shared on git and is connecting to my cluster. Why he is able to connect to my cluster? How I can prevent this?
Yesss, #Sachin. You are right. After adding
securityCfg.setEnabled(true);
to hazelcast configuration passwords and logins are checked.
Second problem I had with multiple hazelcast instances on localhost was related with hibernate. When using hazelcast as second level cache in hibernate there is created hazelcast member. It can be turned on/off by:
properties.setProperty("hibernate.cache.hazelcast.use_native_client", "false");
or
properties.setProperty("hibernate.cache.hazelcast.use_native_client", "true");
I am trying to develop a Video Client/functionality that captures video using webcam and transfers to other servent (server-client) somewhere on the internet. I am using UDPCLient Class to do that.
I want my application to be able to listen and tarnsmit video captured from webcam. The capturing, transmission and receiving works fine when i do that on local network.
But when i test the application from behind router (across two differnt networks/internet) after forwarding respective ports, the internet connectivity is lost on both routers (They hang up or something) and i need to restart the routers or switch to an alternate connection. The configuration is as follows:
Servent 1 <--> Router1 <--> Internet Connection#01
Servent 02 <---> Router2 <---> Internet Connection#02
Both connections are on separate DSL Line. One of the routers is ZTE brand and the other is of Netgear.
Code for listenning/transmission is as follows:
private void StartSockets()
{
//For testing across internet i use IPAddress obtained via different function
var IPAddress = getMyIpAddress();
this.udpSender = new UdpClient(IpAddress, 4000);
this.udpListener = new UdpClient(4000);
}
private IPAddress getMyIpAddress()
{
IPAddress localIP ;//= AddressAr[0];
localIP = IPAddress.Parse(GetPublicIP());
return localIP;
}
public string GetPublicIP()
{
String direction = "";
WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
using (WebResponse response = request.GetResponse())
{
using (StreamReader stream = new StreamReader(response.GetResponseStream()))
{
direction = stream.ReadToEnd();
}
}
//Search for the ip in the html
int first = direction.IndexOf("Address: ") + 9;
int last = direction.LastIndexOf("</body>");
direction = direction.Substring(first, last - first);
return direction;
}
Code for receiving response is as follows:
private void ReceiveData()
{
//For testing across internet i use IPAddress obtained via different function
var IPAddress = getMyIpAddress();
IPEndPoint ep = new IPEndPoint(IPAddress, myPort);
try
{
byte[] receiveBytes = this.udpListener.Receive(ref ep);
this.OnReadImage(new ImageEventArgs(this.ByteToImage(receiveBytes)));
}
catch (Exception)
{
}
}
If i test on local network , i use DNSHostname to get ip address (private ip addresses) and video works fine on local network. That does not work over internet so i switch to live Ip Address and thus i use the method of getPublicIpAddress().
I know there is something seriously wrong with my approach? What would be right approach?
Should i switch to TCP Listenner? I intend to have multiple receiver of same video in future. So would that affect?
Can UDP clients cause routers to crash, hang up and restart? How can i avoid that?
Lastly, if were to avoid port-forwarding what would be the best strategy?
Please help.
Thanks
Steve