Migrating from Elastic 2 to 5


(praveen) #1
  1. We are migrating from Spring Boot 1.x (comes with Elastic 2) to
    Spring Boot 2.x (comes with Elastic 5)
    In Spring boot 1 (i.e Elastic 2), we've used the NodeBuilder api to create in memory nodes on demand.

  2. With SpringBoot 2(i.e Elastic 5), Nodebuilder is not available, we tried using below code:

   File tmpDir = File.createTempFile("elastic",Long.toString(System.nanoTime()));
    Settings settings = Settings.builder()
            .put("http.enabled", true)
              .put("index.number_of_shards", "1")
              .put("path.data", new File(tmpDir, "data").getAbsolutePath())
              .put("path.logs", new File(tmpDir, "logs").getAbsolutePath())
              .put("path.work", new File(tmpDir, "work").getAbsolutePath()) 
              .put("transport.tcp.port", "9300")
              .put("network.host", "localhost")              
              .put("node.data", "true")
              .put("node.master", "true")

             .put("path.home", tmpDir)
            .put("transport.type", "local").build();
    return new ElasticsearchTemplate(new Node(settings).start().client());
  1. When we try to access the ElasticsearchRepository, it is giving below exception:
NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{6gkUXEX6Rsyowd928D0k_A}{localhost}{127.0.0.1:9200}]]
        at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:347)
        at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:245)
        at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:59)
        at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:363)
        at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:408)
        at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:80)
        at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:54)
        at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.doCount(ElasticsearchTemplate.java:495)
        at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.count(ElasticsearchTemplate.java:473)
        at org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepository.count(AbstractElasticsearchRepository.java:150)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377)
        at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200)
        at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:641)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605)
        at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:590)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
        at com.sun.proxy.$Proxy139.count(Unknown Source)
        at com.werner.ecp.elastic.service.carrier.ElasticCarrierServiceImpl.getCarrierCount(ElasticCarrierServiceImpl.java:58)
        at com.werner.ecp.elastic.service.carrier.ElasticCarrierServiceImpl$FastClassBySpringCGLIB$e96152a4.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
  1. Any thoughts on what am missing? appreciate your help!

(David Turner) #2

Embedding Elasticsearch into your application like this isn't really a recognised way of running Elasticsearch any more. This blog post from 2016 describes the reasoning for this decision.

It may be possible to get it to work like this still, but it's not something we cover in any tests so it might be fragile and difficult to debug. If at all possible, you should run Elasticsearch as a standalone process instead.


(praveen) #3

Thanks Dave for your feedback.

If we move out of 'embedded Elastic server within the application' and move into external standalone elastic search server, how do we set up clustering?
In production, our application runs on 4 servers . Does that mean we need to run Elastic search instance on these 4 DMZ servers? If yes, how do we make sure the 4 Elastic search instance are running in a clustered fashion?
Any feedback/pointers will be highly appreciated!


(David Turner) #4

The setup in your original post did not look like a clustered installation, so perhaps you do not need this? The reference manual covers the configuration needed, particularly this page:

https://www.elastic.co/guide/en/elasticsearch/reference/current/discovery-settings.html

You do not necessarily need to run an Elasticsearch node on each of your servers, because you can communicate with Elasticsearch over HTTP.


(praveen) #5

This is how our current set up looks like

If am running only one external Elastic server, how do we accomplish the load balance and failover piece?

Do we have a way to get on a phone call or meeting?

Thanks Much.


(David Turner) #6

It was not clear from your OP that this was your goal. A resilient Elasticsearch cluster needs at least 3 master-eligible nodes and at least two data nodes (some nodes may be both, so 3 nodes in total).

Although this community forum isn't really the right place to push commercial things, there's no real-time community support offering so the most helpful way I can answer this is to point out that Elastic can help with support and consulting, and this subject matter is also covered in training: https://www.elastic.co/services


(praveen) #7

Sorry for the confusion.

I tried some clustering on my local machine by making below edits to the shipped elasticSearch.yml:

Node 1;
cluster.name: my-elastic-cluster
node.name: my-master-node
node.master: true
node.data: false
network.host: 1.X.Y.Z
Discovery.zen.ping.unicast.hosts: ["1.X.Y.Z:9300", "127.0.0.1:9300"]

Node 2;
cluster.name: my-elastic-cluster
node.name: my-data-node
node.master: false
node.data: true
network.host: 127.0.0.1
Discovery.zen.ping.unicast.hosts: ["1.X.Y.Z:9300", "127.0.0.1:9300"]

Although both the nodes come up fine.

  1. When I try to --> http://1.X.Y.Z:9200/_cluster/health?pretty
    I get
    {
    "cluster_name" : "praveen-elastic-cluster",
    "status" : "red",
    "timed_out" : false,
    "number_of_nodes" : 2,
    "number_of_data_nodes" : 1,
    "active_primary_shards" : 0,
    "active_shards" : 0,
    "relocating_shards" : 0,
    "initializing_shards" : 0,
    "unassigned_shards" : 10,
    "delayed_unassigned_shards" : 0,
    "number_of_pending_tasks" : 0,
    "number_of_in_flight_fetch" : 0,
    "task_max_waiting_in_queue_millis" : 0,
    "active_shards_percent_as_number" : 0.0
    }

  2. Also, when I try to index a document via postman client, I get this:

"error": {"root_cause": [ {
"type": "unavailable_shards_exception",
"reason": "[accounts][3] primary shard is not active..... }

 Guessing if 1 is fixed, 2 will be fixed.

Question:

  1. Any thoughts around what changes do I need to make on my local so that the my local cluster status is green and doesn't have any unassigned shards?

  2. Also, would you have a sample elasticsearch.yml files for the above mentioned 3 node cluster? where each nodes are running on different machines?

Thanks a bunch for your continuous help!


(praveen) #8

I cleaned up some folders under elastic directory and am able to run elastic nodes on my local in a clustered fashion. Thanks Dave for all your help!


(David Turner) #9

You're welcome :slight_smile:

For future reference, if you have an unassigned shard, the allocation explain API is the first thing you should look at, as it will try and explain why things couldn't be allocated.


(praveen) #10

Dave - Now that am able to make some progress on how to set up ES cluster locally, I have my next set of questions for you! :slight_smile:

Our current Elastic implementation:
Ours is a SpringBoot (SprinBoot 1.5) application. We have used Spring Boot API to implement
Embedded Elastic (i.e its an in-memory elastic instance within the app) and we use Node client to connect to our embedded elastic instance.

What we like to get to:

  • We are looking to migrate from Embedded Elastic to an External Elastic server.
  • Migrate from using Node Client and to using a Rest Client

Questions For you:

1) Any pointers you can provide on how we go about migrating our application code from NodeClient to using Rest Client?
2) They talk about Low Level Rest Client and High Level Rest Client. Which one would you recommend us to use? High Level Rest client is available from what version of Elastic?

Thanks Much for your feedback!


(David Turner) #11

Not really, I've never done such a migration myself. The client APIs are designed to be quite similar in shape. Are you stuck on something specific?

You should use the High-level REST client as much as possible, but it does not cover 100% of the APIs so you might need to use the Low-level REST client from time to time. You can use both clients in one application (in fact the high-level one is implemented on top of the low-level one).


(praveen) #12

Any sample code or links you can share around High and Low level rest client?


(praveen) #13

"Are you stuck on something specific?" --> just looking to see how to get started/proceed with this migration in general..