elastic / elasticsearch-php

Official PHP client for Elasticsearch.
https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
MIT License
5.26k stars 965 forks source link

client->indices()->stats fails with "No alive nodes in your cluster" exception #1146

Closed FxNion closed 2 years ago

FxNion commented 3 years ago

Summary of problem or feature request

The call to indices->stats(INDEX_NAME) throw an Exception "No alive nodes in your cluster" The cluster is single node, and respond correctly to other client calls, through PHP client our curl

Code snippet of problem

$this->client->indices()->stats(['index'=>'es-index']);

System details

ezimuel commented 3 years ago

@FxNion can you post the PHP code that you are using to build the $this->client instance? Can you also share the code that you mentioned working using other client? Thanks.

FxNion commented 3 years ago

@ezimuel, here the whole things i found to help:

The docker-compose part (who knows):

elasticsearch-7:
    container_name: elasticsearch-7
    image: docker.elastic.co/elasticsearch/elasticsearch:7.13.1
    restart: always 
    environment:
      - discovery.type=single-node
      - cluster.name=wabtch-es-docker-cluster
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms1G -Xmx1G -Xlog:disable -Xlog:all=warning:stderr:utctime,level,tags -Xlog:gc=debug:stderr:utctime"
     ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - elasticsearch-7:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - backend

The php code used to create the client (truncated):

class ElasticRepository{

    protected $index, $host, $client;

    public function __construct($host, $index){
        $this->index = $index;
        $this->host = $host;
        $this->buildClient();
    }

    public function getIndexSize(){
        try {
            return (int)($this->client->indices()->stats(['index'=>$this->getIndexName()])['_all']['primaries']['store']['size_in_bytes'] / 1024 /1024 );
        }catch(\ Exception $e){
            error_log("getIndexSize : " . $e->getMessage());
            return 1024;
        }
    }

    public function getClient(){
        return $this->client;
    }

    public function getIndexName(){
        return $this->index;
    }

    protected function buildClient()  {
                $clientBuilder = \Elasticsearch\ClientBuilder::create();   // Instantiate a new ClientBuilder
                $clientBuilder->setHosts([$this->host]);           // Set the hosts
                $this->client = $clientBuilder->build();          // Build the client object
        }
// Other code, truncated ...
}

//To obtain index size, use the stat endpoint ...
$params = [
    'host' => config('elastic.host'),
    'port' => config('elastic.port'),
    'user' => config('elastic.username'),
    'pass' => config('elastic.password')
];

$esRepository= new ElasticRepository($params, 'the_cool_project'); 
$stats = $esRepository->getIndexSize();

And when the stat portion of code fails, i do search queries in my apps, using the same classes, but also just doing a query to the catalog endpoint to check wether nodes are really dead (they are alive):

docker exec -it elasticsearch-7 curl http://localhost:9200/_cat/indices?v

Or even, the stat endpoint, which is successfull

docker exec -it elasticsearch-7 curl http://localhost:9200/_stats

Hope this helps, Regards

ezimuel commented 3 years ago

@FxNion I didn't find the issue on your code. I suggest to enable the logging with DEBUG level to investigate more. You can enable the logging installing monolog (composer require monolog/monolog) and using the following code:

use Elasticsearch\ClientBuilder;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('name');
$logger->pushHandler(new StreamHandler('elasticsearch-php.log', Logger::DEBUG));

$client = ClientBuilder::create() 
    ->setLogger($logger)
    ->build(); 

$result = $client->indices()->stats(['index'=>'es-index']);
var_dump($result);

Then you can find the log in the elasticserach-php.log file. Please, share the log file so I can help you.

damianoi commented 3 years ago

@ezimuel I'm experiencing the same issue reported by @FxNion. Unfortunately I don't know if he finally solved it or not, by the way, I'm attaching you the elasticsearch-php.log file. elasticsearch-php.log

Reading the log, it reports "connection refused", but it's quite strange since using a simple curl call from terminal like this: curl -X GET http://elastic:changeme@localhost:9200 it works perfectly and elasticsearch is responding returning cluster's info, as expected.

This is the class that is managing the call to my local Elasticsearch instance:

use Elasticsearch\ClientBuilder;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;

class ElasticsearchRepository
{
    protected $index, $host, $client;

    public function __construct($index, $host = null){
        $this->index = $index;

        if(!$host)
        {

            $host = [
                'host' => config('elasticsearch.default_connection.host'), // 127.0.0.1
                'port' => config('elasticsearch.default_connection.port'), // 9200
                'user' => config('elasticsearch.default_connection.username'), // elastic
                'pass' => config('elasticsearch.default_connection.password'), // changeme
                'scheme' => config('elasticsearch.default_connection.scheme') // http
            ];

            // $host = 'http://elastic:changeme@127.0.0.1:9200';
        }

        $this->host = $host;

        $this->buildClient();
    }

    public function getIndexSize(){
        try {
            return (int)($this->client->indices()->stats(['index'=>$this->getIndexName()])['_all']['primaries']['store']['size_in_bytes'] / 1024 /1024 );
        }catch(\ Exception $e){
            var_dump("getIndexSize : " . $e->getMessage());
            return 1024;
        }
    }

    public function getClient(){
        return $this->client;
    }

    public function getIndexName(){
        return $this->index;
    }

    protected function buildClient()  {

        $logger = new Logger('name');
        $logger->pushHandler(new StreamHandler('elasticsearch-php.log', Logger::DEBUG));

        $clientBuilder = ClientBuilder::create()->setLogger($logger);   // Instantiate a new ClientBuilder
        $clientBuilder->setHosts([$this->host]);           // Set the hosts
        $clientBuilder->includePortInHostHeader(true);
        $this->client = $clientBuilder->build();          // Build the client object
    }
}

Then, when I create a new instance of the class in this way:

$repo = new ElasticsearchRepository('test-index');

var_dump($repo->getIndexSize());

I get this response:

string(51) "getIndexSize : No alive nodes found in your cluster" int(1024)

damianoi commented 3 years ago

Update: I'm having two different docker containers: one for elasticsearch instance and the other for laravel instance. Obviously the two containers were not "talking" each other. I solved creating a network between these different container and using the local IP (172. ...) assigned to the elasticsearch one into the laravel instance. Now it works perfectly.

ezimuel commented 2 years ago

OK, I'm glad that you solved, it was a connection issue. I'm closing the issue.