PHP Backend Application(三)Solr MySQL Cache
PHP Backend Application(3)Solr MySQL Cache
PHP Backend Application(3)Solr MySQL Cache
1 Solr
First of all, add the dependency.
> ./composer.phar require solarium/solarium
Clean all SOLR documents
http://xxx.xxx.xxx.xxx:8983/job/update?stream.body=%3Cdelete%3E%3Cquery%3E*:*%3C/query%3E%3C/delete%3E&commit=true
Set up Indexer
https://sillycat.atlassian.net/wiki/display/EN/Deploy+a+New+Indexer
SolrSearchClient.php to support adding documents to Solr Server
<?php
namespace JobConsumerPHP;
require __DIR__.'/../../vendor/autoload.php';
use \Solarium\Client;
use \Solarium\Exception;
class SolrSearchClient
{
protected $client = null;
protected $ioc = null;
public function __construct($ioc){
$this->ioc = $ioc;
$this->client = new Client(
array(
'endpoint' => array(
'localhost' => array(
'host' => ‘xxx.xxx.xxx.xxx',
'port' => 8983,
'path' => '/job',
)
)
)
);
}
public function ping()
{
//set up features needed for this method
$logger = $this->ioc->getService("logger");
//create a ping query
$ping = $this->client->createPing();
//execute the ping query
try {
$result = $this->client->ping($ping);
$logger->debug("Ping query successful-----");
$logger->debug(var_export($result->getData(), true));
$logger->debug("--------------------------");
} catch (Exception $e){
$logger->error("Ping query failed: " . $e);
}
}
public function addJobDocument($job, $commit)
{
//set up features needed for this method
$logger = $this->ioc->getService("logger");
//get an update query instance
$update = $this->client->createUpdate();
//create a new document for the data
$doc = $update->createDocument();
$logger->debug("addJobDocument-----------------");
while(list($key, $value) = each($job))
{
if(is_array($value)){
//array
$logger->debug("$key => " . var_export($value, true));
}else{
//string
$logger->debug("$key => $value ");
}
$doc->addField($key, $value);
}
$logger->debug("-------------------------------");
try{
$update->addDocuments(array($doc));
if($commit)
{
$update->addCommit();
$logger->debug("committing during add documents.");
}else{
$logger->debug("NOT committing during add documents.");
}
$result = $this->client->update($update);
$logger->debug("Update query executed---------");
$logger->debug("Query status: " . $result->getStatus());
$logger->debug("Query time: " . $result->getQueryTime());
} catch (Exception $e){
$logger->error("Add document failed: " . $e);
}
}
public function deleteDocument($jobID)
{
//set up features needed for this method
$logger = $this->ioc->getService("logger");
//get an update query instance
$update = $this->client->createUpdate();
//add the delete query and a commit command to the update query
$update->addDeleteQuery("id:".$jobID);
$update->addCommit();
//this executes the query and returns the result
$result = $this->client->update($update);
$logger->debug("Update query executed---------------");
$logger->debug("Query status: " . $result->getStatus());
$logger->debug("Query time: " . $result->getQueryTime());
$logger->debug("------------------------------------");
}
}
?>
Test Case for that Base Class, SolrSearchClientTest.php
<?php
use \JobConsumerPHP\IOCUtil;
class SolrSearchClientTest extends PHPUnit_Framework_TestCase
{
protected $solrSearchClient;
protected function setUp()
{
$ioc = new IOCUtil();
$this->solrSearchClient = $ioc->getService("solrSearchClient");
}
public function testDummy()
{
$this->assertTrue(true);
}
public function testPing()
{
$this->solrSearchClient->ping();
}
public function testAddJobDocument()
{
$jobProperties = array(
"id" => "id2", //required
"customer_id" => 1, //required
"pool_id" => 1, //required
"source_id" => 1, //required
"url" => "http://url1",
"company_id" => 1,
"state_id" => array(
1,
2,
),
"zipcode" => array(
78729,
78749,
),
"cpc" => 12,
"reg_cpc" => 10,
"posted" => "2016-06-23T22:00:00Z",
"created" => "2016-05-23T22:00:00Z",
"experience" => 1,
"salary" => 1,
"education" => 1,
"jobtype" => 1,
"industry" => 1, //main industry
"industries" => array(
1,
2,
), //list of industries
"quality_score" => 1.0,
"boost_factor" => 1.0,
"paused" => false,
"budget" => 100,
..snip...
);
$this->solrSearchClient->addJobDocument($jobProperties, true);
}
public function testDeleteDocument()
{
$jobID = "id2";
$this->solrSearchClient->deleteDocument($jobID);
}
}
?>
2 MySQL
MySQLi
http://stackoverflow.com/questions/39753/connection-pooling-in-php
It seems that there is no connection pool in PHP. mysql_pconnect is different.
http://codular.com/php-mysqli
http://cuiqingcai.com/1534.html
http://tao1848.blog.51cto.com/895768/196653
http://www.phpthinking.com/archives/1296
MySQLi Base Class to connect to 3 different DB, MySQLDAO.php
<?php
namespace JobConsumerPHP;
require __DIR__.'/../../vendor/autoload.php';
class MySQLDAO
{
//job DB info
protected $jobDBHost = null;
protected $jobDBName = null;
protected $jobDBUser = null;
protected $jobDBPassword = null;
//stats DB info
protected $statsDBHost = null;
protected $statsDBName = null;
protected $statsDBUser = null;
protected $statsDBPassword = null;
//core DB info
protected $coreDBHost = null;
protected $coreDBName = null;
protected $coreDBUser = null;
protected $coreDBPassword = null;
protected $ioc = null;
public function __construct($ioc){
$this->ioc = $ioc;
$logger = $this->ioc->getService("logger");
$config = $this->ioc->getService("config");
$this->jobDBHost = $config['jobDBHost'];
$this->jobDBName = $config['jobDBName'];
$this->jobDBUser = $config['jobDBUser'];
$this->jobDBPassword = $config['jobDBPassword'];
$this->statsDBHost = $config['statsDBHost'];
$this->statsDBName = $config['statsDBName'];
$this->statsDBUser = $config['statsDBUser'];
$this->statsDBPassword = $config['statsDBPassword'];
$this->coreDBHost = $config['coreDBHost'];
$this->coreDBName = $config['coreDBName'];
$this->coreDBUser = $config['coreDBUser'];
$this->coreDBPassword = $config['coreDBPassword'];
$logger->info("==============MySQL config start ==============");
$logger->info("jobDBHost = " . $this->jobDBHost);
$logger->info("jobDBName = " . $this->jobDBName);
$logger->info("jobDBUser = " . $this->jobDBUser);
$logger->info("jobDBPassword = " . $this->jobDBPassword);
$logger->info("===============================================");
$logger->info("statsDBHost = " . $this->statsDBHost);
$logger->info("statsDBName = " . $this->statsDBName);
$logger->info("statsDBUser = " . $this->statsDBUser);
$logger->info("statsDBPassword = " . $this->statsDBPassword);
$logger->info("===============================================");
$logger->info("coreDBHost = " . $this->coreDBHost);
$logger->info("coreDBName = " . $this->coreDBName);
$logger->info("coreDBUser = " . $this->coreDBUser);
$logger->info("coreDBPassword = " . $this->coreDBPassword);
}
public function getJobSourceInfoBySourceID($sourceID)
{
$query = "
SELECT
job_sources.id,
..snip...
job_pools.acct_mgr_id
FROM
job_sources
JOIN job_pools ON pool_id = job_pools.id
JOIN job_customers ON job_customers.id = job_customer_id
WHERE
job_sources.id = ? AND
status = 1
";
$conn = $this->getJobDBConn();
$stmt = $conn->prepare($query);
$stmt->bind_param("i", $sourceID);
$stmt->execute();
$result = $stmt->get_result();
//$data = $result->fetch_all(MYSQLI_ASSOC);
//just fetch the first row;
$data = $result->fetch_assoc();
$this->closeDBConn($conn);
return $data;
}
private function closeDBConn($conn)
{
mysqli_close($conn);
}
private function getDBConn($dbHost, $dbName, $dbUser, $dbPass, $dbAlis)
{
$logger = $this->ioc->getService("logger");
$conn = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName);
if(!$conn)
{
$logger->error("Fail to connect ". $dbAlis ." DB---------");
$logger->error($dbAlis . " DBHost = " . $dbHost);
$logger->error($dbAlis . " DBName = " . $dbName);
$logger->error($dbAlis . " DBUser = " . $dbUser);
$logger->error($dbAlis . " DBPassword = " . $dbPass);
}
return $conn;
}
private function getJobDBConn()
{
return $this->getDBConn($this->jobDBHost, $this->jobDBName, $this->jobDBUser, $this->jobDBPassword, "JOB");
}
private function getStatsDBconn()
{
return $this->getDBConn($this->statsDBHost, $this->statsDBName, $this->statsDBUser, $this->statsDBPassword, "STATS");
}
private function getCoreDBConn()
{
return $this->getDBConn($this->coreDBHost, $this->coreDBName, $this->coreDBUser, $this->coreDBPassword, "CORE");
}
}
?>
Test the MySQL Base class, MySQLDAOTest.php
<?php
use \JobConsumerPHP\IOCUtil;
class MySQLDAOTest extends PHPUnit_Framework_TestCase
{
protected $mySQLDAO;
protected function setUp()
{
$ioc = new IOCUtil();
$this->mySQLDAO = $ioc->getService("mySQLDAO");
}
public function testDummy()
{
$this->assertTrue(true);
}
public function testGetJobSourceInfoBySourceID()
{
$result = $this->mySQLDAO->getJobSourceInfoBySourceID(790);
$this->assertNotEmpty($result);
}
}
?>
3 Cache System
https://github.com/gilbitron/PHP-SimpleCache
http://www.phpfastcache.com/
https://github.com/PHPSocialNetwork/phpfastcache/wiki
Redis for that
https://github.com/PHPSocialNetwork/phpfastcache/blob/final/examples/predis.php
> composer require phpFastCache/phpFastCache
The Cache Base Class, FastCache.php
<?php
namespace JobConsumerPHP;
require __DIR__.'/../../vendor/autoload.php';
use \phpFastCache\CacheManager;
class FastCache
{
protected $cache = null;
protected $ioc = null;
public function __construct($ioc){
$this->ioc = $ioc;
$logger = $this->ioc->getService("logger");
$config = $this->ioc->getService("config");
$logger->info("==============FastCache config start ==========");
$logger->info("redisHost = " . $config['redisHost']);
$logger->info("redisPort = " . $config['redisPort']);
$logger->info("===============================================");
try {
CacheManager::setup(array(
'redis' => array(
'host' => $config['redisHost'],
'port' => $config['redisPort'],
//'password' => '',
//'database' => '',
//'time' => '',
),
));
$this->cache = CacheManager::getInstance('predis');
$logger->debug("Successfully connected to Redis and build Cache");
} catch (Exception $e) {
$logger->error("Couldn't connected to Redis");
$logger->error($e->getMessage());
}
}
public function getCache()
{
return $this->cache;
}
}
?>
Test Case class for that, FastCacheTest.php
<?php
use \JobConsumerPHP\IOCUtil;
class FastCacheTest extends PHPUnit_Framework_TestCase
{
protected $fastCache;
protected function setUp()
{
$ioc = new IOCUtil();
$this->fastCache = $ioc->getService("fastCache");
}
public function testDummy()
{
$this->assertTrue(true);
}
public function testCacheAndFetch()
{
$key = "cache_key1";
$value = "cache_value1";
//seconds
$this->fastCache->getCache()->set($key, $value, 2);
$result1 = $this->fastCache->getCache()->get($key);
$this->assertEquals($value, $result1);
sleep(3);
$result2 = $this->fastCache->getCache()->get($key);
$this->assertEmpty($result2);
}
}
References:
http://www.solarium-project.org/
http://solarium.readthedocs.io/en/stable/getting-started/
http://solarium.readthedocs.io/en/stable/getting-started/#adding-documents
https://gist.github.com/basdenooijer/894286
PHP Backend Application(3)Solr MySQL Cache
1 Solr
First of all, add the dependency.
> ./composer.phar require solarium/solarium
Clean all SOLR documents
http://xxx.xxx.xxx.xxx:8983/job/update?stream.body=%3Cdelete%3E%3Cquery%3E*:*%3C/query%3E%3C/delete%3E&commit=true
Set up Indexer
https://sillycat.atlassian.net/wiki/display/EN/Deploy+a+New+Indexer
SolrSearchClient.php to support adding documents to Solr Server
<?php
namespace JobConsumerPHP;
require __DIR__.'/../../vendor/autoload.php';
use \Solarium\Client;
use \Solarium\Exception;
class SolrSearchClient
{
protected $client = null;
protected $ioc = null;
public function __construct($ioc){
$this->ioc = $ioc;
$this->client = new Client(
array(
'endpoint' => array(
'localhost' => array(
'host' => ‘xxx.xxx.xxx.xxx',
'port' => 8983,
'path' => '/job',
)
)
)
);
}
public function ping()
{
//set up features needed for this method
$logger = $this->ioc->getService("logger");
//create a ping query
$ping = $this->client->createPing();
//execute the ping query
try {
$result = $this->client->ping($ping);
$logger->debug("Ping query successful-----");
$logger->debug(var_export($result->getData(), true));
$logger->debug("--------------------------");
} catch (Exception $e){
$logger->error("Ping query failed: " . $e);
}
}
public function addJobDocument($job, $commit)
{
//set up features needed for this method
$logger = $this->ioc->getService("logger");
//get an update query instance
$update = $this->client->createUpdate();
//create a new document for the data
$doc = $update->createDocument();
$logger->debug("addJobDocument-----------------");
while(list($key, $value) = each($job))
{
if(is_array($value)){
//array
$logger->debug("$key => " . var_export($value, true));
}else{
//string
$logger->debug("$key => $value ");
}
$doc->addField($key, $value);
}
$logger->debug("-------------------------------");
try{
$update->addDocuments(array($doc));
if($commit)
{
$update->addCommit();
$logger->debug("committing during add documents.");
}else{
$logger->debug("NOT committing during add documents.");
}
$result = $this->client->update($update);
$logger->debug("Update query executed---------");
$logger->debug("Query status: " . $result->getStatus());
$logger->debug("Query time: " . $result->getQueryTime());
} catch (Exception $e){
$logger->error("Add document failed: " . $e);
}
}
public function deleteDocument($jobID)
{
//set up features needed for this method
$logger = $this->ioc->getService("logger");
//get an update query instance
$update = $this->client->createUpdate();
//add the delete query and a commit command to the update query
$update->addDeleteQuery("id:".$jobID);
$update->addCommit();
//this executes the query and returns the result
$result = $this->client->update($update);
$logger->debug("Update query executed---------------");
$logger->debug("Query status: " . $result->getStatus());
$logger->debug("Query time: " . $result->getQueryTime());
$logger->debug("------------------------------------");
}
}
?>
Test Case for that Base Class, SolrSearchClientTest.php
<?php
use \JobConsumerPHP\IOCUtil;
class SolrSearchClientTest extends PHPUnit_Framework_TestCase
{
protected $solrSearchClient;
protected function setUp()
{
$ioc = new IOCUtil();
$this->solrSearchClient = $ioc->getService("solrSearchClient");
}
public function testDummy()
{
$this->assertTrue(true);
}
public function testPing()
{
$this->solrSearchClient->ping();
}
public function testAddJobDocument()
{
$jobProperties = array(
"id" => "id2", //required
"customer_id" => 1, //required
"pool_id" => 1, //required
"source_id" => 1, //required
"url" => "http://url1",
"company_id" => 1,
"state_id" => array(
1,
2,
),
"zipcode" => array(
78729,
78749,
),
"cpc" => 12,
"reg_cpc" => 10,
"posted" => "2016-06-23T22:00:00Z",
"created" => "2016-05-23T22:00:00Z",
"experience" => 1,
"salary" => 1,
"education" => 1,
"jobtype" => 1,
"industry" => 1, //main industry
"industries" => array(
1,
2,
), //list of industries
"quality_score" => 1.0,
"boost_factor" => 1.0,
"paused" => false,
"budget" => 100,
..snip...
);
$this->solrSearchClient->addJobDocument($jobProperties, true);
}
public function testDeleteDocument()
{
$jobID = "id2";
$this->solrSearchClient->deleteDocument($jobID);
}
}
?>
2 MySQL
MySQLi
http://stackoverflow.com/questions/39753/connection-pooling-in-php
It seems that there is no connection pool in PHP. mysql_pconnect is different.
http://codular.com/php-mysqli
http://cuiqingcai.com/1534.html
http://tao1848.blog.51cto.com/895768/196653
http://www.phpthinking.com/archives/1296
MySQLi Base Class to connect to 3 different DB, MySQLDAO.php
<?php
namespace JobConsumerPHP;
require __DIR__.'/../../vendor/autoload.php';
class MySQLDAO
{
//job DB info
protected $jobDBHost = null;
protected $jobDBName = null;
protected $jobDBUser = null;
protected $jobDBPassword = null;
//stats DB info
protected $statsDBHost = null;
protected $statsDBName = null;
protected $statsDBUser = null;
protected $statsDBPassword = null;
//core DB info
protected $coreDBHost = null;
protected $coreDBName = null;
protected $coreDBUser = null;
protected $coreDBPassword = null;
protected $ioc = null;
public function __construct($ioc){
$this->ioc = $ioc;
$logger = $this->ioc->getService("logger");
$config = $this->ioc->getService("config");
$this->jobDBHost = $config['jobDBHost'];
$this->jobDBName = $config['jobDBName'];
$this->jobDBUser = $config['jobDBUser'];
$this->jobDBPassword = $config['jobDBPassword'];
$this->statsDBHost = $config['statsDBHost'];
$this->statsDBName = $config['statsDBName'];
$this->statsDBUser = $config['statsDBUser'];
$this->statsDBPassword = $config['statsDBPassword'];
$this->coreDBHost = $config['coreDBHost'];
$this->coreDBName = $config['coreDBName'];
$this->coreDBUser = $config['coreDBUser'];
$this->coreDBPassword = $config['coreDBPassword'];
$logger->info("==============MySQL config start ==============");
$logger->info("jobDBHost = " . $this->jobDBHost);
$logger->info("jobDBName = " . $this->jobDBName);
$logger->info("jobDBUser = " . $this->jobDBUser);
$logger->info("jobDBPassword = " . $this->jobDBPassword);
$logger->info("===============================================");
$logger->info("statsDBHost = " . $this->statsDBHost);
$logger->info("statsDBName = " . $this->statsDBName);
$logger->info("statsDBUser = " . $this->statsDBUser);
$logger->info("statsDBPassword = " . $this->statsDBPassword);
$logger->info("===============================================");
$logger->info("coreDBHost = " . $this->coreDBHost);
$logger->info("coreDBName = " . $this->coreDBName);
$logger->info("coreDBUser = " . $this->coreDBUser);
$logger->info("coreDBPassword = " . $this->coreDBPassword);
}
public function getJobSourceInfoBySourceID($sourceID)
{
$query = "
SELECT
job_sources.id,
..snip...
job_pools.acct_mgr_id
FROM
job_sources
JOIN job_pools ON pool_id = job_pools.id
JOIN job_customers ON job_customers.id = job_customer_id
WHERE
job_sources.id = ? AND
status = 1
";
$conn = $this->getJobDBConn();
$stmt = $conn->prepare($query);
$stmt->bind_param("i", $sourceID);
$stmt->execute();
$result = $stmt->get_result();
//$data = $result->fetch_all(MYSQLI_ASSOC);
//just fetch the first row;
$data = $result->fetch_assoc();
$this->closeDBConn($conn);
return $data;
}
private function closeDBConn($conn)
{
mysqli_close($conn);
}
private function getDBConn($dbHost, $dbName, $dbUser, $dbPass, $dbAlis)
{
$logger = $this->ioc->getService("logger");
$conn = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName);
if(!$conn)
{
$logger->error("Fail to connect ". $dbAlis ." DB---------");
$logger->error($dbAlis . " DBHost = " . $dbHost);
$logger->error($dbAlis . " DBName = " . $dbName);
$logger->error($dbAlis . " DBUser = " . $dbUser);
$logger->error($dbAlis . " DBPassword = " . $dbPass);
}
return $conn;
}
private function getJobDBConn()
{
return $this->getDBConn($this->jobDBHost, $this->jobDBName, $this->jobDBUser, $this->jobDBPassword, "JOB");
}
private function getStatsDBconn()
{
return $this->getDBConn($this->statsDBHost, $this->statsDBName, $this->statsDBUser, $this->statsDBPassword, "STATS");
}
private function getCoreDBConn()
{
return $this->getDBConn($this->coreDBHost, $this->coreDBName, $this->coreDBUser, $this->coreDBPassword, "CORE");
}
}
?>
Test the MySQL Base class, MySQLDAOTest.php
<?php
use \JobConsumerPHP\IOCUtil;
class MySQLDAOTest extends PHPUnit_Framework_TestCase
{
protected $mySQLDAO;
protected function setUp()
{
$ioc = new IOCUtil();
$this->mySQLDAO = $ioc->getService("mySQLDAO");
}
public function testDummy()
{
$this->assertTrue(true);
}
public function testGetJobSourceInfoBySourceID()
{
$result = $this->mySQLDAO->getJobSourceInfoBySourceID(790);
$this->assertNotEmpty($result);
}
}
?>
3 Cache System
https://github.com/gilbitron/PHP-SimpleCache
http://www.phpfastcache.com/
https://github.com/PHPSocialNetwork/phpfastcache/wiki
Redis for that
https://github.com/PHPSocialNetwork/phpfastcache/blob/final/examples/predis.php
> composer require phpFastCache/phpFastCache
The Cache Base Class, FastCache.php
<?php
namespace JobConsumerPHP;
require __DIR__.'/../../vendor/autoload.php';
use \phpFastCache\CacheManager;
class FastCache
{
protected $cache = null;
protected $ioc = null;
public function __construct($ioc){
$this->ioc = $ioc;
$logger = $this->ioc->getService("logger");
$config = $this->ioc->getService("config");
$logger->info("==============FastCache config start ==========");
$logger->info("redisHost = " . $config['redisHost']);
$logger->info("redisPort = " . $config['redisPort']);
$logger->info("===============================================");
try {
CacheManager::setup(array(
'redis' => array(
'host' => $config['redisHost'],
'port' => $config['redisPort'],
//'password' => '',
//'database' => '',
//'time' => '',
),
));
$this->cache = CacheManager::getInstance('predis');
$logger->debug("Successfully connected to Redis and build Cache");
} catch (Exception $e) {
$logger->error("Couldn't connected to Redis");
$logger->error($e->getMessage());
}
}
public function getCache()
{
return $this->cache;
}
}
?>
Test Case class for that, FastCacheTest.php
<?php
use \JobConsumerPHP\IOCUtil;
class FastCacheTest extends PHPUnit_Framework_TestCase
{
protected $fastCache;
protected function setUp()
{
$ioc = new IOCUtil();
$this->fastCache = $ioc->getService("fastCache");
}
public function testDummy()
{
$this->assertTrue(true);
}
public function testCacheAndFetch()
{
$key = "cache_key1";
$value = "cache_value1";
//seconds
$this->fastCache->getCache()->set($key, $value, 2);
$result1 = $this->fastCache->getCache()->get($key);
$this->assertEquals($value, $result1);
sleep(3);
$result2 = $this->fastCache->getCache()->get($key);
$this->assertEmpty($result2);
}
}
References:
http://www.solarium-project.org/
http://solarium.readthedocs.io/en/stable/getting-started/
http://solarium.readthedocs.io/en/stable/getting-started/#adding-documents
https://gist.github.com/basdenooijer/894286