Skip to content

Commit 677356e

Browse files
committed
MAGETWO-95275: Varnish "Connection reset by peer" error when large catalog is reindexed on schedule
1 parent cf3f078 commit 677356e

File tree

2 files changed

+66
-31
lines changed

2 files changed

+66
-31
lines changed

app/code/Magento/CacheInvalidate/Model/PurgeCache.php

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ class PurgeCache
2626
*/
2727
private $logger;
2828

29+
/**
30+
* Batch size of the purge request.
31+
*
32+
* Based on default Varnish 4 http_req_hdr_len size minus a 512 bytes margin for method,
33+
* header name, line feeds etc.
34+
*
35+
* @see https://varnish-cache.org/docs/4.1/reference/varnishd.html
36+
*
37+
* @var int
38+
*/
39+
private $requestSize = 7680;
40+
2941
/**
3042
* Constructor
3143
*
@@ -52,10 +64,59 @@ public function __construct(
5264
*/
5365
public function sendPurgeRequest($tagsPattern)
5466
{
67+
$successful = true;
5568
$socketAdapter = $this->socketAdapterFactory->create();
5669
$servers = $this->cacheServer->getUris();
57-
$headers = [self::HEADER_X_MAGENTO_TAGS_PATTERN => $tagsPattern];
5870
$socketAdapter->setOptions(['timeout' => 10]);
71+
72+
$formattedTagsChunks = $this->splitTags($tagsPattern);
73+
foreach ($formattedTagsChunks as $formattedTagsChunk) {
74+
if (!$this->sendPurgeRequestToServers($socketAdapter, $servers, $formattedTagsChunk)) {
75+
$successful = false;
76+
}
77+
}
78+
79+
return $successful;
80+
}
81+
82+
/**
83+
* Split tags by batches
84+
*
85+
* @param string $tagsPattern
86+
* @return \Generator
87+
*/
88+
private function splitTags($tagsPattern)
89+
{
90+
$tagsBatchSize = 0;
91+
$formattedTagsChunk = [];
92+
$formattedTags = explode('|', $tagsPattern);
93+
foreach ($formattedTags as $formattedTag) {
94+
if ($tagsBatchSize + strlen($formattedTag) > $this->requestSize - count($formattedTagsChunk) - 1) {
95+
yield implode('|', array_unique($formattedTagsChunk));
96+
$formattedTagsChunk = [];
97+
$tagsBatchSize = 0;
98+
}
99+
100+
$tagsBatchSize += strlen($formattedTag);
101+
$formattedTagsChunk[] = $formattedTag;
102+
}
103+
if (!empty($formattedTagsChunk)) {
104+
yield implode('|', array_unique($formattedTagsChunk));
105+
}
106+
}
107+
108+
/**
109+
* Send curl purge request to servers
110+
* to invalidate cache by tags pattern
111+
*
112+
* @param \Zend\Http\Client\Adapter\Socket $socketAdapter
113+
* @param \Zend\Uri\Uri[] $servers
114+
* @param string $formattedTagsChunk
115+
* @return bool Return true if successful; otherwise return false
116+
*/
117+
private function sendPurgeRequestToServers($socketAdapter, $servers, $formattedTagsChunk)
118+
{
119+
$headers = [self::HEADER_X_MAGENTO_TAGS_PATTERN => $formattedTagsChunk];
59120
foreach ($servers as $server) {
60121
$headers['Host'] = $server->getHost();
61122
try {
@@ -69,12 +130,11 @@ public function sendPurgeRequest($tagsPattern)
69130
$socketAdapter->read();
70131
$socketAdapter->close();
71132
} catch (\Exception $e) {
72-
$this->logger->critical($e->getMessage(), compact('server', 'tagsPattern'));
133+
$this->logger->critical($e->getMessage(), compact('server', 'formattedTagsChunk'));
73134
return false;
74135
}
75136
}
76-
77-
$this->logger->execute(compact('servers', 'tagsPattern'));
137+
$this->logger->execute(compact('servers', 'formattedTagsChunk'));
78138
return true;
79139
}
80140
}

app/code/Magento/CacheInvalidate/Observer/InvalidateVarnishObserver.php

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,6 @@ class InvalidateVarnishObserver implements ObserverInterface
2121
*/
2222
protected $purgeCache;
2323

24-
/**
25-
* Batch size of the purge request.
26-
*
27-
* Based on default Varnish 4 http_req_hdr_len size minus a 512 bytes margin for method,
28-
* header name, line feeds etc.
29-
*
30-
* @see http://www.varnish-cache.org/docs/4.0/reference/varnishd.html#http-req-hdr-len
31-
*
32-
* @var int
33-
*/
34-
private $requestSize = 7680;
35-
3624
/**
3725
* Invalidation tags resolver
3826
*
@@ -56,8 +44,6 @@ public function __construct(
5644
* If Varnish caching is enabled it collects array of tags
5745
* of incoming object and asks to clean cache.
5846
*
59-
* For scaling reason the purge request is chopped down to fix batch size.
60-
*
6147
* @param \Magento\Framework\Event\Observer $observer
6248
* @return void
6349
*/
@@ -70,21 +56,10 @@ public function execute(\Magento\Framework\Event\Observer $observer)
7056
if ($this->config->getType() == \Magento\PageCache\Model\Config::VARNISH && $this->config->isEnabled()) {
7157
$bareTags = $this->getTagResolver()->getTags($object);
7258

73-
$tagsBatchSize = 0;
7459
$tags = [];
75-
$pattern = '((^|,)%s(,|$))';
60+
$pattern = "((^|,)%s(,|$))";
7661
foreach ($bareTags as $tag) {
77-
$formattedTag = sprintf($pattern, $tag);
78-
79-
// Send request if batch size is reached and add the implode with pipe to the computation
80-
if ($tagsBatchSize + strlen($formattedTag) > $this->requestSize - count($tags) - 1) {
81-
$this->purgeCache->sendPurgeRequest(implode('|', array_unique($tags)));
82-
$tags = [];
83-
$tagsBatchSize = 0;
84-
}
85-
86-
$tagsBatchSize += strlen($formattedTag);
87-
$tags[] = $formattedTag;
62+
$tags[] = sprintf($pattern, $tag);
8863
}
8964
if (!empty($tags)) {
9065
$this->purgeCache->sendPurgeRequest(implode('|', array_unique($tags)));

0 commit comments

Comments
 (0)