День 1613. #ЗаметкиНаПолях
Сжатие Ответов в ASP.NET Core
Уменьшение размера ответа API может заметно повысить производительность вашего приложения. А поскольку пропускная способность сети является ограниченным ресурсом, следует, по крайней мере, рассмотреть преимущества сжатия ответов.
Использовать сжатие ответов в приложениях .NET очень просто. Нужно вызвать два метода:
- AddResponseCompression – для настройки сервисов сжатия ответа;
- UseResponseCompression – для добавления промежуточного ПО сжатия ответа в конвейер.
Сжатие ответов по умолчанию отключено в HTTPS, поэтому его надо явно включить:
В идеале лучше использовать серверное сжатие ответа, если ваш сервер приложений (IIS, Apache, Nginx) поддерживает его. Если сервер не поддерживает сжатие ответов, то оправдано использование промежуточного ПО. Однако т.к. оно происходит на уровне приложения, производительность обычно падает.
Еще одной проблемой является безопасность, т.к. использование сжатия ответов в HTTPS может подвергнуть вас атакам CRIME и BREACH. Вот что можно сделать, чтобы защититься от них:
- Добавить токены защиты от подделки (anti-forgery).
- Не отправлять секреты приложения в теле запроса.
- Добавить ограничитель трафика
Настройка провайдеров сжатия
При вызове AddResponseCompression по умолчанию добавляются два провайдера сжатия (но можно добавить свои в настройках AddResponseCompression):
- BrotliCompressionProvider
- GzipCompressionProvider
По умолчанию используется сжатие Brotli, если оно поддерживается клиентом. В противном случае будет использоваться Gzip. Можно настроить уровень сжатия для Brotli и Gzip:
- Optimal,
- Fastest (по умолчанию),
- NoCompression,
- SmallestSize.
Итого
Сжатие ответов — хороший метод повышения производительности API и снижения сетевых затрат. В идеале желательно использовать серверное сжатие ответов, если оно поддерживается вашим сервером приложений. Если нет, сжатие ответов в приложении доступно в .NET через промежуточное ПО.
Это увеличивает нагрузку на ЦП и может подвергнуть HTTPS некоторым рискам безопасности, но есть способы смягчить это.
Обычно конфигурации по умолчанию для провайдера сжатия и уровня сжатия дают отличные результаты.
Вы можете протестировать значение сжатия ответа в своём приложении и изучить изменения в размере и времени ответа. Попробуйте разные провайдеры сжатия, изменяя заголовок Accept-Encoding клиента, а также настраивая разные уровни сжатия в приложении.
Источник: https://www.milanjovanovic.tech/blog/response-compression-in-aspnetcore
Сжатие Ответов в ASP.NET Core
Уменьшение размера ответа API может заметно повысить производительность вашего приложения. А поскольку пропускная способность сети является ограниченным ресурсом, следует, по крайней мере, рассмотреть преимущества сжатия ответов.
Использовать сжатие ответов в приложениях .NET очень просто. Нужно вызвать два метода:
- AddResponseCompression – для настройки сервисов сжатия ответа;
- UseResponseCompression – для добавления промежуточного ПО сжатия ответа в конвейер.
Сжатие ответов по умолчанию отключено в HTTPS, поэтому его надо явно включить:
builder.ServicesКогда использовать
.AddResponseCompression(opts =>
{
opts.EnableForHttps = true;
});
В идеале лучше использовать серверное сжатие ответа, если ваш сервер приложений (IIS, Apache, Nginx) поддерживает его. Если сервер не поддерживает сжатие ответов, то оправдано использование промежуточного ПО. Однако т.к. оно происходит на уровне приложения, производительность обычно падает.
Еще одной проблемой является безопасность, т.к. использование сжатия ответов в HTTPS может подвергнуть вас атакам CRIME и BREACH. Вот что можно сделать, чтобы защититься от них:
- Добавить токены защиты от подделки (anti-forgery).
- Не отправлять секреты приложения в теле запроса.
- Добавить ограничитель трафика
Настройка провайдеров сжатия
При вызове AddResponseCompression по умолчанию добавляются два провайдера сжатия (но можно добавить свои в настройках AddResponseCompression):
- BrotliCompressionProvider
- GzipCompressionProvider
По умолчанию используется сжатие Brotli, если оно поддерживается клиентом. В противном случае будет использоваться Gzip. Можно настроить уровень сжатия для Brotli и Gzip:
- Optimal,
- Fastest (по умолчанию),
- NoCompression,
- SmallestSize.
builder.ServicesЗаметим, что уровень SmallestSize ожидаемо имеет сильное негативное влияние на время ответа.
.Configure<BrotliCompressionProviderOptions>(opts =>
{
opts.Level = CompressionLevel.Optimal;
});
Итого
Сжатие ответов — хороший метод повышения производительности API и снижения сетевых затрат. В идеале желательно использовать серверное сжатие ответов, если оно поддерживается вашим сервером приложений. Если нет, сжатие ответов в приложении доступно в .NET через промежуточное ПО.
Это увеличивает нагрузку на ЦП и может подвергнуть HTTPS некоторым рискам безопасности, но есть способы смягчить это.
Обычно конфигурации по умолчанию для провайдера сжатия и уровня сжатия дают отличные результаты.
Вы можете протестировать значение сжатия ответа в своём приложении и изучить изменения в размере и времени ответа. Попробуйте разные провайдеры сжатия, изменяя заголовок Accept-Encoding клиента, а также настраивая разные уровни сжатия в приложении.
Источник: https://www.milanjovanovic.tech/blog/response-compression-in-aspnetcore
👍10
День 1614. #ЧтоНовенького
Новинки Превью 5 .NET 8
Продолжаем рассматривать, что нового появилось в превью 5 8й версии .NET.
1. IHttpSysRequestTimingFeature
Новый интерфейс IHttpSysRequestTimingFeature предоставляет подробные данные о временных метках, связанных с обработкой запросов при использовании сервера HTTP.sys. Раньше информация о запросе HTTP.sys предоставлялась через интерфейс IHttpSysRequestInfoFeature. С добавлением IHttpSysRequestTimingFeature мы движемся к более чётко определённым API, которые обеспечивают лучший доступ к данным о времени запроса.
Метод TryGetTimestamp извлекает метку времени для предоставленного типа времени, а метод TryGetElapsedTime даёт время, прошедшее между двумя указанными временами.
Это усовершенствование предоставляет разработчикам:
- Более детальное понимание различных этапов обработки запросов.
- Возможности точной диагностики производительности.
- Улучшенный доступ к данным о времени запросов HTTP.sys и контроль над ними.
2. Имя хоста в ITlsHandshakeFeature
Имя хоста Server Name Indication (SNI) теперь доступно в интерфейсе ITlsHandshakeFeature.
Предоставление имени хоста особенно полезно для крупномасштабных сервисов, управляющих тысячами привязок SNI. С помощью этой функции вы получаете ценную информацию о выбранном SNI во время TLS-рукопожатия, тем самым значительно улучшая свои возможности отладки при росте количества клиентов. Это позволяет быстрее решать проблемы и повышать надёжность обслуживания.
Источник: https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-5/#servers
Новинки Превью 5 .NET 8
Продолжаем рассматривать, что нового появилось в превью 5 8й версии .NET.
1. IHttpSysRequestTimingFeature
Новый интерфейс IHttpSysRequestTimingFeature предоставляет подробные данные о временных метках, связанных с обработкой запросов при использовании сервера HTTP.sys. Раньше информация о запросе HTTP.sys предоставлялась через интерфейс IHttpSysRequestInfoFeature. С добавлением IHttpSysRequestTimingFeature мы движемся к более чётко определённым API, которые обеспечивают лучший доступ к данным о времени запроса.
namespace Microsoft.AspNetCore.Server.HttpSysСвойство Timestamps предоставляет доступ ко всем временным меткам HTTP.sys. Временные метки получаются с помощью QueryPerformanceCounter, а частота временных меток может быть определена с помощью QueryPerformanceFrequency.
{
public interface IHttpSysRequestTimingFeature
{
ReadOnlySpan<long> Timestamps { get; }
bool TryGetTimestamp(
HttpSysRequestTimingType timestampType,
out long timestamp);
bool TryGetElapsedTime(
HttpSysRequestTimingType startingTimestampType,
HttpSysRequestTimingType endingTimestampType,
out TimeSpan elapsed);
}
}
Метод TryGetTimestamp извлекает метку времени для предоставленного типа времени, а метод TryGetElapsedTime даёт время, прошедшее между двумя указанными временами.
Это усовершенствование предоставляет разработчикам:
- Более детальное понимание различных этапов обработки запросов.
- Возможности точной диагностики производительности.
- Улучшенный доступ к данным о времени запросов HTTP.sys и контроль над ними.
2. Имя хоста в ITlsHandshakeFeature
Имя хоста Server Name Indication (SNI) теперь доступно в интерфейсе ITlsHandshakeFeature.
/// <summary>SNI является частью процесса TLS-рукопожатия и позволяет клиентам указывать имя хоста, к которому они пытаются подключиться. Это позволяет серверам, на которых размещается несколько виртуальных хостов или доменов, предоставлять правильный сертификат безопасности во время процесса установки связи, следовательно, позволяет работать нескольким HTTPS-сайтам (или другим сервисам поверх TLS) на одном IP-адресе без использования одного и того же сертификата для всех сайтов. Обычно SNI обрабатывается только в стеке TLS и используется для выбора соответствующего сертификата, но теперь раскрытие имени хоста позволяет другим компонентам приложения использовать эту информацию для диагностики, ограничения скорости, маршрутизации и т. д.
/// Gets the host name from the "server_name" (SNI) extension of the client hello if present.
/// See <see href="https://www.rfc-editor.org/rfc/rfc6066#section-3">RFC 6066</see>.
/// </summary>
string? HostName => null;
Предоставление имени хоста особенно полезно для крупномасштабных сервисов, управляющих тысячами привязок SNI. С помощью этой функции вы получаете ценную информацию о выбранном SNI во время TLS-рукопожатия, тем самым значительно улучшая свои возможности отладки при росте количества клиентов. Это позволяет быстрее решать проблемы и повышать надёжность обслуживания.
Источник: https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-5/#servers
👍8
День 1615. #ЗаметкиНаПолях
Разбираем и Оптимизируем SQL-Запросы. Начало
Сегодня разберём, как SQL-запросы выполняются механизмом базы данных и как мы можем использовать эти знания для оптимизации запросов.
Порядок выполнения SQL — это фактическая последовательность, в которой механизм БД обрабатывает различные компоненты запроса. Он может серьёзно отличаться от порядка написания запроса. Так ядро БД может свести к минимуму дисковый ввод-вывод, эффективно использовать индексы и избежать ненужных операций. Рассмотрим запрос:
1. FROM: определение таблиц, задействованных в запросе (customers и orders).
2. JOIN: выполнение операции соединения на основе условия соединения (customers.id = orders.customer_id).
3. WHERE: применение условия фильтрации к объединённой таблице (order_date >= '2023-01-01'), которое отбирает только заказы, сделанные 1 января 2023 года или позже.
4. GROUP BY: группировка строк по указанным столбцам (customers.name).
5. HAVING: фильтрация групп по условию (total_spent >= 1000), при котором выбираются только клиенты с общей потраченной суммой 1000 и более.
6. SELECT: выбор столбцов и агрегатных функций из каждой группы (customers.name, COUNT(order_id) и SUM(order_amount)).
7. ORDER BY: сортировка строк по указанным столбцам (customers.name).
8. LIMIT: ограничение результата максимум 100 строками.
Запросы SARGABLE
SARGABLE (Searched ARGUment ABLE) - это запрос, который может использовать индексы для более быстрого выполнения. Запрос SARGABLE использует операторы и функции, которые могут использовать преимущества индексов. Например, использование операторов равенства (=), неравенства (<>, !=), диапазона (BETWEEN) или членства (IN) в индексированных столбцах может сделать запрос пригодным для поиска.
Запрос не является SARGABLE, если он использует операторы или функции, которые препятствуют использованию индекса или требуют полного сканирования таблицы. Например, использование операторов отрицания (NOT), подстановочных знаков (LIKE) или арифметических операций (+, -, *, /) в индексированных столбцах может сделать запрос недоступным для поиска.
Чтобы написать SARGABLE-запрос, обычно нужно ИЗБЕГАТЬ использования следующих конструкций в предложении WHERE:
1. Функций для индексированных столбцов: UPPER(), LOWER(), SUBSTRING() и т. д.
2. Арифметических операций над индексированными столбцами: столбец + 1 > 10, столбец * 2 < 20 и т. д.
3. Операторов отрицания для индексированных столбцов: NOT IN, NOT LIKE, NOT EXISTS и т. д.
4. Ведущих подстановочных знаков в индексированных столбцах: LIKE '%abc', LIKE '%xyz%' и т. д.
5. Неявных преобразований типов, которые могут повлиять на использование индекса.
Замечание: некоторые СУБД могут эффективно обрабатывать такие запросы и использовать индексы, а также некоторые виды индексов специально предназначены для таких запросов, но в общем случае полагаться на это не стоит.
Окончание следует…
Источник: https://dev.to/kanani_nirav/secret-to-optimizing-sql-queries-understand-the-sql-execution-order-28m1
Разбираем и Оптимизируем SQL-Запросы. Начало
Сегодня разберём, как SQL-запросы выполняются механизмом базы данных и как мы можем использовать эти знания для оптимизации запросов.
Порядок выполнения SQL — это фактическая последовательность, в которой механизм БД обрабатывает различные компоненты запроса. Он может серьёзно отличаться от порядка написания запроса. Так ядро БД может свести к минимуму дисковый ввод-вывод, эффективно использовать индексы и избежать ненужных операций. Рассмотрим запрос:
SELECT customers.name,Порядок выполнения этого запроса следующий:
COUNT(order_id) as Total_orders,
SUM(order_amount) as total_spent
FROM customers
JOIN orders ON customers.id = orders.customer_id
WHERE order_date >= '2023-01-01'
GROUP BY customers.name
HAVING total_spent >= 1000
ORDER BY customers.name
LIMIT 100;
1. FROM: определение таблиц, задействованных в запросе (customers и orders).
2. JOIN: выполнение операции соединения на основе условия соединения (customers.id = orders.customer_id).
3. WHERE: применение условия фильтрации к объединённой таблице (order_date >= '2023-01-01'), которое отбирает только заказы, сделанные 1 января 2023 года или позже.
4. GROUP BY: группировка строк по указанным столбцам (customers.name).
5. HAVING: фильтрация групп по условию (total_spent >= 1000), при котором выбираются только клиенты с общей потраченной суммой 1000 и более.
6. SELECT: выбор столбцов и агрегатных функций из каждой группы (customers.name, COUNT(order_id) и SUM(order_amount)).
7. ORDER BY: сортировка строк по указанным столбцам (customers.name).
8. LIMIT: ограничение результата максимум 100 строками.
Запросы SARGABLE
SARGABLE (Searched ARGUment ABLE) - это запрос, который может использовать индексы для более быстрого выполнения. Запрос SARGABLE использует операторы и функции, которые могут использовать преимущества индексов. Например, использование операторов равенства (=), неравенства (<>, !=), диапазона (BETWEEN) или членства (IN) в индексированных столбцах может сделать запрос пригодным для поиска.
Запрос не является SARGABLE, если он использует операторы или функции, которые препятствуют использованию индекса или требуют полного сканирования таблицы. Например, использование операторов отрицания (NOT), подстановочных знаков (LIKE) или арифметических операций (+, -, *, /) в индексированных столбцах может сделать запрос недоступным для поиска.
Чтобы написать SARGABLE-запрос, обычно нужно ИЗБЕГАТЬ использования следующих конструкций в предложении WHERE:
1. Функций для индексированных столбцов: UPPER(), LOWER(), SUBSTRING() и т. д.
2. Арифметических операций над индексированными столбцами: столбец + 1 > 10, столбец * 2 < 20 и т. д.
3. Операторов отрицания для индексированных столбцов: NOT IN, NOT LIKE, NOT EXISTS и т. д.
4. Ведущих подстановочных знаков в индексированных столбцах: LIKE '%abc', LIKE '%xyz%' и т. д.
5. Неявных преобразований типов, которые могут повлиять на использование индекса.
Замечание: некоторые СУБД могут эффективно обрабатывать такие запросы и использовать индексы, а также некоторые виды индексов специально предназначены для таких запросов, но в общем случае полагаться на это не стоит.
Окончание следует…
Источник: https://dev.to/kanani_nirav/secret-to-optimizing-sql-queries-understand-the-sql-execution-order-28m1
👍22
День 1615. #ЗаметкиНаПолях
Разбираем и Оптимизируем SQL-Запросы. Окончание
Начало
Настройка производительности на уровне БД
Повышение производительности в порядке выполнения SQL включает в себя оптимизацию шагов, выполняемых ядром БД для обработки и выполнения SQL-запросов. Вот несколько способов повысить производительность в порядке выполнения SQL:
1. Используйте соответствующие индексы: проанализируйте шаблоны запросов и определите столбцы, часто используемые в операциях поиска, объединения и фильтрации. Создайте индексы для этих столбцов для более быстрого извлечения данных и уменьшения потребности в полном сканировании таблиц.
2. Используйте покрывающие индексы: по возможности добавьте в индекс все столбцы, которые требуются для выполнения запроса. Тогда ядро БД для выполнения запроса просканирует только индекс (INDEX ONLY SCAN в плане выполнения запроса), вообще не обращаясь к таблице. Например, если у вас есть индекс таблицы клиентов по дате рождения, а в запросе нужно вывести имена клиентов определённого года рождения, имеет смысл добавить поля имени в индекс. Это несколько увеличит накладные расходы на индекс и его обновление, зато запрос, извлекающий только имя по дате рождения, будет сканировать только индекс и выполняться значительно быстрее. В противном случае имя клиента должно будет извлекаться из таблицы по ссылке для каждой строки индекса (INDEX SCAN в плане выполнения запроса), что обычно быстрее полного сканирования таблицы (FULL TABLE SCAN), но медленнее сканирования только индекса.
3. Оптимизируйте операции соединения: убедитесь, что условия соединения эффективны, и используйте соответствующие индексы. По возможности используйте INNER JOIN вместо OUTER JOIN, поскольку это обычно приводит к повышению производительности. Рассмотрите порядок соединения нескольких таблиц, чтобы свести к минимуму размер промежуточного набора результатов.
4. Ограничьте размер набора результатов: используйте предложение LIMIT, чтобы ограничить количество строк, возвращаемых запросом. Это может уменьшить объём обрабатываемых данных и сократить время ответа на запрос.
5. Избегайте ненужной сортировки и группировки: устраните ненужные операции сортировки и группировки, добавляя их только при необходимости. Этого можно добиться путем тщательного анализа запроса и удаления ненужных предложений ORDER BY и GROUP BY.
6. Используйте раннюю фильтрация в предложении WHERE: применяйте условия фильтрации как можно раньше в порядке выполнения запроса с помощью предложения WHERE. Это уменьшит количество строк, обрабатываемых на последующих этапах, повышая производительность. Также используйте наиболее ограничивающие условия первыми в предложении WHERE.
7. Используйте подходящие типы данных: выберите правильные типы данных для столбцов, чтобы обеспечить эффективное хранение и извлечение данных. Использование соответствующих типов данных может помочь сократить потребление памяти и повысить скорость выполнения запросов.
8. Избегайте ненужных вычислений и функций: сведите к минимуму использование вычислений и функций в запросе, особенно в индексированных столбцах. Эти операции могут препятствовать использованию индекса и влиять на производительность. Рассмотрите возможность предварительного вычисления значений или использования производных столбцов, когда это необходимо.
9. Используйте инструменты оптимизации запросов: инструменты или подсказки оптимизатора запросов для конкретной базы данных помогут механизму базы данных создавать эффективные планы выполнения. Эти инструменты могут предоставить информацию, рекомендации и статистику для повышения производительности.
Итого
Порядок выполнения SQL влияет на производительность запросов и эффективность базы данных. Мы можем улучшить производительность с помощью индексации, эффективных объединений, фильтрации, SARGABLE-запросов и лучших практик.
Источник: https://dev.to/kanani_nirav/secret-to-optimizing-sql-queries-understand-the-sql-execution-order-28m1
Разбираем и Оптимизируем SQL-Запросы. Окончание
Начало
Настройка производительности на уровне БД
Повышение производительности в порядке выполнения SQL включает в себя оптимизацию шагов, выполняемых ядром БД для обработки и выполнения SQL-запросов. Вот несколько способов повысить производительность в порядке выполнения SQL:
1. Используйте соответствующие индексы: проанализируйте шаблоны запросов и определите столбцы, часто используемые в операциях поиска, объединения и фильтрации. Создайте индексы для этих столбцов для более быстрого извлечения данных и уменьшения потребности в полном сканировании таблиц.
2. Используйте покрывающие индексы: по возможности добавьте в индекс все столбцы, которые требуются для выполнения запроса. Тогда ядро БД для выполнения запроса просканирует только индекс (INDEX ONLY SCAN в плане выполнения запроса), вообще не обращаясь к таблице. Например, если у вас есть индекс таблицы клиентов по дате рождения, а в запросе нужно вывести имена клиентов определённого года рождения, имеет смысл добавить поля имени в индекс. Это несколько увеличит накладные расходы на индекс и его обновление, зато запрос, извлекающий только имя по дате рождения, будет сканировать только индекс и выполняться значительно быстрее. В противном случае имя клиента должно будет извлекаться из таблицы по ссылке для каждой строки индекса (INDEX SCAN в плане выполнения запроса), что обычно быстрее полного сканирования таблицы (FULL TABLE SCAN), но медленнее сканирования только индекса.
3. Оптимизируйте операции соединения: убедитесь, что условия соединения эффективны, и используйте соответствующие индексы. По возможности используйте INNER JOIN вместо OUTER JOIN, поскольку это обычно приводит к повышению производительности. Рассмотрите порядок соединения нескольких таблиц, чтобы свести к минимуму размер промежуточного набора результатов.
4. Ограничьте размер набора результатов: используйте предложение LIMIT, чтобы ограничить количество строк, возвращаемых запросом. Это может уменьшить объём обрабатываемых данных и сократить время ответа на запрос.
5. Избегайте ненужной сортировки и группировки: устраните ненужные операции сортировки и группировки, добавляя их только при необходимости. Этого можно добиться путем тщательного анализа запроса и удаления ненужных предложений ORDER BY и GROUP BY.
6. Используйте раннюю фильтрация в предложении WHERE: применяйте условия фильтрации как можно раньше в порядке выполнения запроса с помощью предложения WHERE. Это уменьшит количество строк, обрабатываемых на последующих этапах, повышая производительность. Также используйте наиболее ограничивающие условия первыми в предложении WHERE.
7. Используйте подходящие типы данных: выберите правильные типы данных для столбцов, чтобы обеспечить эффективное хранение и извлечение данных. Использование соответствующих типов данных может помочь сократить потребление памяти и повысить скорость выполнения запросов.
8. Избегайте ненужных вычислений и функций: сведите к минимуму использование вычислений и функций в запросе, особенно в индексированных столбцах. Эти операции могут препятствовать использованию индекса и влиять на производительность. Рассмотрите возможность предварительного вычисления значений или использования производных столбцов, когда это необходимо.
9. Используйте инструменты оптимизации запросов: инструменты или подсказки оптимизатора запросов для конкретной базы данных помогут механизму базы данных создавать эффективные планы выполнения. Эти инструменты могут предоставить информацию, рекомендации и статистику для повышения производительности.
Итого
Порядок выполнения SQL влияет на производительность запросов и эффективность базы данных. Мы можем улучшить производительность с помощью индексации, эффективных объединений, фильтрации, SARGABLE-запросов и лучших практик.
Источник: https://dev.to/kanani_nirav/secret-to-optimizing-sql-queries-understand-the-sql-execution-order-28m1
👍12
День 1617. #ЗаметкиНаПолях
Отслеживание Кликов по Ссылке на HTML-Странице
Существует множество способов отслеживать, когда пользователь щёлкает по ссылке на HTML-странице. Большинство из них требуют JS-скрипта и регистрации события click для элемента <a>. Совсем недавно в элемент <a> был добавлен атрибут ping. Он позволяет указать URL-адрес, на который будет отправлен ping-запрос при нажатии на ссылку. Таким образом отпадает необходимость в JS-скрипте.
Атрибут ping хорошо поддерживается. Только Firefox отключил эту функцию по умолчанию. Кроме того, блокировщики рекламы могут заблокировать ping-запрос (так же как они блокируют некоторые JS-скрипты). Поэтому, глобальная поддержка функции составляет около 93%.
Использование атрибута ping даёт некоторые преимущества:
- работает, когда JavaScript отключен,
- ping-запросы являются фоновыми, т.е., когда пользователь покидает страницу, запрос ping не будет прерван.
- тело ответа на ping-запрос игнорируется; браузеру разрешено немедленно завершать соединение, когда сервер отправляет тело ответа. Это помогает экономить ресурсы сервера и браузера.
- ping-запросы не кэшируются, так как это POST-запрос, поэтому каждый ping приводит к запросу на сервер.
Вот пример использования атрибута ping:
Если вам нужно различить несколько ссылок на одной странице, можно использовать параметр строки запроса. Например, если у вас есть две ссылки на одной странице, вы можете использовать
Источник: https://www.meziantou.net/tracking-click-on-anchors-in-an-html-page.htm
Отслеживание Кликов по Ссылке на HTML-Странице
Существует множество способов отслеживать, когда пользователь щёлкает по ссылке на HTML-странице. Большинство из них требуют JS-скрипта и регистрации события click для элемента <a>. Совсем недавно в элемент <a> был добавлен атрибут ping. Он позволяет указать URL-адрес, на который будет отправлен ping-запрос при нажатии на ссылку. Таким образом отпадает необходимость в JS-скрипте.
Атрибут ping хорошо поддерживается. Только Firefox отключил эту функцию по умолчанию. Кроме того, блокировщики рекламы могут заблокировать ping-запрос (так же как они блокируют некоторые JS-скрипты). Поэтому, глобальная поддержка функции составляет около 93%.
Использование атрибута ping даёт некоторые преимущества:
- работает, когда JavaScript отключен,
- ping-запросы являются фоновыми, т.е., когда пользователь покидает страницу, запрос ping не будет прерван.
- тело ответа на ping-запрос игнорируется; браузеру разрешено немедленно завершать соединение, когда сервер отправляет тело ответа. Это помогает экономить ресурсы сервера и браузера.
- ping-запросы не кэшируются, так как это POST-запрос, поэтому каждый ping приводит к запросу на сервер.
Вот пример использования атрибута ping:
<a href="/demo" ping="/ping">Demo</a>Вы можете обработать этот ping-запрос в вашем приложении ASP.NET Core application. Например:
app.MapPost("/ping",В примере выше заголовки ping-from и ping-to выдают исходный URL и запрашиваемый URL (указанный в атрибуте href) соответственно.
([FromHeader(Name = "ping-from")]string from,
[FromHeader(Name = "ping-to")] string to) =>
{
// обрабатываем ping-запрос
return Results.Ok();
});
Если вам нужно различить несколько ссылок на одной странице, можно использовать параметр строки запроса. Например, если у вас есть две ссылки на одной странице, вы можете использовать
<a ping="/ping?id=Link1">
и <a ping="/ping?id=Link2">
, чтобы различать их.Источник: https://www.meziantou.net/tracking-click-on-anchors-in-an-html-page.htm
👍17
День 1618. #ЗаметкиНаПолях
LINQ: Select.Where или Where.Select?
LINQ — очень мощный инструмент для запросов данных. Поскольку большинство функций построены на основе IEnumerable<T> и в большинстве случаев он также возвращает IEnumerable<T>, очень легко объединять несколько функций в цепочку. Возникает вопрос: есть ли разница между Select.Where или Where.Select?
Сначала замечу, что далее мы рассматриваем только коллекции «в памяти», и не IQueryable<T>. Там порядок зависит в основном от провайдера, поэтому Entity Framework и LINQ to SQL могут давать разные результаты.
Рассмотрим следующий пример кода:
Скорее всего, первый, т.к. второй вариант создаст анонимный тип для всех пользователей, даже для тех, кто не является студентом. Т.е. второму варианту придётся проделать больше работы. Для больших списков разница может быть значительна. Как правило, всегда нужно пытаться отфильтровать как можно больше, прежде чем начинать создавать новые объекты. Аналогично с OrderBy. Если список предварительно не фильтруется, OrderBy должен будет проверить гораздо больше записей.
А теперь рассмотрим такой пример:
Если всё же не обойтись без нескольких предложений Where, имеет смысл поставить лучший фильтр в начале, либо попробовать реорганизовать все фильтры в один метод:
LINQ: Select.Where или Where.Select?
LINQ — очень мощный инструмент для запросов данных. Поскольку большинство функций построены на основе IEnumerable<T> и в большинстве случаев он также возвращает IEnumerable<T>, очень легко объединять несколько функций в цепочку. Возникает вопрос: есть ли разница между Select.Where или Where.Select?
Сначала замечу, что далее мы рассматриваем только коллекции «в памяти», и не IQueryable<T>. Там порядок зависит в основном от провайдера, поэтому Entity Framework и LINQ to SQL могут давать разные результаты.
Рассмотрим следующий пример кода:
var users = GetAllUsers();Результат обоих запросов будет одинаковым. Но это не означает, что они делают одно и то же. Первый вариант сначала отфильтрует всех пользователей, которые не являются студентами, а затем создаст анонимный тип. Второй вариант сначала создаст анонимный тип для всех пользователей, а затем отфильтрует тех, кто не является студентами. Какой запрос быстрее?
// Вариант 1
users.Where(u => u.IsStudent)
.Select(u =>
new { u.FirstName, u.LastName, u.IsStudent });
// Вариант 2
users.Select(u =>
new { u.FirstName, u.LastName, u.IsStudent })
.Where(u => u.IsStudent);
Скорее всего, первый, т.к. второй вариант создаст анонимный тип для всех пользователей, даже для тех, кто не является студентом. Т.е. второму варианту придётся проделать больше работы. Для больших списков разница может быть значительна. Как правило, всегда нужно пытаться отфильтровать как можно больше, прежде чем начинать создавать новые объекты. Аналогично с OrderBy. Если список предварительно не фильтруется, OrderBy должен будет проверить гораздо больше записей.
А теперь рассмотрим такой пример:
// вариант 1Опять же семантически они делают одно и то же. Результат будет одинаковым, но способ его достижения - разным. Первый вариант сразу проверит оба условия. Второй вариант (хотя это и не очевидно) также пройдёт по списку только один раз, но здесь возникнут дополнительные накладные расходы на вызов нескольких функций. Кстати, автор оригинальной статьи (см. источник ниже) считает, что этими расходами можно пренебречь. Однако, судя по моим бенчмаркам (см. картинку ниже) разница в некоторых средах может быть довольно существенной (хотя, в .NET 8 выполнение заметно оптимизировали).
users.Where(u => u.IsStudent && u.Age > 30);
// вариант 2
users.Where(u => u.IsStudent)
.Where(u => u.Age > 30);
Если всё же не обойтись без нескольких предложений Where, имеет смысл поставить лучший фильтр в начале, либо попробовать реорганизовать все фильтры в один метод:
private bool IsStudentAndOlderThan30(User user)Источник: https://steven-giesel.com/blogPost/57ed9867-4afd-4d02-9f35-e0941bc6f715
{
return user.IsStudent && user.Age > 30;
}
users.Where(IsStudentAndOlderThan30);
👍21