В останньому відео на каналі про реліз PHP 8.5 я отримав коментар, мовляв шкода, що я не глибоко в темі проблеми Persistent cURL Share Handles.
І цей коментар прямо в точку. Бо останній раз я користувався саме cURL за царя Панька і тоді, я думаю, просто не відчував цієїї проблеми. Але хто я такий, щоб в тому не розібратись? Тим більше проблема досить очевидна і зрозуміла.
Тому взявся я за старий добрий гугл і почав гуглити (так-так, в чат гпт я не поліз, уявляєте? 😱).
Отже, в чому проблема?
Суть в тому, що share handle дає
1. Що взагалі робить cURL при curl_exec()
Типовий життєвий цикл одного HTTP-запиту:
1. DNS: резолв домену в IP.
2. TCP handshake: тристороннє рукостискання з сервером.
3. SSL/TLS handshake (якщо https):
- узгодження протоколів/шифрів;
- перевірка сертифіката;
- обмін ключами.
4. HTTP-запит/відповідь.
5. Що робити з сокетом після відповіді?
- або закрити (Connection: close),
- або залишити відкритим (HTTP keep-alive, HTTP/2/3 multiplex).
2. Що саме кешує libcurl
1. DNS-cache
- Відповідність host:port → IP на деякий час (TTL).
- Якщо є валідний запис, DNS-запит не робиться.
2. Connection cache (пул з’єднань)
- Відкриті TCP (і TLS) з’єднання, які ще не закриті сервером.
- Ключ — приблизно: scheme + host + port + proxy + TLS-параметри + користувач/пароль/….
- Якщо знайдено підходяще з’єднання – HTTP-запит просто відправляється поверх вже відкритого сокета.
3. SSL session cache
- SSL-сесії (session ID / session ticket), які дозволяють скорочений handshake при відкритті нового TLS-з’єднання до того ж сервера.
DNS + TCP + SSL — це найдорожча частина. І
3. Навіщо потрібен share handle
За замовчуванням кожен
Тобто:
Що відбувається:
- CURL_LOCK_DATA_DNS – ch1 і ch2 користуються одним і тим самим DNS-кешем.
- CURL_LOCK_DATA_CONNECT (якщо підтримується) – ділять пул з’єднань.
- Можна також шарити cookies, SSL-сесії тощо.
Головна відмінність: у PHP 8.5 з’явився справді персистентний cURL Share Handle
У PHP ≤ 8.4 будь-який share handle жив лише в межах одного HTTP-запиту.
Після завершення запиту PHP-процес очищував пам’ять, і:
- DNS cache — зникав
- Connection cache — зникав
- SSL session cache — зникав
Тому реального повторного використання TCP/TLS з’єднань між запитами не було.
PHP 8.5: `curl_share_init_persistent()`
Це вперше дозволяє створити глобальний
- не знищується після завершення PHP-запиту
- зберігає DNS cache, connection cache та SSL session cache в памʼяті FPM-процесу
- автоматично повторно використовується іншими PHP-скриптами, якщо ті самі опції шарингу
Детальніше про все це я описав у KRUHLYK Pro, тому якщо вам цікаво про це дізнатись глибше - велкам в наш закритий канал!
І цей коментар прямо в точку. Бо останній раз я користувався саме cURL за царя Панька і тоді, я думаю, просто не відчував цієїї проблеми. Але хто я такий, щоб в тому не розібратись? Тим більше проблема досить очевидна і зрозуміла.
Тому взявся я за старий добрий гугл і почав гуглити (так-так, в чат гпт я не поліз, уявляєте? 😱).
Отже, в чому проблема?
Суть в тому, що share handle дає
libcurl спільний кеш (DNS, конекшени, SSL-сесії), і коли є підходяще живе з’єднання в цьому кеші – libcurl просто шле новий HTTP-запит по вже відкритому сокету, а не будує все з нуля.1. Що взагалі робить cURL при curl_exec()
Типовий життєвий цикл одного HTTP-запиту:
1. DNS: резолв домену в IP.
2. TCP handshake: тристороннє рукостискання з сервером.
3. SSL/TLS handshake (якщо https):
- узгодження протоколів/шифрів;
- перевірка сертифіката;
- обмін ключами.
4. HTTP-запит/відповідь.
5. Що робити з сокетом після відповіді?
- або закрити (Connection: close),
- або залишити відкритим (HTTP keep-alive, HTTP/2/3 multiplex).
2. Що саме кешує libcurl
Libcurl має кілька внутрішніх кешів:1. DNS-cache
- Відповідність host:port → IP на деякий час (TTL).
- Якщо є валідний запис, DNS-запит не робиться.
2. Connection cache (пул з’єднань)
- Відкриті TCP (і TLS) з’єднання, які ще не закриті сервером.
- Ключ — приблизно: scheme + host + port + proxy + TLS-параметри + користувач/пароль/….
- Якщо знайдено підходяще з’єднання – HTTP-запит просто відправляється поверх вже відкритого сокета.
3. SSL session cache
- SSL-сесії (session ID / session ticket), які дозволяють скорочений handshake при відкритті нового TLS-з’єднання до того ж сервера.
DNS + TCP + SSL — це найдорожча частина. І
libcurl дуже старається їх не повторювати, якщо може.3. Навіщо потрібен share handle
За замовчуванням кожен
curl_init() має свій окремий DNS-кеш і пул з’єднань.Тобто:
$ch1 = curl_init('https://example.com');
curl_exec($ch1); // створює свій DNS cache + connection cache
$ch2 = curl_init('https://example.com');
curl_exec($ch2); // знову робить DNS, новий TCP/TLS, свій cachecurl_share_init() + curl_share_setopt() дозволяють декільком easy-handle’ам ділити один і той самий кеш. Наприклад:$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); // якщо доступно у твоїй версії PHP/libcurl
$ch1 = curl_init('https://example.com');
curl_setopt($ch1, CURLOPT_SHARE, $sh);
$ch2 = curl_init('https://example.com');
curl_setopt($ch2, CURLOPT_SHARE, $sh);
Що відбувається:
- CURL_LOCK_DATA_DNS – ch1 і ch2 користуються одним і тим самим DNS-кешем.
- CURL_LOCK_DATA_CONNECT (якщо підтримується) – ділять пул з’єднань.
- Можна також шарити cookies, SSL-сесії тощо.
Головна відмінність: у PHP 8.5 з’явився справді персистентний cURL Share Handle
У PHP ≤ 8.4 будь-який share handle жив лише в межах одного HTTP-запиту.
Після завершення запиту PHP-процес очищував пам’ять, і:
- DNS cache — зникав
- Connection cache — зникав
- SSL session cache — зникав
Тому реального повторного використання TCP/TLS з’єднань між запитами не було.
PHP 8.5: `curl_share_init_persistent()`
Це вперше дозволяє створити глобальний
persistent share handle, який:- не знищується після завершення PHP-запиту
- зберігає DNS cache, connection cache та SSL session cache в памʼяті FPM-процесу
- автоматично повторно використовується іншими PHP-скриптами, якщо ті самі опції шарингу
Детальніше про все це я описав у KRUHLYK Pro, тому якщо вам цікаво про це дізнатись глибше - велкам в наш закритий канал!
🔥6❤2
Добрий раночок, спільното! Маю надію, що всі мають смачну кавусю і чудовий настрій на робочий день! ☕️
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝6
А тим часом не Laravelʼом єдиним.
Sumfony готує в реліз нову версію 7.4.
З цікавого для мене є те, що симфа і далі бере зручні речі з ларки.
Цього разу з заявлених нововведень - це відхід від конфігів через XML формат (він тепер deprecated) та те, що конфіги в симфі замінюють fluent PHP підхід на array-based формат.
Коли є конкуренція і розробники голосують своїм вибором - ми отримуємо тільки краще.
Детальніше про оновлення тут.
Sumfony готує в реліз нову версію 7.4.
З цікавого для мене є те, що симфа і далі бере зручні речі з ларки.
Цього разу з заявлених нововведень - це відхід від конфігів через XML формат (він тепер deprecated) та те, що конфіги в симфі замінюють fluent PHP підхід на array-based формат.
Коли є конкуренція і розробники голосують своїм вибором - ми отримуємо тільки краще.
Детальніше про оновлення тут.
🔥7
#думкивголос
Працюючи зі своїми менті на менторських сесіях все частіше ловлю себе на думках, що на початках свого розвитку як розробника та й навіть з величезним досвідом за плечима ми або не до кінця розуміємо з чим ми працюємо.
А насправді все досить просто, якщо спуститись на декілька рівнів нижче у сприйнятті задач.
Ми працюємо з даними. Беремо їх з вхідних джерел чи генеруємо ці дані самі — не важливо. Ми працюємо з даними, які якось оброблюємо, у щось трансформуємо, десь зберігаємо та модіфіковану (чи ні) версію цих даних передаємо кудись далі.
А для доставки цих даних між різними шарами оброки їх ми і використовуємо оті всі патерни, про які багато говорять, але які на практиці майже не використовують, або використовують не так, як вони задумувались. Але то й не дивно, дуже часто вони суперечать один одному і суперечать отим всім принципам розробки (привіт SOLID та DRY).
До прикладу, багато молодих розробників не розуміють для чого потрібен той самий DTO. Особливо, коли вони замкнені в рамках фреймворку і бояться за нього вийти.
А насправді задача проста. Взяти дані і в середині класу зберегти стейт цих даних, щоб вони десь не загубились чи хтось їх не модифікував до невпізнаваності, що повпливає на кінцевий результат.
Всі якось напружуються, працюючи з цим, замість того, щоб зрозуміти, що насправді ті самі класи - це набір даних. Набір декількох екземплярів класів - це набір даних, які мають лише спільну структуру, а дані будуть різні. Логічно ж?.. Але не завжди, коли забуваєш спрощувати це сприйняття.
Все це я до того, що не забивайте голову занадто складними конструкціями, коли це не потрібно.
І тут якраз KISS (Keep It Simple Stupid) в допомогу. Не ускладнюй!
Такі думки прийшли... мав ними з вами поділитись. А що ви думаєте про це? 🙂
Працюючи зі своїми менті на менторських сесіях все частіше ловлю себе на думках, що на початках свого розвитку як розробника та й навіть з величезним досвідом за плечима ми або не до кінця розуміємо з чим ми працюємо.
А насправді все досить просто, якщо спуститись на декілька рівнів нижче у сприйнятті задач.
Ми працюємо з даними. Беремо їх з вхідних джерел чи генеруємо ці дані самі — не важливо. Ми працюємо з даними, які якось оброблюємо, у щось трансформуємо, десь зберігаємо та модіфіковану (чи ні) версію цих даних передаємо кудись далі.
А для доставки цих даних між різними шарами оброки їх ми і використовуємо оті всі патерни, про які багато говорять, але які на практиці майже не використовують, або використовують не так, як вони задумувались. Але то й не дивно, дуже часто вони суперечать один одному і суперечать отим всім принципам розробки (привіт SOLID та DRY).
До прикладу, багато молодих розробників не розуміють для чого потрібен той самий DTO. Особливо, коли вони замкнені в рамках фреймворку і бояться за нього вийти.
А насправді задача проста. Взяти дані і в середині класу зберегти стейт цих даних, щоб вони десь не загубились чи хтось їх не модифікував до невпізнаваності, що повпливає на кінцевий результат.
Всі якось напружуються, працюючи з цим, замість того, щоб зрозуміти, що насправді ті самі класи - це набір даних. Набір декількох екземплярів класів - це набір даних, які мають лише спільну структуру, а дані будуть різні. Логічно ж?.. Але не завжди, коли забуваєш спрощувати це сприйняття.
Все це я до того, що не забивайте голову занадто складними конструкціями, коли це не потрібно.
І тут якраз KISS (Keep It Simple Stupid) в допомогу. Не ускладнюй!
Такі думки прийшли... мав ними з вами поділитись. А що ви думаєте про це? 🙂
👍7
Media is too big
VIEW IN TELEGRAM
Комуналка тепер підтримує темну і світлу тему та автоматичне перемикання відносно теми операційної системи.
Ще трохи і верстку закінчу. Будемо прикручувати до API.
Ще трохи і верстку закінчу. Будемо прикручувати до API.
🔥10
KRUHLYK 🇺🇦
Я працюю на "галері" (аутсорс, аутстаф)
Це всі такі типу фрілансери? Чи продукти пиляєте? 🫣
Хто ще хотів піти на DOU PHP Meetup, але ще не взяв квиток, наступний пост буде саме для вас 😎
❤2
В DOU теж стартує Чорна п’ятниця 🕺
З 27.11 до 30.11 купуй один квиток на DOU PHP Meetup — і отримуй другий безкоштовно.
Механіка проста: після оплати першого квитка на пошту автоматично прилетить промокод на 100% знижку для другого.
Хочеш прийти сам?
Тоді тримай промокод на 15% знижки: FROM_KRUHLYK_15
(діє лише одна акція, комбінація недоступна)
Лови момент 👇
https://dou.ua/goto/RK7i
З 27.11 до 30.11 купуй один квиток на DOU PHP Meetup — і отримуй другий безкоштовно.
Механіка проста: після оплати першого квитка на пошту автоматично прилетить промокод на 100% знижку для другого.
Хочеш прийти сам?
Тоді тримай промокод на 15% знижки: FROM_KRUHLYK_15
(діє лише одна акція, комбінація недоступна)
Лови момент 👇
https://dou.ua/goto/RK7i
🔥3
А оскільки сьогодні пʼятниця і певним чином можна починати розслаблятися, давайте подивимось просто цікавий матеріал 💁♂️
Tideways вирішили дати можливість помірятисьпіс… бенчмарками різним версіям пихи.
Спойлер: різниці в продуктивності 8.4 і 8.5 немає. Воно і зрозуміло. Але все одно цікаво подивитись результати.
https://tideways.com/profiler/blog/php-benchmarks-8-5-vs-8-4-8-3-and-7-4
Tideways вирішили дати можливість помірятись
Спойлер: різниці в продуктивності 8.4 і 8.5 немає. Воно і зрозуміло. Але все одно цікаво подивитись результати.
https://tideways.com/profiler/blog/php-benchmarks-8-5-vs-8-4-8-3-and-7-4
Tideways
PHP Benchmarks: 8.5 vs 8.4, 8.3 and 7.4
Each year, right on schedule, a new version of PHP is released at the end of November. So, how much faster is this new release across popular frameworks and applications? Our tests show that, in general, the performance between 8.2, 8.3, 8.4 and 8.5 does…
❤3🤔1
А поки були вихідні і багато інших справ, пара дійсно цікавих новин.
1. В рамках святкування двадцятиріччя (!) Symfony випустили в реліз версію 8.0.0.
Тобто, минулого тижня ми говорили за версію 7.4, а тепер одразу 8.0.0. Такий хід для мене досить дивний, хоча з нововведень заявлено РІВНО те, про що ми вже говорили.
Дуже схоже на стратегію релізів китайських смартфонів як на мене 🙄
2. Laravel випустили в реліз версію 12.40.0 з новими, як на мене, дійсно цікавими хелперами. Про них детальніше.
У фасаду
Заявляють, що це покращить читабельність коду при роботі з датами. Як вам така зручність?
Також доступними стали інші функції-хелпери по роботі з датою:
Заюзати можна отак:
Запуск консольних команд у вибраний день або місяць.
Теж зручна фіча, якої досить часто не вистачало для зручності читання коду.
З використанням методу
Валідація кодування файлів.
Оцього точно роками не вистачало, щоб швидко отримувати файли в потрібному кодуванні і не переживати, що фіг ти що по-людськи розпарсиш із вхідного файлу.
Ну і з останнього цікавого. Тепер черги можна ставити на паузу та поновлювати з Artisan команди.
Що думаєте про оновлення? Як вам такий формат новин?
1. В рамках святкування двадцятиріччя (!) Symfony випустили в реліз версію 8.0.0.
Тобто, минулого тижня ми говорили за версію 7.4, а тепер одразу 8.0.0. Такий хід для мене досить дивний, хоча з нововведень заявлено РІВНО те, про що ми вже говорили.
Дуже схоже на стратегію релізів китайських смартфонів як на мене 🙄
2. Laravel випустили в реліз версію 12.40.0 з новими, як на мене, дійсно цікавими хелперами. Про них детальніше.
У фасаду
Illuminate\Support\Carbon зʼявилась можливість змінювати час таймстемпів за допомогою хелперів plus() та minus(). use Illuminate\Support\Carbon;
// Додає 1 рік та 5 днів
Carbon::now()->plus(years: 1, days: 5);
// Забирає 4 тижні
Carbon::now()->minus(weeks: 4);
Заявляють, що це покращить читабельність коду при роботі з датами. Як вам така зручність?
Також доступними стали інші функції-хелпери по роботі з датою:
use function Illuminate\Support\{seconds, minutes, hours, days, years};
seconds(5);
minutes(5);
hours(1);
days(30);
years(1);Заюзати можна отак:
use function Illuminate\Support\minutes;
Cache::put('name', 'Taylor', minutes(5));
Invitation::create([
'expires_at' => now()->plus(weeks: 1),
]);
Запуск консольних команд у вибраний день або місяць.
Теж зручна фіча, якої досить часто не вистачало для зручності читання коду.
З використанням методу
daysOfMonth() можна задати числа місяця, в які запускати команду:schedule->command('generate-reports')
->daysOfMonth(1, 10, 20);
//Або масив в якості іргументу
$schedule->command('generate-reports')
->daysOfMonth([1, 10, 20]);Валідація кодування файлів.
Оцього точно роками не вистачало, щоб швидко отримувати файли в потрібному кодуванні і не переживати, що фіг ти що по-людськи розпарсиш із вхідного файлу.
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'attachment' => [
'required',
File::types(['csv'])->encoding('utf-8'),
],
]);
Ну і з останнього цікавого. Тепер черги можна ставити на паузу та поновлювати з Artisan команди.
php artisan queue:pause database:default
php artisan queue:continue database:default
Що думаєте про оновлення? Як вам такий формат новин?
🔥8👍4👏1