Wednesday, April 1, 2020

ElasticSearch– was created with version [5.3.0] but the minimum compatible version is [6.0.0-beta1]. It should be re-indexed in Elasticsearch 6.x before upgrading to 7.6.1.

As mentioned in some of the previous posts I am migrating an ‘old’ 5.3 instance of ElasticSearch to 7.6.1. In my first (too optimistic) attempt I directly migrated to ElasticSearch 7.6.1.

When starting the ElasticSearch cluster this resulted in the following error message:

[myindex/gTTtwHT3ShiAz-eR94eKmw]] was created with version [5.3.0] but the minimum compatible version is [6.0.0-beta1]. It should be re-indexed in Elasticsearch 6.x before upgrading to 7.6.1.

               at org.elasticsearch.cluster.metadata.MetaDataIndexUpgradeService.checkSupportedVersion(MetaDataIndexUpgradeService.java:113)

               at org.elasticsearch.cluster.metadata.MetaDataIndexUpgradeService.upgradeIndexMetaData(MetaDataIndexUpgradeService.java:87)

               at org.elasticsearch.gateway.GatewayMetaState.upgradeMetaData(GatewayMetaState.java:240)

               at org.elasticsearch.gateway.GatewayMetaState.upgradeMetaDataForNode(GatewayMetaState.java:223)

               at org.elasticsearch.gateway.GatewayMetaState.start(GatewayMetaState.java:154)

               at org.elasticsearch.node.Node.start(Node.java:705)

at org.elasticsearch.bootstrap.Bootstrap.start(Bootstrap.java:273)

               at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:358)

at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170)

               at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:161)

               at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86)

               at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:125)

               at org.elasticsearch.cli.Command.main(Command.java:90)

               at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:126)

               at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92)

For complete error details, refer to the log at C:\Program Files\ElasticSearch\7.6.1\logs\elasticsearch.log

The trick is to first migrate to ElasticSearch 6.8 and Kibana 6.8. Kibana 6.8 offers an update wizard which guides you through the required steps to upgrade your indices to a supported format.

Here are the steps:

  • Go to Kibana
  • Click on the Management icon on the left
  • Click on the 7.0 Upgrade Assistant
  • Check all the listed issues and apply the suggested solutions
  • When everything is fixed you can safely install ElasticSearch 7.x

Tuesday, March 31, 2020

ElasticSearch - Error when using latest OpenJRE

While migration from ElasticSearch 5 to 7.6.1 I had to take an extra step and first migrate to ElasticSearch 6.8.

When I tried to run the 6.8 version, it failed with the following error message:

2020-03-30 10:18:32 Commons Daemon procrun stderr initialized

OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.

Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.jdk.internal.vm.annotation")

               at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)

               at java.base/java.security.AccessController.checkPermission(AccessController.java:1036)

               at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:408)

               at java.base/java.lang.SecurityManager.checkPackageAccess(SecurityManager.java:1324)

               at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:174)

               at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)

               at java.base/java.lang.Class.forName0(Native Method)

               at java.base/java.lang.Class.forName(Class.java:416)

               at java.base/sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)

               at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)

               at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)

               at java.base/sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:440)

               at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:242)

               at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:121)

               at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:73)

               at java.base/java.lang.reflect.Executable.declaredAnnotations(Executable.java:614)

               at java.base/java.lang.reflect.Executable.declaredAnnotations(Executable.java:612)

               at java.base/java.lang.reflect.Executable.getAnnotation(Executable.java:582)

               at java.base/java.lang.reflect.Method.getAnnotation(Method.java:696)

               at <<<guice>>>

               at org.elasticsearch.repositories.RepositoriesModule.lambda$configure$1(RepositoriesModule.java:68)

               at java.base/java.util.HashMap.forEach(HashMap.java:1338)

               at java.base/java.util.Collections$UnmodifiableMap.forEach(Collections.java:1505)

               at org.elasticsearch.repositories.RepositoriesModule.configure(RepositoriesModule.java:68)

               at <<<guice>>>

               at org.elasticsearch.node.Node.<init>(Node.java:492)

               at org.elasticsearch.node.Node.<init>(Node.java:245)

at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:212)

               at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:212)

               at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:322)

               <<<truncated>>>

The problem was that I already installed the latest JAVA OpenJRE. This version is not compatible with ElasticSearch 6.8.

To fix it I had to downgrade to Java 12.

Monday, March 30, 2020

ElasticSearch–Failed to run ElasticSearch 7.6.1 after upgrade

After upgrading ElasticSearch to 7.6.1, it failed to start when I tried to run ElasticSearch as a windows service.

In the logs I found the following error message:

[2020-03-30 10:04:11] [info]  [ 4516] Service 'elasticsearch-service-x64' installed

[2020-03-30 10:04:11] [info]  [ 4516] Commons Daemon procrun finished

[2020-03-30 10:04:23] [info]  [ 4336] Commons Daemon procrun (1.1.0.0 64-bit) started

[2020-03-30 10:04:23] [info]  [ 4336] Running 'elasticsearch-service-x64' Service...

[2020-03-30 10:04:23] [info]  [ 4992] Starting service...

[2020-03-30 10:04:23] [error] [ 2432] CreateJavaVM Failed

[2020-03-30 10:04:23] [error] [ 2432] The system cannot find the file specified.

[2020-03-30 10:04:23] [error] [ 4992] Failed to start Java

[2020-03-30 10:04:23] [error] [ 4992] ServiceStart returned 4

[2020-03-30 10:04:23] [info]  [ 4336] Run service finished.

[2020-03-30 10:04:23] [info]  [ 4336] Commons Daemon procrun finished

The problem is that ElasticSearch tries to pass on a ‘-server’ option which is no longer supported in the latest JAVA versions.

To fix I had to change the Java Options:

  • Install the windows service through ‘elasticsearch-service install’
  • Open the ElasticSearch service manager through ‘elasticsearch-service manager’
  • Go to the Java tab and remove the ‘-server’ flag from the Java Options

  • Start the service

Friday, March 27, 2020

C#–Discards

Have a look at the code below:

Did you notice the underscore character ‘_’? This is the discard character.

From the documentation:

Starting with C# 7.0, C# supports discards, which are temporary, dummy variables that are intentionally unused in application code. Discards are equivalent to unassigned variables; they do not have a value. Because there is only a single discard variable, and that variable may not even be allocated storage, discards can reduce memory allocations. Because they make the intent of your code clear, they enhance its readability and maintainability.

This is more than just a placeholder variable. If you try to use the assigned _ value later on in your code, this will fail:

Thursday, March 26, 2020

Microsoft Orleans - Multi silo deployment behind a load balancer

In one of my projects we are using Orleans, the virtual actor framework from Microsoft. Your Orleans backend(the cluster) can span out over multiple servers(silos).

In a cluster there are 2 types of communication  happening:

  • silo-to-silo communication(through the silo port)
  • client-to-silo communication(through the gateway port)

As a result on every server 2 ports should be opened to enable this traffic.

Load balancing

The Orleans runtime does all the load balancing for you. More important it is one of the pillars of the Orleans runtime. The runtime tries to make everything balanced, since balancing allows to maximize resource usage and avoid hotspots, which leads to better performance, as well as helps with elasticity.

More information: https://dotnet.github.io/orleans/Documentation/implementation/load_balancing.html

This means that it doesn’t make sense to put a load balancer between the clients and the cluster as this would defy one of the core purposes of the Orleans runtime.

But what if a load balancer exists?

This was exactly the situation I had with one of my customers. They were not fully aware that it doesn’t make sense to add a load balancer and installed our Orleans application on 2 servers behind a load balancer.

What they noticed was the following? As long as only one silo was running everything worked as expected. However the moment a second silo was spinned up, the other one shut down.

The problem was that due to the load balancer both silo got the same IP address. This was easily detectable in the Orleans Membershiptable:

To solve it, we explicitly specified the IP address of each server in the silo configuration:

Wednesday, March 25, 2020

Autofac - Decorators

One of the nice features of Autofac is the support for decorators.

A decorator class implements the same interface as the class it “wraps”.  With a decorator you can add functionality to a class without changing it’s signature.

Let’s walk through an example step by step:

Here is the class and it’s corresponding interface I want to decorate:

Nothing special at the Autofac level yet:

Let’s now extend the behavior of this class through a decorator. What if we want to benchmark the execution time of the LogMessage() method? The decorator class should implement the same interface AND inject the interface at the same time:

Now we need to register the decorator in Autofac:

Remark: When using generics, it is also possible to register an open generic  decorator. Therefore you need to use the RegisterGenericDecorator() overload

More information: https://autofaccn.readthedocs.io/en/latest/advanced/adapters-decorators.html

Tuesday, March 24, 2020

C#–is null or == null that’s the question

While reviewing some code I noticed the following code construct:

So far I’ve always written my null checks using the following syntax:

I wasn’t aware that this was even possible. Turns out this was introduced in C# 7.

Why would you use the ‘is’ keyword instead of ‘==’? The ‘is’ keyword ignores any operator overloads so you don’t end up with unexpected behavior when you are using operator overloading.

Learned something today? Check!