7 наиболее распространенных ошибок при установке ограничений памяти Java

Оригинал: "6 Common Errors in Setting Java Heap Size" (кажется, автор несколько ошибся в подсчетах)
Перевод: Владимир Русинов

Для установки размера кучи java (heap) используются две опции: -Xmx для установки максимального размера и -Xms для начального(минимального) размера. Вот наиболее часто встречающиеся ошибки их использования:

1. Отсутствие m, M, g или G в конце (регистр не имеет значения). Например:

java -Xmx128 BigApp
java.lang.OutOfMemoryError: Java heap space

Правильная команда должна быть такой:
java -Xmx128m BigApp
. Строго говоря, -Xmx128 корректная настройка для очень маленьких приложений (например HelloWorld), но я думаю в большинстве случаев все-таки имелось в виду -Xmx128m.


2. Лишний пробел или использование =. Например:

java -Xmx 128m BigApp
Invalid maximum heap size: -Xmx
Could not create the Java virtual machine.

java -Xmx=512m HelloWorld
Invalid maximum heap size: -Xmx=512m
Could not create the Java virtual machine.

Правильная команда должна иметь вид
java -Xmx128m BigApp
, без пробела или знака =. -X опции ведут себя отлично от -Dключ=значение опций, в которых используется =.

3. Установка только -Xms в значение большее чем максимальный размер кучи по умолчанию (64m). Похоже что минимальный размер кучи по умолчанию равен 0.
Пример:
java -Xms128m BigApp
Error occurred during initialization of VM
Incompatible initial and maximum heap sizes specified

Корректная команда должна выглядеть так:
java -Xms128m -Xmx128m BigApp
. Установить минимальный и максимальный размер равными - хорошая идея. В любом случае, минимальное значение не должно превышать максимальное.

4. Установка размера кучи большего чем объем доступной физической памяти. Пример:
java -Xmx2g BigApp
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Устанавливайте размер кучи меньше чем размер физической памяти:
java -Xmx1g BigApp

5. Использование mb в качестве единицы измерения, вместо m или M.
java -Xms256mb -Xmx256mb BigApp
Invalid initial heap size: -Xms256mb
Could not create the Java virtual machine.

6. Установка размера кучи в большее значение, чем позволяет JVM. Пример:
java -Xmx256g BigApp
Invalid maximum heap size: -Xmx256g
The specified size exceeds the maximum representable size.
Could not create the Java virtual machine.

Укажите размер поменьше:
java -Xmx256m BigApp

7. Указание дробного чиста в качестве значения. Пример:
java -Xmx0.9g BigApp
Invalid maximum heap size: -Xmx0.9g
Could not create the Java virtual machine.

Правильная команда должна выглядеть так:
java -Xmx928m BigApp

PS:

Как установить размер кучи(heap) в Tomcat?

Остановите сервер Tomcat, установите переменную окружения CATALINA_OPTS, затем запустите Tomcat снова. Смотрите файлы tomcat-install/bin/catalina.sh или catalina.bat чтобы узнать как используется эта переменная окружения.

Примеры:
set CATALINA_OPTS=-Xms512m -Xmx512m
(Windows, значение не в кавычках)
export CATALINA_OPTS="-Xms512m -Xmx512m"
(ksh/bash, значение в кавычках)
setenv CATALINA_OPTS "-Xms512m -Xmx512m"
(tcsh/csh, значение в кавычках)

Просмотрев catalina.bat или catallina.sh, вы можете заметить что для установки JVM опций использутся CATALINA_OPTS, JAVA_OPTS или и то и другое. В чем же различие между CATALINA_OPTS и JAVA_OPTS? Имя CATALINA_OPTS специфично именно для Tomcat, а JAVA_OPTS может использоваться и в других java приложениях (например Jboss). Так как переменные окружения как правило устанавливаются глобально, Вы можете использовать это CATALINA_OPTS задания опций для Tomcat, и JAVA_OPTS - для опций других приложений.
Я предпочитаю использовать CATALINA_OPTS.

Как установить размер кучи в JBoss?

Остановите Jboss, отредактируйте значения в файле $JBOSS_HOME/bin/run.conf, запустите сервер. Вы можете изменить (или добавить если ее там нет) значение переменной JAVA_OPTS например на такое: JAVA_OPTS="-server -Xms128m -Xmx128m"

Как установить размер кучи в Eclipse?

Запускайте Eclispe с ключем "-vmargs <ваши опции>". Все опции после -vmargs будут интерпретированы как опции JVM.
Пример:
eclipse -vmargs -Xms64m -Xmx256m

Это установит опции для Eclipse, но не для приложения которое Вы разрабатываете в eclipse. Для того чтобы поменять опции приложения, используйте Run As -> Open Run Dialog -> (x)=Arguments -> VM Arguments

Как установить размер кучи в NetBeans?

Закройте NetBeans, отредактируйте файл netbeans-install/etc/netbeans.conf. Пример:
netbeans_default_options="-J-Xms512m -J-Xmx512m -J-XX:PermSize=32m -J-XX:MaxPermSize=128m -J-Xverify:none

Как установить размер кучи в Apache Ant?

Установите переменную окружения ANT_OPTS. Примеры:
set ANT_OPTS=-Xms512m -Xmx512m
(Windows)
export ANT_OPTS="-Xms512m -Xmx512m"
(ksh/bash)
setenv ANT_OPTS "-Xms512m -Xmx512m"
(tcsh/csh)

Как установить размер кучи в JavaEE SDK/J2EE SDK/Glassfish/Sun Java System Application Server?

Остановите сервер приложений, откройте $GLASSFISH_HOME/domains/domain1/config/domain.xml, найдите там XML элемент с именем java-config -> jvm-options. Пример:

-Xmx512m
-XX:NewRatio=2
-XX:MaxPermSize=128m
...


Также вы можете изменять опции через веб-интерфейс администратора, обычно http://localhost:4848/, или https://localhost:4848/. Откройте Application Server в верхней части левой панели, затем на правой панели откройте JVM Settings -> JVM Options, и Вы увидите список текущих опций. Вы можете добавить новые или изменить существующие.

Еще один способ - использование cli комманды. Смотрите справку:
./asadmin help create-jvm-options
./asadmin help delete-jvm-options

Определение размера swap использованого процессом

Стандартные консольные утилиты linux не показывают количество памяти процесса выгруженой в подкачку (swapped out).

Однако есть достаточно простой способ узнать это. Все что для нужно - взять идентефикатор процесса (PID) и просмотреть файл smaps относящийся к этому процессу:

cat /proc/pid/smaps | grep Swap

Эта команда выдаст кучу строк, отосящихся к разным сегментам памяти. Чтобы просуммировать все можно воспользоваться awk:

cat /proc/pid/smaps | grep Swap | awk '{ SUM += $2 } END { print SUM }'

Выведеное число - размер использованого свопа в килобайтах.


// Оригинал: http://linuxgazette.net/164/lg_tips.html

Введение в nginx, часть 2: Другие возможности

Данная статья была опубликована в электронном приложением к журналу "Системный администратор"- "Open Source #042"

В первой части статьи я рассказал о базовых и наиболее часто применяемых возможностях nginx. Однако это малая часть того, что можно сделать с nginx. Во второй части своей статьи я расскажу о некоторых более продвинутых возможностях, которые используются в крупных и высоконагруженых проектах.

Failover и балансировка

Крупные проекты редко состоят из одного сервера приложений. Часто их два или больше, и возникает задача балансировки клиентов по этим серверам, а также выполнения failover — необходимо чтобы выход из строя одного из серверов не был заметен для клиентов.
Простейший способ рещить эту задачу — dns round-robin, т.е. назначение доменному имени нескольких ip-адресов. Но это решение имеет ряд недостатков, и гораздо лучше выглядит решение балансировки запросов по бакендам на фронтенде nginx. В конфигурационном файле выглядит это примерно так:

# объявляем upstream — список бакендов
upstream backend {
# перечисляем dns-имена или ip-адреса серверов и их «вес»
server web1 weight=5;
server 1.2.3.4:8080 weight=5;
# а так можно подключаться к бакенду через unix-сокет
server unix:/tmp/backend3 weight=1;
}
# конфигурация виртуального сервера
server {
listen <...>;
server_name myserver.com;
# отправляем все запросы из локейшена / в апстрим
location / {
proxy_pass http://backend;
}
}

Запросы, приходящие к nginx, распределяются по бакендам соответственно указаному весу. Кроме того, можно сделать так, чтобы запросы с одних и тех же IP-адресов отправлялись на одни и те же серверы (для этого в upstream нужно указать директиву ip_hash). Так можно решить проблему с сессиями, но все же лучше найти какой-нибудь способ их репликации или (что еще лучше) использовать RESTful-подход.
В случае, если один из серверов откажется принимать соединения или соединение к нему отвалится по таймауту, он на некоторое время будет исключен из upstream.



Оптимизация nginx


1. Увеличение количества и объема буферов


Для хранения принятых запросов и еще не отданных ответов nginx использует буферы в памяти, а если запрос или ответ не помещается в них, nginx записывает его во временный файл (и пишет при этом предупреждение в log-файл). Поэтому необходимо установить такие размеры, чтобы в большинстве случаев не требовалось обращаться к временному файлу, а с другой стороны — чтобы буферы не использовали слишком много памяти.

Для этого используются следующие параметры:
client_body_buffer_size (по умолчанию: 8k/16k — в зависимости от архитектуры) — задает размер буфера для чтения тела запроса клиента. Обычно стандартного значения хватает, его требуется повышать, только если ваше приложение устанавливает огромные cookies.
proxy_buffer_size (по умолчанию: 4k/8k) — задает размер буфера, в который будет читаться первая часть ответа, получаемого от проксируемого сервера. В этой части ответа находится, как правило, небольшой заголовок ответа. Стандартного значения обычно хватает.
proxy_buffers (по умолчанию: 8 4k/8k) — задает число и размер буферов для одного соединения, в которые будет читаться ответ, получаемый от проксируемого сервера. Установите этот параметр так, чтобы большинство ответов от бэкенда помещалось в буферы.

2. Механизмы обработки соединений


Есть одна тонкость, касающаяся механизма обработки соединений, а именно — способ получения информации о событиях на сокетах. Существуют следующие методы:

  • select — стандартный метод. На большой нагрузке сильно нагружает процессор.
  • poll — стандартный метод. Также сильно нагружает процессор.
  • kqueue — эффективный метод, используемый в операционных системах FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 и Mac OS X. На 2-процессорных машинах под управлением Mac OS X использование kqueue может привести к kernel panic.
  • epoll — эффективный метод, используемый в Linux 2.6+. В некоторых старых дистрибутивах есть патчи для поддержки epoll ядром 2.4.
  • rtsig — real time signals, эффективный метод, используемый в Linux 2.2.19+. При больших количествах одновременных соединений (более 1024) с ним могут быть проблемы (их можно обойти, но на мой взгляд, лучше с этим не связываться).
  • /dev/poll — эффективный метод, используемый в Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ и Tru64 UNIX 5.1A+.

При компиляции nginx автоматически выбирается максимально эффективный найденый метод, однако скрипту configure можно насильно указать какой метод использовать. Если вы решили сделать это, то лучше использовать такие методы:
Linux 2.6: epoll;
FreeBSD: kqueue;
Solaris, HP/UX и другие: /dev/poll;
Linux 2.4 и 2.2: rtsig, не рекомендуется при больших нагрузках.



Включение gzip позволяет сжимать ответ, отправляемый клиенту, что положительно сказывается на удовлетворенности пользователя, но требует больше времени CPU. Gzip включается директивой gzip (on|off). Кроме того, стоит обратить на следующие важные директивы модуля gzip:

gzip_comp_level 1..9 — устанавливает уровень сжатия. Опытным путем выявлено, что оптимальные значения лежат в промежутке от 3 до 5, большие значения дают маленький выигрыш, но создают существенно большую нагрузку на процессор, меньшие — дают слишком маленький коэффициент сжатия.
gzip_min_length (по умолчанию, 0) — минимальный размер ответа, который будет сжиматься. Имеет смысл поставить этот параметр в 1024, чтобы слишком малеьнике файлы не сжимались (т.к. эффективность этого будет мала).
gzip_types mime-тип [mime-тип ...] - разрешает сжатие ответа методом gzip для указанных MIME-типов в дополнение к "text/html". "text/html" сжимается всегда. Имеет смысл добавить такие mime-типы как text/css, text/javascript и подобные. Разумеется, сжимать gif, jpg и прочие уже компрессированые форматы не имеет смысла.

Кроме того, существует модуль gzip_static, который позволяет раздавать уже сжатые статические файлы. В конфирурационном файле это выглядит так:

location /files/ {
gzip on;
gzip_min_length 1024;
gzip_types text/css text/javascript;
gzip_comp_level 5;
gzip_static on;
}

При использовании такой конфигурации в случае запроса «/files/test.html» nginx будет проверять наличие «/files/test.html.gz», и, если этот файл существует и дата его последнего изменения больше, чем дата последнего изменения файла test.html, будет отдан уже сжатый файл, что сохранит ресурсы процессора, которые потребовались бы для сжатия оригинального файла.

Оптимизация приложений


Существует очень полезный трюк, который позволяет указать разработчикам приложений, какие страницы нужно оптимизировать в первую очередь. Для этого потребуется в конфиге nginx указать новый формат лога:

log_format  my_combined  '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$upstream_response_time "$host"'

access_log /var/log/nginx/access_log my_combined;

Переменная $upstream_response_time содержит время ответа бэкенда, поэтому в лог попадает время обработки каждого запроса бэкендом. Далее понадобятся два скрипта:

1. /usr/local/bin/url_stats_report.sh:

#!/bin/sh

echo "=== Requests which took most of the time ===" > /tmp/report.txt
echo "overall time - number of requests - average time - url" >> /tmp/report.txt

cat /var/log/nginx/*access.log | /usr/local/bin/url_stats.py >> /tmp/report.txt
cat /tmp/report.txt | mail -s "url performance report" root

2. /usr/local/bin/url_stats.py:

#!/usr/bin/env python

import sys

urls = {}

try:
while 1:
line = raw_input()
line_arr = line.split(" ")
try:
host = line_arr[-1]
host = host[1:]
host = host[:-1]
url = line_arr[6]
t = float(line_arr[-2])
#print host, url, t

try:
urls[host + url] = (urls[host + url][0] + t, urls[host + url][1] + 1)
except KeyError, e:
urls[host + url] = (t, 1)
except ValueError, e:
pass


except EOFError, e:
pass

def sort_by_value(d):
""" Returns the keys of dictionary d sorted by their values """
items=d.items()
backitems=[ [v[1],v[0]] for v in items]
backitems.sort(reverse=True)
return [backitems[i][1] for i in range(0,len(backitems))]

if (len(sys.argv) > 1):
f = open(sys.argv[1], 'r')
for k in f.readlines():
k = k.strip()
try:
print urls[k][0], urls[k][1], urls[k][0] / urls[k][1], k
except:
print 0, 0, k
else:
i = 0
for k in sort_by_value(urls):
print urls[k][0], urls[k][1], urls[k][0] / urls[k][1], k
i += 1
if i > 100: break

Они не идеальны, но задачу выполняют: запуская /usr/local/bin/url_stats_report.sh (например, в postrotate утилиты logrotate), вы получаете наглядную картину, какие запросы занимают большую часть времени бэкенда.

Кеширование

Незадолго до выхода этой статьи, Игорь Сысоев выпустил версию nginx 0.7.44 с экспериментальной поддержкой кеширования. Из-за большого количества багов, за которкое время было выпущено несколько версий, и в настоящее время последняя версия — 0.7.50 уже достаточно хорошо (хотя и не идеально) работает с кешированием.
Однако это все еще экспериментальная функция, но я решил рассказать о ней, т.к. ее одень давно ждали многое администраторы, да и лично для меня она очень полезна.
Сейчас nginx умеет кешировать на диске ответы от http и fastcgi запросов на бакенды, указывать ключ для кеширования, учитывать заголовки "X-Accel-Expires", "Expires" и "Cache-Control" и вручную устанавливать максимальное время жизни объекта в кеше.
Обслуживанием кеша (очиста старых файлов, наблюдение за размером и т.п.) занимается специальный процесс cache manager. Положительной особенностью реализации является то, что при старте nginx cache manager начинает проверку кеша в фоне, благодаря чему nginx не делает то что называется «дает сквида», т.е. он не висит несколько минут проверяя кеш перед стартом.
Я намеренно не указываю пример конфигурации, т.к. во-первых директивы могут еще поменяться, а во-вторых нужно глубокое понимание механизма кеширования, что требует вдумчивого чтения документации (http://sysoev.ru/nginx/docs/http/ngx_http_proxy_module.html#proxy_cache) и архивов рассылки nginx-ru.

За кадром


В статье освещена лишь та часть возможностей nginx, которыми я пользуюсь чаще всего. За пределами рассказа остались такие вопросы, как поддержка SSI, работа с memcached, экспериментальный встроенный Perl и сторонние модули, реализующие дополнительную функциональность.

Введение в nginx, часть 1

Данная статья была опубликована в электронном приложением к журналу "Системный администратор"- "Open Source #041 (27.03.2009)"

Введение


nginx (engine x) — это HTTP-сервер и IMAP/POP3 прокси-сервер для UNIX-подобных платформ (FreeBSD и GNU/Linux). Nginx начал разрабатываться Игорем Сысоевым, сотрудником компании Рамблер весной 2002 года, а осенью 2004 года появился первый публично доступный релиз. Он, как и все последующие, распространяется под лицензией BSD.
На данный момент nginx работает на большом количестве высоконагруженных сайтов (среди них — Рамблер, Яндекс, В Контакте, wordpress.com, Wrike и другие). Текущая версия, 0.6.x, рассматривается как стабильная с точки зрения надежности, а релизы из ветки 0.7 считаются нестабильными. При этом важно заметить, что функциональность некоторых модулей будет меняться, вследствие чего могут меняться и директивы, поэтому обратной совместимости в nginx до версии 1.0.0 не гарантируется.

Чем же nginx так хорош и почему его так любят администраторы высоконагруженных проектов? Почему бы просто не использовать Apache?



Почему Apache — плохо?


Для начала нужно объяснить, как вообще работают сетевые серверы. Те, кто знаком с сетевым программированием, знают, что по сути существуют три модели работы сервера:
  1. Последовательная. Сервер открывает слушающий сокет и ждет, когда появится соединение (во время ожидания он находится в заблокированном состоянии). Когда приходит соединение, сервер обрабатывает его в том же контексте, закрывает соединение и снова ждет соединения. Очевидно, это далеко не самый лучший способ, особенно когда работа с клиентом ведется достаточно долго и подключений много. Кроме того, у последовательной модели есть еще много недостатков (например, невозможность использования нескольких процессоров), и в реальных условиях она практически не используется.
  2. Многопроцессная (многопоточная). Сервер открывает слушающий сокет. Когда приходит соединение, он принимает его, после чего создает (или берет из пула заранее созданных) новый процесс или поток, который может сколь угодно долго работать с соединением, а по окончании работы завершиться или вернуться в пул. Главный поток тем временем готов принять новое соединение. Это наиболее популярная модель, потому что она относительно просто реализуется, позволяет выполнять сложные и долгие вычисления для каждого клиента и использовать все доступные процессоры. Пример ее использования — Web-сервер Apache. Однако у этого подхода есть и недостатки: при большом количестве одновременных подключений создается очень много потоков (или, что еще хуже, процессов), и операционная система тратит много ресурсов на переключения контекста. Особенно плохо, когда клиенты очень медленно принимают контент. Получаются сотни потоков или процессов, занятых только отправкой данных медленным клиентам, что создает дополнительную нагрузку на планировщик ОС, увеличивает число прерываний и потребляет достаточно много памяти.
  3. Неблокируемые сокеты/конечный автомат. Сервер работает в рамках одного потока, но использует неблокируемые сокеты и механизм поллинга. Т.е. сервер на каждой итерации бесконечного цикла выбирает из всех сокетов тот, что готов для приема/отправки данных с помощью вызова select(). После того, как сокет выбран, сервер отправляет на него данные или читает их, но не ждет подтверждения, а переходит в начальное состояние и ждет события на другом сокете или же обрабатывает следующий, в котором событие произошло во время обработки предыдущего. Данная модель очень эффективно использует процессор и память, но достаточно сложна в реализации. Кроме того, в рамках этой модели обработка события на сокете должна происходить очень быстро — иначе в очереди будет скапливаться много событий, и в конце концов она переполнится. Именно по такой модели работает nginx. Кроме того, он позволяет запускать несколько рабочих процессов (так называемых workers), т.е. может использовать несколько процессоров.

Итак, представим следующую ситуацию: на HTTP-сервер с каналом в 1 Гбит/с подключается 200 клиентов с каналом по 256 Кбит/с:

Что происходит в случае Apache? Создается 200 потоков/процессов, которые относительно быстро генерируют контент (это могут быть как динамические страницы, так и статические файлы, читаемые с диска), но медленно отдают его клиентам. Операционная система вынуждена справляться с кучей потоков и блокировок ввода/вывода.
Nginx в такой ситуации затрачивает на каждый коннект на порядок меньше ресурсов ОС и памяти. Однако тут выявляется ограничение сетевой модели nginx: он не может генерировать динамический контент внутри себя, т.к. это приведет к блокировкам внутри nginx. Естественно, решение есть: nginx умеет проксировать такие запросы (на генерирование контента) на любой другой веб-сервер (например, все тот же Apache) или на FastCGI-сервер.

Рассмотрим механизм работы связки nginx в качестве «главного» сервера и Apache в качестве сервера для генерации динамического контента:

Nginx принимает соединение от клиента и читает от него весь запрос. Тут следует отметить, что пока nginx не прочитал весь запрос, он не отдает его на «обработку». Из-за этого обычно «ломаются» практически все индикаторы прогресса закачки файлов — впрочем, существует возможность починить их с помощью стороннего модуля upload_progress (это потребует модификации приложения).
После того, как nginx прочитал весь ответ, он открывает соединение к Apache. Последний выполняет свою работу (генерирует динамический контент), после чего отдает свой ответ nginx, который его буферизует в памяти или временном файле. Тем временем, Apache освобождает ресурсы.
Далее nginx медленно отдает контент клиенту, тратя при этом на порядки меньше ресурсов, чем Apache.

Такая схема называется фронтэнд + бэкенд (frontend + backend) и применяется очень часто.


Установка


Т.к. nginx только начинает завоевывать популярность, имеются некоторые проблемы с бинарными пакетами, так что будьте готовы к тому, что его придется компилировать самостоятельно. С этим обычно не возникает проблем, надо лишь внимательно прочитать вывод команды ./configure --help и выбрать необходимые вам опции компиляции, например такие:
./configure \
--prefix=/opt/nginx-0.6.x \ # префикс установки
--conf-path=/etc/nginx/nginx.conf \ # расположение конфигурационного файла
--pid-path=/var/run/nginx.pid \ # ... и pid-файла
--user=nginx \ # имя пользователя под которым будет запускаться nginx
--with-http_ssl_module --with-http_gzip_static_module --with-http_stub_status_module \ # список нужных
--without-http_ssi_module --without-http_userid_module --without-http_autoindex_module --without-http_geo_module --without-http_referer_module --without-http_memcached_module --without-http_limit_zone_module # ... и не нужных модулей

После конфигурирования стоит запустить стандартный make && make install, после чего можно пользоваться nginx.
Кроме того в Gentoo вы можете воспользоваться ebuild'ом из стандартного дерева портов; в RHEL/CentOS репозиторием epel (в нем расположени nginx 0.6.x) или srpm для версии 0.7, который можно скачать отсюда: http://blogs.mail.ru/community/nginx; в Debian можно воспользоваться пакетом nginx из ветки unstable.

Конфигурационный файл


Конфигурационный файл nginx очень удобен и интуитивно понятен. Называется он обычно nginx.conf и распологается в $prefix/conf/ если расположение не было переопределено при компиляции. Я люблю класть его в /etc/nginx/, также делают и разработчики всех пакетов упомянутых выше.
Структура конфигурационного файла такова:

user nginx; # имя пользователя, с правами которого будет запускаться nginx
worker_processes 1; # количество рабочих процессов
events {
<...> # в этом блоке указывается механизм поллинга который будет использоваться (см. ниже) и максимальное количество возможных подключений
}

http {
<глобальные директивы http-сервера, например настройки таймаутов и т.п.>;
<почти все из них можно переопределить для отдельного виртуального хоста или локейшена>;

# описание серверов (это то что в apache называется VirtualHost)
server {
# адрес и имя сервера
listen *:80;
server_name aaa.bbb;

<Директивы сервера. Здесь обычно указывают расположение докуменов (root), редиректы и переопределяют глобальные настройки>;

# а вот так можно определить location, для которого можно также переопределить практически все директивы указаные на более глобальных уровнях
location /abcd/ {
<директивы>;
}
# Кроме того, можно сделать location по регулярному выражению, например так:
location ~ \.php$ {
<директивы>;
}
}

# другой сервер
server {
listen *:80;
server_name ccc.bbb;

<директивы>
}
}

Обратите внимание на то, что каждая директива должна оканчиваться точкой с запятой.
Обратное проксирование и FastCGI

Итак, выше мы рассмотрели преимущества схемы frontend + backend, разобрались с установкой, структурой и синтаксисом конфигурационного файла, рассмотрим тепеть как реализовать обратное проксирование в nginx.

А очень просто! Например так:

location / {
proxy_pass http://1.2.3.4:8080;
}

В этом примере все запросы попадающие в location / будут проксироваться на сервер 1.2.3.4 порт 8080. Это может быть как apache, так и любой другой http-сервер.

Однако тут есть несколько тонкостей, связанных с тем, что приложение будет считать, что, во-первых, все запросы приходят к нему с одного IP-адреса (что может быть расценено, например, как попытка DDoS-атаки или подбора пароля), а во-вторых, считать, что оно запущено на хосте 1.2.3.4 и порту 8080 (соответственно, генерировать неправильные редиректы и абсолютные ссылки). Чтобы избежать этих проблем без необходимости переписывания приложения, мне кажется удобной следующая конфигурация:
Nginx слушает внешний интерфейс на порту 80.

Если бэкенд (допустим, Apache) расположен на том же хосте, что и nginx, то он «слушает» порт 80 на 127.0.0.1 или другом внутреннем IP-адресе.

Конфигурация nginx в таком случае выглядит следующим образом:
server {
listen 4.3.2.1:80;
# устанавливаем заголовок Host и X-Real-IP: к каждому запросу отправляемому на backend
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:$proxy_port;
# или «proxy_set_header Host $host;», если приложение будет дописывать :80 ко всем ссылкам
}

Для того, чтобы приложение различало IP-адреса посетителей, нужно либо поставить модуль mod_extract_forwarded (если оно исполняется сервером Apache), либо модифицировать приложение так, чтобы оно брало информацию о IP-адресе пользователя из HTTP-заголовка X-Real-IP.

Другой вариант бэкенд — это использование FastCGI. В этом случае конфигурация nginx будет выглядеть примерно так:

server {
<...>

# location, в который будут попадать запросы на php-скрипты
location ~ .php$ {
fastcgi_pass 127.0.0.1:8888; # определяем адрес и порт fastcgi-сервера,
fastcgi_index index.php; # ...индексный файл

# и некоторые параметры, которые нужно передать серверу fastcgi, чтобы он понял какой скрипт и с какими параметрами выполнять:
fastcgi_param SCRIPT_FILENAME /usr/www/html$fastcgi_script_name; # имя скрипта
fastcgi_param QUERY_STRING $query_string; # строка запроса
# и параметры запроса:
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
}

# благодяря тому что локейшены с регулярными выражениями обладают большим «приоритетом», сюда будут попадать все не-php запросы.
location / {
root /var/www/html/
}

Статика


Для того, чтобы меньше нагружать бэкенд, статические файлы лучше отдавать только через nginx — он, с этой задачей справляется лучше, т.к. на каждый запрос он тратит существенно меньше ресурсов (не надо порождать новый процесс, да процесс nginx'а как правило потребляет меньше памяти, а обслуживать может множество соединений).

В конфигурационном файле это выглядит примерно так:

server {
listen *:80;
server_name myserver.com;

location / {
proxy_pass http://127.0.0.1:80;
}

# предположим что все статичные файлы лежат в /files
location /files/ {
root /var/www/html/; # указываем путь на фс
expires 14d; # добавляем заголовок Expires:
error_page 404 = @back; # а если файл не найден, отправляем его в именованный локейшн @back
}

# запросы из /files, для которых не было найдено файла отправляем на backend, а он может либо сгенерировать нужный файл, либо показать красивое сообщение об ошибке
location @back {
proxy_pass http://127.0.0.1:80;
}

Если вся статика не помещена в какой-то определенный каталог, то воспользоваться регулярным выражением:

location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|wav|bmp|rtf|js)$ {
# аналогично тому что выше, только в этот location будут попадать все запросы оканчивающиеся на одно из указаных суффиксов
root /var/www/html/;
error_page 404 = @back;
}

К сожалению, в nginx не реализована асинхронная работа с файлами. Иными словами, nginx worker блокируется на операциях ввода-вывода. Так что если у вас очень много статических файлов и, в особенности, если они читаются с разных дисков, лучше увеличивать количество рабочих процессов (до числа, которое в 2—3 раза больше, чем суммарное число головок на диске). Это, конечно, ведет к увеличению нагрузки на ОС, но в целом производительность увеличивается. Для работы с типичным количеством статики (не очень большое количество сравнительно небольших файлов: CSS, JavaScript, изображения) вполне хватает одного-двух рабочих процессов.

To be continued


Продолжение статьи уже можно прочитать на этом сайте или в "OpenSource" #042.

Ссылки


Тут можно найти дополнительноую информацию о nginx:

официальный сайт nginx
сайт Игоря Сысоева
Nginx Wiki
nginx с дополнительными сторонними модулями
src.rpm для последних версий nginx
еще несколько хороших ссылок
список рассылки nginx-ru

GNUnet: свободный и анонимный обмен файлами

Общий обзор проекта.

Автор: Vladimir Rusinov, Murano Software
Для конкурса статей проекта opennet.

Введение



GNUnet - это программный пакет для безопасного peer-to-peer соединения, не нуждающегося в серверах. Проект GNUnet возник в 2001 году и был вдохновлён целым рядом технических идей, призванных обеспечить безопасный файлообмен в пиринговых (P2P) сетях.

GNUnet является не просто файлообменной сетью. Основная цель проекта - создание надежной, открытой, равноправной и анонимной (т.е. недоступной цензуре и контролю) системы обмена информацией. Планируется предоставление множества интернет-услуг, а GNUnet стремится стать платформой для разработки децентрализованных сервисов следующего поколения.

Основные технические вопросы работы GNUnet подробно описаны в ряде научных публикаций. Среди этих идей — улучшенное кодирование содержимого (ECRS) и новый протокол анонимной маршрутизации (gap). Вы можете найти все материалы на сайте gnunet. Когда началась работа над GNUnet, были изучены существующие системы (в частности, Freenet и Mnet) на основе которых можно было бы начать новую работу. Однако задуманная система слишком отличалась от существовавших реализаций, чтобы строить GNUnet на основе одной из существовавших систем.

Первый реализованный сервис позволяет обмениваться файлами (анонимно и без какой либо цензуры). Анонимность обеспечивается за счет того, что исходящие от узла сети сообщения неотличимы от чужих сообщений, в передаче которых участвует узел. Все узлы действуют как маршрутизаторы, установленные между ними соединения шифруются, а уровень использования пропускной способности канала поддерживается постоянным. GNUnet использует простую, основанную на избытках экономическую модель для выделения ресурсов. Узлы в GNUnet следят за поведением друг друга, с уважением к использованию ресурсов; узлы, которые больше дают сети награждаются лучшим обслуживанием.

GNUnet продолжает развиваться: появляются новые идеи и улучшается программный код. Часто улучшения GNUnet являются результатом дискуссий с разработчиками других проектов. Наверное, один из наиболее известных таких проектов — это Tor — децентрализованная сеть, действующая как анонимный прокси для TCP трафика с низкой латентностью. Tor спроектирован как универсальное решение, и в нем отсутствуют некоторые возможности специфичные для анонимного файлообмена, например поиск, дублирование данных, параллельная загрузка с нескольких узлов.

Кроме всего прочего, впечатляет список протоколов, которые может использовать GNUnet для передачи. Это стандартные tcp и udp, и необычные для p2p http (причем может работать и через прокси) и smtp. Ко всему прочему GNUnet вполне хорошо работает за NAT.

GNUnet является частью проекта GNU. Страница проекта на сайте gnu имеет адрес http://www.gnu.org/software/gnunet/. Кроме того, существует отдельный сайт gnunet: http://gnunet.org/.

Текущая версия 0.8.0c написана на С (однако существует проект реализации GNUnet на Java), работает под ОС GNU/Linux, *BSD, Mac OS X, Solaris, Windows и распространяется под лицензией GNU GPL. В данный момент в проект входит демон gnunetd, несколько библиотек и два фронтенда: gnunet-gtk и gnunet-qt (соответственно написанные с использованием GTK и Qt).



Сервисы и модули GNUnet


Для идентификации объектов и сервисов GNUnet использует URI (Uniform Resource Identifiers). Любой объект в сети GNUnet идентефицируется с помощью URI, который в текущей версии выглядит как gnunet://module/identifier, где module - имя модуля сети, а identifier - уникальный хеш, идентефецирующий сам объект.

File Sharing и ECRS


Самый популярным и наиболее стабильным сервисом является File Sharing (fs), и, как следует из названия, он предназначен для анонимного децентрализованного обмена файлами. Он позволяет искать, выкладывать (publish) и скачивать (download) как отдельные файлы, так и целые директории. С точки зрения пользователя, все это осуществляется аналогично тому, как это происходит например в dc++, однако, благодаря сложному механизму роутинга запросов и ответов, вы понятия не имеете от кого вы на самом деле принимаете или кому передаете файл.

Интересный момент - можно настраивать степень анонимности: от 0 (не анонимно) до бесконечности. По умолчанию используется 1 и этого в большинстве случаев достаточно (вы же не собираетесь передавать таким образом сверхсекретные данные). Передаваемые файлы закодированы с помощью ECRS (An Encoding for Censorship-Resistant Sharing) и обрабатываются модулем с соответствующем названием.

Другие сервисы


Существует также чат (очень простой, с минимумом функций), планируется еще несколько сервисов (например, анонимная p2p почта).

Установка и Настройка


Я пользуюсь дистрибутивом на основе Gentoo, и в моем случае ebuild для gnunet 0.8.0 уже был в официальном дереве портов (в ветке ~). Для работы gnunet требует sql-бд. В настоящий момент поддерживаются mysql и sqlite. Поскольку я не использую mysql, я выбрал sqlite (USE="sqlite" emerge -v1 gnunet), после чего все собралось без каких-либо проблем.

Также, без проблем нашлись rpm для RHEL/CentOS 5 (в репозитории rpmforge), пакеты для Debian, Ubuntu и Arch Linux. Думаю, готовый пакет легко найдется и для других дистрибутивов.

GNUnet работает в клиент-серверном режиме. Т.е. основной рабочий процесс - gnunetd работает в качестве демона, работает без какого-либо интерфейса и управляется фронтендами gnunet (которые не обязательно должны быть запущены на той же машине).
Это отлично вписывается в мою домашнюю сеть: у меня есть headless сервер, подключеный к интернету, который я использую в качестве интернет-шлюза, NAS, proxy, dns и svn сервера, а моим основным рабочим компьютером является ноутбук.

Сервер


Итак, сначала я установил gnunet на сервер. После установки portage подсказала мне что для настойки нужно запустить gnunet-setup -d с правами пользователя root, что я и сделал. gnunet-setup в диалоговом режиме спросил меня о настройках, после чего создал конфигурационный файл /etc/gnunet.conf для демона. Все опции достаточно понятны, и обладают подробной стправкой.
Однако оказалось что диалоговый режим генерирует не совсем корректный конфигурационный файл, поэтом я собрал на ноутбуке GNUnet с поддержкой gtk, вместо диалогового увидел вот такое окно конфигурации:



А получившийся gnunetd.conf скопировал на сервер.

Клиент


Итак, затем я настроил клиента на моем ноутбук. К сожалению, ebuild'а для gnunet-qt я не нашел (я использую KDE), а написать по-быстрому его не удалось. Поэтому я оставил это до лучших времен и установил gnunet-gtk.
После выполнения gnunet-setup я смог подключиться к серверу и успешно запустить несколько поисков и закачек.

Итак, вот несколько скриншотов:







Недостатки


К сожалению не все так безоблачно в GNUnet как хотелось бы.

Основная проблема - это очень высокая задержка, низкая скорость работы и достаточно высокое потребление ресурсов. Это - цена, которую приходится платить за децентрализованность и шифрование.
Так, поиск редкого контента может длиться часами, а прежде чем начнется его скачивание может пройти еще много часов, да и скорость скачивания будет не на высоте. Однако, это пробоема всех децентрализованных сетей, и чем более децентрализованна она, тем более усугубляется эта пробоема (так, eDonkey показывает чуть лучшие результаты, а не децентрализованный torrent намного более лучшие). Остается надеяться что в будущем, с увеличением пропускной способности сетей и производительности компьютеров эта проблема будет становится все менее актуальной.

Вторая проблема - малая популярность сети, и, как следствие, недостаточное количества контента. Отчасти в этом виновата малая раскручености протокола, отчасти - нетривиальность использование, да и проблема высокой задержки тоже играет немаловажную роль.
Эту проблему можно решить, и я надеюсь что данная статья приведет новых пользователей в сеть GNUnet.

Ссылки




  • TOR
  • Freenet
  • Winny

Denyhosts - блокировка перебора паролей ssh

Denyhosts - весьма полезная утилита для пресечения попыток подобрать пароль к ssh.

Устанавливается без каких-либо проблем: emerge denyhosts в Gentoo, для других дистрибутивов пакеты также существуют и как правило находятся в основном репозитории.

Denyhosts работает следующим образом: он проверяет логи и добавляет в /etc/hosts.deny ip адреса, с которых наблюдается много попыток неудачного входа. Для того чтобы это работало, ssh должен быть собран с tcpwrappers (что всегда разумно и делается по умолчанию).

У denyhosts достаточно гибкие настройки, можно указать после скольких неудачных попыток блокировать хост, на какой период это делать и т.п. Настойки по умолчанию на мой взгляд черезчур суровы, поэтому имеет смысл отредактировать файл /etc/denyhosts.conf, который весьма прост для понимания и имеет подробные комментарии.

Есть два способа запустить denyhosts: в качестве демона или в качестве cron-задания. Памяти он потребляет немного, поэтому проще первое:
/etc/init.d/denyhosts start
rc-upade add denyhosts default

Оптимизация производительности Apache

Введение


По данным Netcraft, Apache - самый популярный веб-сервер в интернет, он обслуживает множество серверов и сайтов. Часто возникает необходимость увеличить производительность веб-сервера. Наверное лучший способ это сделать - перейти к схеме frontend+backend, но это может потребовать достаточно серьезных изменений в приложении (например, у вас наверняка отвалятся всяческие индикаторы прогресса аплоада файлов).

Другой способ - просто увеличить производительность сервера - поставить более быстрый процессор и больше памяти.

Однако и первое и второе требует много времени и ресурсов, так что на первое время можно попробовать ускорить apache путем оптимизации его конфигурации. Существуют оптимизации, которые можно применить только при пересборке apache, другие же можно применять без перекомпиляции сервера.

Загружайте только необходимые модули


Apache - модульная программа, бОльшая часть функций которой реализуется в модулях. При этом эти модули могут быть как вкомпилированы, так и собраны в виде DSO - динамических библиотеках. Большинство современных дистрибутивов поставляет apache с набором DSO, так что не нужные модули можно легко отключить без перекомпиляции.

Запускайте apache только с необходимыми модулями, чтобы уменьшить потребление памяти. Если вы решили скомпилировать apache самостоятельно, то либо тщательно подходите к выбору списка модулей, которые вы включите, либо компилируйте их как DSO используя apxs в apache1 и apxs2 в apache2. Для того чтобы отключить ненужные DSO-модули, достаточно закомментировать лишние строчки LoadModule в httpd.conf. Apache со статически скомпилированными модулями будет потреблять чуть меньше памяти, однако вам придется каждый раз его перекомпилировать для изменения списка модулей.



Выберете подходящий MPM


В apache каждый запрос обрабатывается в своем процессе или потоке. При компиляции apache позволяет выбирать один из нескольким MPM (Multi-processing module), которые отвечают за прослушивание портов, прием запросов и раздачу этих запросов дочерним процессам или потокам, в которых эти запросы будут обработаны.

Выбор MPM зависит от нескольких факторов, таких как наличие поддержки потоков в ОС, количества свободной памяти, а также требований стабильности и безопасности.

Если безопасность очень важна, следует выбрать peruser MPM, пожертвовав производительностью.

Если важна именно производительность, то выбор ограничивается двумя mpm: prefork и worker.

Worker - поточный MPM, т.е. в нем каждый запрос обслуживается в отдельном потоке одного из дочерних процессов. Потоки - более легкие для ОС объекты, чем процессы, они более эффективно используют память и переключения контекста для них происходят быстрее. Однако, из-за того что каждый поток имеет доступ ко всей памяти процесса, worker mpm более подвержен сбоям: сбой одного потока может повлечь падение всего процесса, в котором находился этот поток (именно поэтому worker mpm запускает несколько дочерних процессов с несколькими потоками в каждом).

Perfork - mpm использует несколько дочерних процессов, каждый дочерний процесс обрабатывает одно подключение. Из-за того что процесс - более тяжелая структура, он использует немного больше ресурсов, зато он менее подвержен сбоям - обработка каждого отдельного запроса не зависит от других процессов.

К сожалению, для смены mpm требуется перекомпиляция apache. Тут проявляют свои достоинства source-based дистрибутивы: вы можете легко перекомпилировать apache и все зависимые от него пакеты, не превратив систему в свалку. Бинарные дистрибутивы выходят из этой ситуации по-разному. Например в RHEL в apache rpm находится сразу две версии apache - с worker и prefork mpm (prefork используется по умолчанию). Однако worker mpm не поддерживает php. Так что если вы хотите php и worker mpm вам придется компилировать его самостоятельно либо искать сторонние репозитории.

DNS запросы


Директива HostnameLookups включает reverse DNS запросы, так что в логи будут попадать dns-имена клиентов вместо ip-адресов. Разумеется, что это существенно замедляет обработку запроса, т.к. запрос не обрабатывается пока не будет получен ответ от DNS-сервера. Поэтому следите чтобы эта директива всегда была выключена (HostnameLookups Off), а если вам все-таки нужны dns-адреса, вы можете узнать их позже, прогнав лог в утилите logresolve (которая поставляется с apache).

Кроме того, следите чтобы в директивах Allow from и Deny From использовались ip-адреса а не доменные имена. Иначе apache будет делать два dns запроса (обратный и прямой) чтобы убедиться что клиент-тот за кого себя выдает.

AllowOverride


Если директива AllowOverride не установлена в 'None', apache будет пытаться открыть .htaccess файлы в каждой директории которую он посещает и во всех директориях выше нее. Например:

DocumentRoot /var/www/html
<Directory /var/www/html/>
AllowOverride all
</Directory>

Если будет запрошен /index.html, apache попытается открыть (и интерпретировать) файлы /.htaccess, /var/.htaccess, /var/www/.htaccess, и /var/www/html/.htaccess. Это увеличивает время обработки запроса. Так что, если вам нужен .htaccess только для одной директории, разрешайте его только для нее:

DocumentRoot /var/www/html
<Directory />
AllowOverride None
</Directory>
<Directory /var/www/html/>
AllowOverride all
</Directory>

FollowSymLinks и SymLinksIfOwnerMatch


Если для директории включена опция FollowSymLinks, сервер будет следовать по символическим ссылкам в этой директории. Если для директории включена опция SymLinksIfOwnerMatch, apache будет следовать по символическим ссылкам только если владелец файла или директории, на которую указывает эта ссылка совпадает с владельцем указанной директории. Так что при включенной опции SymLinksIfOwnerMatch apache делает больше системных запросов.

Кроме того, дополнительные системные запросы требуются когда FollowSymlinks НЕ УСТАНОВЛЕН. Т.о. наиболее оптимальная ситуация для производительности - когда опция FollowSymlinks включена.

Content Negotiatio


Старайтесь избегать content negotiaion.

MaxClients


Директива MaxClients устанавливает максимальное количество параллельных запросов, которые будет поддерживать сервер. Apache не будет порождать больше процессов/потоков чем MaxClients. Значение MaxClient не долно быть слишком маленьким (иначе много клиентов останутся необслуженными), но и не стоит устанавливать слишком большое количество - лучше не обслужить часть клиентов чем исчерпать все ресурсы, залезть в своп и умереть под нагрузкой. Хорошим может быть значение MaxClients = количество памяти выделенное под веб-сервер / максимальный размер порожденного процесса или потока. Для статических файлов apache использует около 2-3 Мб на процесс, для динамики (php, cgi) - зависит от скрипта, но обычно около 16-32 Мб.

Вы можете прикинуть примерный размер посмотрев на колонку rss в выводе `ps -ylC httpd --sort:rss`

Если сервер уже обслуживает MaxClients запросов, новые запросы попадут в очередь, размер которой устанавливается с помощью директивы ListenBacklog.

MinSpareServers, MaxSpareServers, и StartServers


Т.к. создание потока, и особенно процесса - дорогая операция, apache создает их заранее. Директивы MaxSpareServers и MinSpareServers устанавливают как много процессов/потоков должны ожидать в готовности принять запрос (максимум и минимум). Если значение MinSpareServers слишком маленькое и неожиданно приходит много запросов, apache вынужден будет создавать много новых процессов/потоков, что создаст дополнительную нагрузку в этой стрессовой ситуации. С другой стороны, если MaxSpareServers слишком велико, apache будет сильно нагружать систему этими процессами, даже если количество клиентов минимально.

Постарайтесь установить такие MinSpareServers и MaxSpareServers, чтобы apache не создавал более 4 процессов/потоков в секунду. Если он создаст более 4, в ErrorLog будет помещено сообщение об этом. Это - сигнал того что MinSpareServers слишком мало.

MaxRequestsPerChild


Директива MaxRequestsPerChild устанавливает сколько запросов может обработать один дочерний процесс/поток прежде чем он будет завершен. По умолчанию значение этой директивы установлено в 0, что означает что однажды созданный процесс/поток не будет завершен никогда (ну кроме случаев остановки сервера или краха этого процесса/потока). Рекомендую установить MaxRequestsPerChild равное какому-нибудь достаточно большому числу (несколько тысяч). Это не создаст излишней нагрузки, связаной с тем что apache будет вынужден создавать новые дочерние процессы, в то же время это поможет избавиться от проблем с утечкой памяти в дочерних процессах (что очень возможно например если вы используете нестабильную версию php).

KeepAlive и KeepAliveTimeout


KeepAlive позволяет делать несколько запросов в одном TCP-подключении. Это особенно полезно для html-страниц с большим количеством изображений. Если KeepAlive установлен в Off, то для самой страницы и для каждого изображения будет создано отдельное подключение (которое нужно будет обработать master-процессу), что плохо и для сервера и для клиента. Так что для подобных случаев рекомендуется устанавливать KeepAlive в On. Для других применений (например для download-сервера) KeepAlive может быть бесполезен и даже вреден, т.к. при включенном KeepAlive сервер закрывает соединение не сразу, а ждет KeepAliveTimeout секунд нового запроса. Для того чтобы процессы не висели слишком долго в бесполезном ожидании, устанавливайте KeepAliveTimeout достаточно малым, около 5-10 секунд обычно достаточно.

Сжатие


HTTP-сжатие было определено в стандарте HTTP/1.1, и сейчас все современные клиентские программы и практически все сервера его поддерживают. Сервер может отдавать ответ в gzip или deflate, а клиентская программа незаметно для пользователя разжимает данные. Это уменьшает количество передаваемого трафика (до 75%), но конечно же повышает использование процессора.
Однако если ваш сервер посещает много клиентов с медленным подключение, сжатие может снизить нагрузку с вашего сервера из-за того что сервер сможет быстрее передать сжатый ответ и освободить ресурсы, занятые дочерним процессом. Особенно сильно этот эффект может быть заметен если у вас быстрый процессор, но мало памяти.

Кеширование конфигурируется директивами модуля mod_deflate. Имейте в виду, что не следует устанавливать степень сжатия gzip более 4-5 - это потребует существенно большего времени CPU, а эффект будет достаточно невелик. Ну и разумеется не нужно пытаться сжать изображения в jpg, gif и png, музыку, видео файлы и все другие бинарные файлы, которые уже и так хорошо сжаты.

Кеширование на стороне клиента


Не забывайте устанавливать Expires заголовки на статические файлы (см. модуль mod_expires). Если файл не изменяется, то его всегда следует попробовать закешировать на клиенте. Тогда у клиента будут быстрее загружаться страницы, а сервер освободится от лишних запросов.

Оригинал: "Configuring Apache for Maximum Performance". Vishnu Ram V: http://linuxgazette.net/123/vishnu.html

Как изменить настройки сетевой карты в linux

Вопрос: Как отключить авто-определение сетевых настроек (auto-negotiation) моего серевого интерфейса и установить полу/полно-дуплексный режим из коммандной строки? Как просмотреть текущие настроки?

Используйте ethtool:


ethtool eth0 # показывает текущие настройки


Пример вывода:

Settings for eth0:
Supported ports: [ TP MII ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
Advertised auto-negotiation: No
Speed: 10Mb/s
Duplex: Half
Port: MII
PHYAD: 32
Transceiver: internal
Auto-negotiation: off
Supports Wake-on: pumbg
Wake-on: d
Current message level: 0x00000007 (7)
Link detected: yes

Другие примеры:

ethtool -s eth0 duplex half autoneg off - Выключает автоопределение, включает half-duplex
ethtool -s eth1 duplex full speed 1000 autoneg off - Выключает автоопределение, включает Full Duplex и устанавливает скорость в 1000 Mb/s.

Оригинал: http://www.linuxscrew.com/2008/11/20/faq-how-to-change-duplex-andor-auto-negotiation-nic-settings-in-linux/

GNU Screen: как "промотать" окно вверх

Screen - очень полезная и удобная утилита. Но при ее использовании часто возникает вопрос: как просмотреть что-то что произошло раньше и не влезает в экран. Стандартные Ctrl+PageUp не работают.

Для того чтобы решить эту проблему, нужно перевести screen в режим копирования сочетанием клавиш Ctrl + a, [ или Ctrl + a, Esc.

После этого можно перемещаться стандартными стрелочками или следующим способом:

h - Передвинуть курсор влево
j - Передвинуть курсор на строку вниз
k - Передвинуть курсор на строку вверх
l - Перевинуть курсор вправо
0 - Передвинуть курсор в начало строки
$ - Передвинуть курсор в конец строки
G - Передвинуть курсор в указаную строку
C-u - Промотать вверх пол страницы
C-b - Промотрать целую страницу вверх
C-d - Промотать вниз пол страницы
C-f - Промотрать целую страницу вниз

Для того чтобы указать количество строк используйте параметр h:


screen -h 5000


Для тех кто не знает: screen - утилита, которая позволяет запускать несколько приложений в "виртуальных" консолях, что очень удобно например при работе с ssh.

Оригинал: http://www.linuxscrew.com/2008/11/14/faq-how-to-scrollback-in-gnu-screen/