Php session module does not utilize shared memory segment for tracking cluster status

#1

I ran some tests on the default aerospike session handler and noticed that the number of connections go up substantially whenever I enable sessions (as opposed to my typicaly usage scenario of a simple LRU cache). Testing things out showed that the session handler does not respect/use aerospike.shm* Is that the expected behavior? This is for the php5 module (dealing with mostly older code currently) - have not gotten to testing php7 version yet.

#2

Long story short… the native aerospike session handler does not support shm feature to minimize connections (for php5 module at least - will report back if php7 module has same problem when I cross that bridge shortly). The work around is to not use the internal aerospike session handler - you can write your own though pretty easily that does use aerospoike for storage with shared memory cluster tending…

class as_session implements SessionHandlerInterface {

private $aerospike = NULL;
private $hosts = array('hosts' => array(array('addr' => '127.0.0.1', 'port' => 3000)));
private $persistent = TRUE; // not even sure we should make this an option - should always be true
private $as_namespace = 'namespace_name';
private $as_set = 'session';
private $as_bin = 'data';
private $ttl = 3600; // could be set via ini_get('session.gc_maxlifetime'); but we avoid unecessary call this way
private $compress = NULL; // TRUE/FALSE/NULL - NULL means auto-compress based on threshold size
private $compress_threshold = 960000; // don't bother compressing values this many bytes or lower

public function __construct($p = array()) {
    
    require_once 'Aerospike/Bytes.php';
    foreach ($p as $k => $v) {         
                                       
        $this->$k = $v;                
                                       
    }
    $this->aerospike = new Aerospike($this->hosts, $this->persistent);
    // NOTE: do not throw exception on failed connect - rely on open() returning false
    //if (!$aerospike->isConnected()) {
    //    
    //     throw new Exception("Aerospike failed to connect[{$aerospike->errorno()}]: {$aerospike->error()}");
    //    
    //}
    
}

public function open($sess_path, $sess_name) {
    
    return $this->aerospike->isConnected();
    
}

public function close() {

    if (!$this->persistent) {
        
        $this->client->close(); // can't think of when we would ever want to do this
        
    }
    return true;
    
}

public function read($sess_id) {
    
    $record = array();
    $status = $this->aerospike->get($this->as_key($sess_id), $record);
    var_dump($record);
    if ($status == Aerospike::OK) {
        
        $sess_data = $record['bins'][$this->as_bin];
        // $sess_data_len = strlen($sess_data);
        // if ($sess_data_len >= 18 && strcmp(substr($sess_data, 0, 2), "\x1f\x8b") === 0) {
        if (is_object($sess_data)) { // check for Aerospike\Bytes object is less overhead than checking gzip header bytes

            $sess_data = gzdecode($sess_data);
            
        }
        return $sess_data;
            
    }
    return ''; // expects ZLS if there is no hit on key
    
}

public function write($sess_id, $sess_data) {

    $compress = ($this->compress);
    if (!$compress && $this->compress === NULL && strlen($sess_data) >= $this->compress_threshold) {

        // NOTE: this tells the aerospike driver not to try and cast this to a data type
        // NOTE: compression is simply a hack to permit session data stores larger than 1MB
        $sess_data = new \Aerospike\Bytes(gzencode($sess_data));
        
    }
    $status = $this->aerospike->put($this->as_key($sess_id), [$this->as_bin => $sess_data], $this->ttl);
    return ($status == Aerospike::OK);
    
}

public function destroy($sess_id) {
    
    $status = $this->aerospike->remove($this->as_key($sess_id));
    return ($status == Aerospike::OK);
    
}

public function gc($sess_max_life) {
    
    // aerospike handles GC internally
    return true;
    
}

private function as_key($sess_id) {
    
    return $this->aerospike->initKey($this->as_namespace, $this->as_set, $sess_id);
    
}

}