Php 内存消耗优化
我在Laravel中有一个服务类,它处理与API端点的集成,以获取记录并处理它们(在数据库中创建和更新) 我多次调用Guzzle实例,因为我必须为每个公司分支使用不同的API键调用API内点 我已将内存限制更改为3000MB,但尽管如此,有时代码执行会达到该内存量,并且进程会由于内存泄漏而失败。每次调用执行后,我都会使用Php 内存消耗优化,php,laravel,optimization,guzzle,Php,Laravel,Optimization,Guzzle,我在Laravel中有一个服务类,它处理与API端点的集成,以获取记录并处理它们(在数据库中创建和更新) 我多次调用Guzzle实例,因为我必须为每个公司分支使用不同的API键调用API内点 我已将内存限制更改为3000MB,但尽管如此,有时代码执行会达到该内存量,并且进程会由于内存泄漏而失败。每次调用执行后,我都会使用memory\u get\u usage()获取内存使用情况(由于分页,我必须进行迭代) 在这个过程中有没有释放内存的方法或推荐的优化方法 代码如下: <?php nam
memory\u get\u usage()
获取内存使用情况(由于分页,我必须进行迭代)
在这个过程中有没有释放内存的方法或推荐的优化方法
代码如下:
<?php
namespace App\Services;
use App\PropertyIntegration;
use GuzzleHttp\Client;
use App\Property;
use App\Integration;
use Carbon\Carbon;
use App\Exception;
use App\Transformation;
use App\Organization;
use Illuminate\Support\Arr;
class IntegrationService {
private $_verbose;
private $_client;
private $_integration;
private $_notifier;
private $_config;
private $_start_time;
/***************************************************************************************************
1) First step - Gets data for Guzzle Client
****************************************************************************************************/
public function firststep() {
$organizations = Organization::where('org_status', 'Activo')->get();
foreach ($organizations as $organization) {
$megaagents = $organization->megaagents()->where('megaagent_status', 'Activo')
->whereNotNull('megaagent_api_key')
->get();
$marketcenters = $organization->marketcenters()->where('mc_status', 'Activo')
->whereNotNull('mc_api_key')
->get();
// PASS DATA TO GUZZLE
foreach ($megaagents as $megaagent) {
$this->initialize($megaagent, $ismegaagent = true);
$this->execute($megaagent, $ismegaagent = true);
}
// PASS DATA TO GUZZLE
foreach ($marketcenters as $marketcenter ) {
$this->initialize($marketcenter, $ismegaagent = false);
$this->execute($marketcenter, $ismegaagent = false);
}
}
}
/***************************************************************************************************
2) Send notification information in console verbose mode
****************************************************************************************************/
private function notify($message, $type='info') {
if($this->_verbose && $this->_notifier !== null) {
$this->_notifier->{$type}($message);
}
}
/***************************************************************************************************
3) Integrate Property API data with the Database
Initialize integration service
Fetch Properties from API Endpoint
Insert/Update properties
****************************************************************************************************/
public function execute ($record, $ismegaagent) {
$properties = [];
$query = [];
if($ismegaagent) {
$apikey = $record->megaagent_api_key;
} else {
$apikey = $record->mc_api_key;
}
$request = 'http://url .$apikey ;
if($ismegaagent) {
$this->notify('====================================================================================================');
$this->notify('INITIALIZING INTEGRATION CREATE/UPDATE -> MEGA AGENT: ' . strtoupper($record->megaagent_name));
$this->notify('====================================================================================================');
} else {
$this->notify('====================================================================================================');
$this->notify('INITIALIZING INTEGRATION CREATE/UPDATE -> MARKET CENTER: ' . strtoupper($record->mc_name));
$this->notify('====================================================================================================');
}
$response = [
'int_properties_sent' => 0,
'int_properties_success' => 0,
'int_properties_updated' => 0,
'int_properties_failed' => 0,
'int_properties_ignored' => 0
];
// CREATES GUZZLE INSTANCE
$this->_client = new Client([
'base_uri' => $this->_config['base_uri']
]);
$pageNumber = 0;
$retry = 0;
$next = true;
while ($next) {
try {
$this->notify('Fetching Properties For Page: ' . ++$pageNumber);
$data = null;
$data = $this->getProperties($request, $pageNumber);
if(is_array($data['objects'])) {
$this->notify('Processing Properties For Page: ' . $pageNumber);
$this->notify('TOTAL PROPERTIES: ' .$data['meta']['total_count']);
$totalproperties = count($data['objects']);
$this->notify('TOTAL PROPERTIES IN PAGE: ' .$totalproperties);
$result = $this->processProperties($data['objects'], $record, $ismegaagent);
$response['int_properties_sent'] += count($data['objects']);
$response['int_properties_success'] += $result['success'];
$response['int_properties_updated'] += $result['updated'];
$response['int_properties_ignored'] += $result['ignored'];
$response['int_properties_failed'] += $result['failed'];
}
$next = $data['meta']['next'];
if($next !== false) {
$request = 'url'.$next;
} else {
$this->notify('Last Page Proccesed: ' . $pageNumber);
}
$retry = 0;
} catch (\Exception $ex) {
// Handle the exception
if($retry < 3) {
--$pageNumber;
$retry++;
$this->notify('Error fetching properties. Retrying...', 'error');
sleep(10);
} else {
$this->notify('Aborting Property Integration! Error: ' . $ex->getMessage(), 'error');
break;
}
}
}
$this->notify('======================================================================================');
$response['int_time_elapsed'] = $this->_start_time->diffInMinutes(Carbon::now());
$this->_integration->fill($response)->save();
$this->notify('Integration Completed: ' .
$response['int_properties_success'] .
' Properties integrated successfully from ' .
$response['int_properties_sent'] .
' sent');
return $response;
$this->notify('======================================================================================');
}
/***************************************************************************************************
4) Fetch property from the API Endpoint
****************************************************************************************************/
private function getProperties($request, $pageNumber = 1) {
$response = $this->_client->get($request, ['decode_content' => false]);
echo 'Memory in use: ' . memory_get_usage() . ' ('. round(((memory_get_usage() / 1024) / 1024)) .'M)' . "\n";
usleep(20000);
if($response->getStatusCode() == 200) {
$body = $response->getBody()->getContents();
$data = json_decode($body, true);
// return $data['objects'];
return $data;
} else {
throw new \Exception($response->getReasonPhrase(), 1);
}
}
/***************************************************************************************************
5) Store property information in Database
If property does not already exists in database then insert
else if the property modification date is different update property
****************************************************************************************************/
private function processProperties($properties, $record, $ismegaagent) {
$dbPropertiesCollection = Property::get(['prop_id', 'updated_at']);
$dbProperties = $dbPropertiesCollection->mapWithKeys(function ($item) {
return [$item['prop_id'] => $item['updated_at']];
})->toArray();
$success = 0;
$updated = 0;
$failed = 0;
$ignored = 0;
foreach ($properties as $property) {
try {
if(!array_key_exists('KWT'.$property['id'], $dbProperties) && ($property['status'] == 3 || $property['status'] == 4 || $property['status'] == 2)) {
$inserted = Property::storeTokkoProperty($property, $record, $ismegaagent);
if($inserted) {
$this->notify('INSERT: Property ' . 'KWT'.$property['id'] . ' does not exists, Inserting Property');
$success++;
} else {
$this->notify('FAILED: Property ' . 'KWT'.$property['id'] . ' review expections');
}
} elseif ($property['status'] == 3 || $property['status'] == 4 || $property['status'] == 2) {
$dbModification = Carbon::createFromFormat('Y-m-d H:i:s', $dbProperties['KWT'.$property['id']]);
$fechaModification = Carbon::createFromFormat('Y-m-d\TH:i:s', $property['deleted_at']);
if($fechaModification->notEqualTo($dbModification)) {
$this->notify('UPDATE: Property ' . 'KWT'.$property['id'] . ' API informs last modification date ' .$fechaModification . ' and database last modification date is ' .$dbModification);
Property::updateTokkoProperty($property, $record, $ismegaagent);
$updated++;
}
else {
$tagsUpdated = Property::reviewTokkoTags($property);
if($tagsUpdated) {
$this->notify('UPDATE: Property ' . 'KWT'.$property['id'] . ' Tags are different although modification date' .$fechaModification . ' and database last modification date is ' .$dbModification);
$updated++;
} else {
$this->notify('IGNORE: Property ' . 'KWT'.$property['id'] . ' already exists with modification date in API '. $dbModification . ' and last API modification date is ' . $fechaModification);
$ignored++;
}
}
} else {
$ignored++;
}
} catch (\Exception $ex) {
// Handle the exception
$failed++;
// Store into integration errors
$this->_integration->integrationerrors()->create([
'property_id' => 'KWT'.$property['id'],
'interror_error_message' => $ex->getMessage()
]);
$this->notify('Error: Operation failed for Property # ' . 'KWT'.$property['id'] . '. Message: ' . $ex->getMessage(), 'error');
}
}
return [
'success' => $success,
'updated' => $updated,
'failed' => $failed,
'ignored' => $ignored
];
}
}