Гейзенбаг: коды возврата при использовании Memcached+Nginx
На этой неделе в нашей тикет-системе был совершенно изумительный гейзенбаг. При запросе определённой страницы, на которой расположен уже удалённый объект было необходимо выдавать код 404. Однако в произвольные моменты времени там выдавался код 200.Начали расследования. К нему подключился наш #seo-шник. Оказалось, что код 200 выдается совершенно произвольно. Пробовали разные браузеры, сначала грешили на Firefox, но потом оказалось, что браузер не причём. Начали копать в сторону ZF, тамвсё было адекватно. Следующим пунктом нашей проверки оказался кэш. Ключ кэша совпадал, а контент…
И тут мы поняли, что ещё давно внесли небольшой фикс в Zend_Cache_Frontend_Page. Т.к. nginx не умеет проводить десериализацию данных, полученных из memcached а просто выдает их, то и сериализацию мы обрубили. А при сериализации к контенту страницы дополнительно добавлялись заголовки. Т.е. мы не сохраняли заголовки страницы при кэшировании, а nginx потом с чистой совестью выдавал код 200, т.к. страница была найдена в кэше.
Я вижу два варианта решения этой задачи.
- Включить сериализацию, сохранять заголовки. Но тогда придется выдавать кэш из php, а не из nginx. Это приведет к снижению производительности.
- Не кэшировать страницы, если обнаружен код 404.
Оба варианта ведут к снижению производительности, однако, как мне кажется, при втором варианте оно меньше. Поэтому на нём мы и остановились. Тем более, что со временем количество обращений к страницам с 404 кодом должно уменьшатся, т.к. они исчезнут из выдачи поисковиков.