Thursday, December 11, 2008

Java API для Sape.ru

Выложил в публичный доступ когда-то написанный интерфейс для работы с биржей ссылок SAPE.ru. Описание, а также исходники можно посмотреть на Google Code, адрес такой http://javasape.googlecode.com/. Комментарии можно ссылать по мылу или писать прямо в этом посте.

Thursday, October 23, 2008

Интересный способ мониторинга рабочих сайтов

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

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

В этом случае можно воспользоваться утилитой jstack которая входит в состав JDK начиная с версии 1.5.0. Эта утилита позволяет просмотреть текущее состояние работающих в указанной виртуальной машине потоков (которые thread). Например,
user@laptop$ jstack 3344 "btpool0-439" prio=10 tid=0xa98da000 nid=0x1b3a in Object.wait() [0xa99ff000..0xa99ff130] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:482) - locked <0xb47e0078> (a org.mortbay.thread.BoundedThreadPool$PoolThread) "Java2D Disposer" daemon prio=10 tid=0xaa35c800 nid=0xb2e in Object.wait() [0xa9fd4000..0xa9fd50b0] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) - locked <0xaf007a30> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) at sun.java2d.Disposer.run(Disposer.java:125) at java.lang.Thread.run(Thread.java:619) Для каждого потока показаны его атрибуты, в том числе его название, и стектрейс.

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

Например, очевидными кандидатами на добавление в название потока являются адрес страницы, которая обрабатывается и логин пользователя. Код по добавлению этой информации логично разместить в HTTP-фильтре. Фрагмент его будет выглядеть приблизительно так:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String threadName = getUser().login + ": " + RequestInfo.get().getRequestUrl(); Thread.currentThread().setName(threadName); chain.doFilter(request, response); } Теперь, если в выводе jstack будет часто видно, например, такое
"medved: /heavy/calculation" prio=10 tid=0x9aa9a800 nid=0x2519 runnable [0x9ad18000..0x9ad 190b0] java.lang.Thread.State: RUNNABLE at com.site.heavy.calculation.Calc.inner(Calc.java:113) at com.site.heavy.calculation.Calc.outer(Calc.java:43) значит, для пользователя medved медленно показывается страница /heavy/calculation. Это уже можно профилировать.

Названия потока удобно использовать также в других случаях отладки, например, записать в него User-Agent, и тогда прямо в стектрейсе ошибки будет видно, под каким браузером она возникла.

Monday, October 13, 2008

Консерваторы и демократы

(Не удержался, чтобы не перепостить - уж очень понравилось.)

Я спросил несовершеннолетнюю дочь своих друзей, кем бы она хотела быть, когда вырастет. Она сказала, что хотела бы когда-нибудь стать Президентом Соединённых Штатов Америки. Оба счастливых родителя, либеральные демократы, присутствовавшие при разговоре, с гордостью переглянулись. Я спросил девочку: "Хорошо, допустим ты стала Президентом, что бы ты сделала в первую очередь?"

Она ответила: "Первым делом я бы предоставила пищу и жильё всем бездомным".

"Чудесно, - согласился я, - весьма достойная цель! Но вовсе не обязательно ждать того времени, когда ты станешь Президентом. Можно уже сейчас начать действовать в соответствии с твоим планом. Приходи ко мне в дом, выполи сорняки в саду, постриги траву на лужайке, подмети двор, и я заплачу тебе пятьдесят долларов. Тогда ты сможешь пойти к лавке, возле которой валяется один из бездомных, и вручить ему свои $50 на покупку еды или для сбережений в счёт покупки будущего дома".

Она надолго задумалась. Её мать смотрела на меня так выразительно, что я не берусь истолковывать её взгляд. В конце концов девочка подняла глаза и спросила: "Почему бы тогда этому бездомному самому не прийти к вам домой и не сделать эту работу - тогда вы бы прямо ему и заплатили эти 50 долларов?"

Я ответил: "Добро пожаловать в ряды консерваторов, дочка!"

Её родители до сих пор со мной не общаются...

Источник: http://art-of-arts.livejournal.com/

Thursday, October 9, 2008

Устанавливаем на Amazon EC2 и Amazon EBS Java-приложение с MySQL

На примере типичного сайта опишу последовательность действий по установке на хостинг Amazon.

Приложение - сайт на Java, который требует большой вычислительной мощности. Поэтому было принято решение сразу запускаться на Amazon. В работе сайт использует на чтение-запись базу MySQL. Сайт будет развернут на одном экземпляре (instance) Elastic Computing Cloud (EC2). База MySQL - на томе (volume) Elastic Block Storage (EBS). Все пользовательские данные будут храниться в MySQL. На диске экземпляра будут храниться настройки, а также скрипт сборки приложения, который будет собирать приложения из внешних источников (например, из репозитария Subversion).

Далее в тексте, при описании вводимых команд, если приглашение оболочки начинается на $ - команду следует выполнять на локальном компьютере, если приглашение начинается на # - на удаленном экземпляре EC2.

Установка утилит EC2 и настройка окружения

  1. Заходим на http://aws-portal.amazon.com, логинимся, покупаем EC2. На страницах нужно будет найти и запомнить Access Key ID, Secret Access Key и Account ID. Также нужно сгенерировать и сохранить файл с сертификатом X.509 (cert-11111111111111.pem) и файл с приватным ключем (pk-11111111111111.pem).
  2. Устанавливаем Amazon EC2 Command-Line Tools.
    1. Скачиваем с Amazon.
    2. Распаковываем в нужное место (например, /usr/ec2).
    3. Прописываем окружение (вариант для Linux): pupkin@local$ export EC2_HOME=/usr/ec2/ec2-api-tools-1.3-19403 pupkin@local$ export PATH=$PATH:$EC2_HOME/bin pupkin@local$ export EC2_PRIVATE_KEY=/home/pupkin/mega-project/ec2/pk-11111111111111.pem pupkin@local$ export EC2_CERT=/home/pupkin/mega-project/ec2/cert-11111111111111.pem
    4. Проверить, правильно ли установлены утилиты можно, выполнив команду ec2-describe-images. Результатом команды будет список доступных для запуска образов виртуальных машин (AMI): pupkin@local$ ec2-describe-images -a IMAGE ami-5586623c 1fm2knh6gyecefa34102-phe-bucket/image.manifest.xml 437711880492 available public i386 machine IMAGE ami-63ec090a 1VYRBPTAGB3GRJD3N902-AMI-082407/image.manifest.xml 681122512140 available public i386 machine IMAGE ami-18cf2a71 1VYRBPTAGB3GRJD3N902-AMI-110407-dev/image.manifest.xml 681122512140 available public i386 machine ...

Настройка экземпляра

В качестве ОС выбираем Ubuntu Linux. За основу берем образ Ubuntu 8.04 LTS Hardy от alestic.com. Дальше доставим туда необходимые Java, MySQL и всё остальное.
  1. Запускаем экземпляр с нужным образом.
    1. Ищем последний по дате нужный образ. Выбираем base (лишнего нам не надо) и 64-битную платформу (нашему сайту будет нужно много памяти). pupkin@local$ ec2-describe-images -a |grep ubuntu |grep alestic |grep 64 IMAGE ami-17d7337e alestic-64/ubuntu-8.04-hardy-base-64-20080924.manifest.xml
    2. Генерируем ключик для доступа к экземпляру по SSH pupkin@local$ ec2-add-keypair pstam-keypair и сохраняем его в файле, например, /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair.
      Если используется OpenSSH, для этого файлы нужно выставить правильные права доступа: pupkin@local$ chmod 600 /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair
    3. Запускаем выбранный экземпляр pupkin@local$ ec2-run-instances ami-17d7337e -k pstam-keypair -t m1.large RESERVATION r-4073a129 701161471898 default INSTANCE i-1b903272 ami-17d7337e pending pstam-keypair 0 m1.large 2008-10-02T12:54:37+0000 us-east-1b aki-b51cf9dc ari-b31cf9da i-1b903272 - это идентификатор экземпляра. Он будет нужен позднее.
      pending - означает, что экземпляр в процессе запуска.

      Ждем 15 секунд, и выполняем команду pupkin@local$ ec2-describe-instances RESERVATION r-4073a129 701161471898 default INSTANCE i-1b903272 ami-17d7337e ec2-75-101-241-247.compute-1.amazonaws.com domU-12-31-39-01-59-41.compute-1.internal running pstam-keypair Статус должен поменяться на running. Если не поменялся - нужно подождать еще.
      Когда статус поменяется на running, в таблице будет видно внешний (ec2-75-101-241-247.compute-1.amazonaws.com) и внутренний (domU-12-31-39-01-59-41.compute-1.internal) адреса экземпляра. Внешний адрес используется для доступа к экземляру из интернета, внутренний - с других инстансов (если такие будут).
  2. Открываем доступ к экземпляру по нужным портам: pupkin@local$ ec2-authorize default -p 22 pupkin@local$ ec2-authorize default -p 80 проверяем pupkin@local$ telnet ec2-75-101-241-247.compute-1.amazonaws.com 22
  3. Логинимся на экземпляр и устанавливаем нужные пакеты pupkin@local$ ssh -i /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair root@ec2-75-101-241-247.compute-1.amazonaws.com root@domU-12-31-39-01-59-41# apt-get update root@domU-12-31-39-01-59-41# apt-get install mysql-server root@domU-12-31-39-01-59-41# apt-get install apache2 root@domU-12-31-39-01-59-41# apt-get install sun-java6-jdk root@domU-12-31-39-01-59-41# apt-get install zabbix-agent root@domU-12-31-39-01-59-41# apt-get install subversion root@domU-12-31-39-01-59-41# apt-get install postfix root@domU-12-31-39-01-59-41# apt-get install mailx Дополнительные пакеты можно будет поставить и позднее, при необходимости.

Настройка Elastic IP

При каждом старте экземпляре ему выдается новый IP-адрес. Чтобы при этом избежать проблем с DNS-ом, закажем также Elastic IP. pupkin@local$ ec2-allocate-address ADDRESS 75.101.137.69 pupkin@local$ ec2-associate-address -i i-1b903272 75.101.137.69 ADDRESS 75.101.137.69 i-1b903272 - это идентификатор экземляра. Если вы его забыли, можно посмотреть командой ec2-describe-instances). Теперь этот адрес можно (и нужно) прописать в DNS, например, связав с именем http://mega-project.pupkin.com.

Настройка EBS

  1. Создаем том. pupkin@local$ ec2-create-volume -s 200 -z us-east-1b us-east-1b - зона, или датацентр Amazon. Её нужно выбрать такой же, в какой запущен экземпляр, чтобы не гонять лишний трафик. Посмотреть зону экземпляра можно командой ec2-describe-instances. Ждем пока поднимется, смотрим информацию о томах: pupkin@local$ ec2-describe-volumes VOLUME vol-2a08ed43 200 us-east-1b available 2008-10-02T15:50:14+0000
  2. Подключаем том к инстансу pupkin@local$ ec2-attach-volume -i i-1b903272 vol-2a08ed43 -d /dev/sdd1
  3. Для новосозданного тома создаём и монтируем файловую систему на экземпляре pupkin@local$ ssh -i /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair root@ec2-75-101-241-247.compute-1.amazonaws.com root@domU-12-31-39-01-59-41# mkfs -t ext3 /dev/sdd1 root@domU-12-31-39-01-59-41# mkdir /mnt/db root@domU-12-31-39-01-59-41# mount /dev/sdd1 /mnt/db Монтирование /dev/sdd1 в /mnt/db нужно прописать в /etc/fstab. Тогда при перезапуске экземпляра том примонтируется автоматически.

Настройка ПО

  1. MySQL MySQL нужно перенести из папки по умолчание (/var) на EBS в раздел с данными (мы его смонтировали в /mnt/db).
    1. Останавливаем MySQL. root@domU-12-31-39-01-59-41# /etc/init.d/mysql stop * Stopping MySQL database server mysqld
    2. Копируем уже созданную БД. root@domU-12-31-39-01-59-41# mkdir /mnt/db/lib /mnt/db/log root@domU-12-31-39-01-59-41# mv /var/lib/mysql /mnt/db/lib/ root@domU-12-31-39-01-59-41# mv /var/log/mysql /mnt/db/log/ root@domU-12-31-39-01-59-41# test -f /vol/log/mysql/mysql-bin.index && perl -pi -e 's%/var/log/%/vol/log/%' /vol/log/mysql/mysql-bin.index
    3. Правим конфиг. root@domU-12-31-39-01-59-41# vim /etc/mysql/my.cnf Раздел mysqld должен быть таким [mysqld] innodb_file_per_table datadir = /mnt/db/lib/mysql log_bin = /mnt/db/log/mysql/mysql-bin.log max_binlog_size = 1000M log_slow_queries = /mnt/db/log/mysql/mysql-slow.log long_query_time = 10
    4. Запускаем. root@domU-12-31-39-01-59-41# /etc/init.d/mysql start
  2. Собственно сайт
    1. Создаём пользователя, под которым будет работать сайт (если сайт сделан в виде отдельного процесса). root@domU-12-31-39-01-59-41# /usr/sbin/adduser mega-project
    2. Пишем скрипт сборки, который
      • чекаутит последнюю версию сайта из репозитария Subversion;
      • делает сборку;
      • перезапускает сайт из новособранной версии.
    3. Запускаем скрипт, настраиваем конфиги приложения, запускаем приложение. Теперь можно зайти на http://mega-project.pupkin.com/ и посмотреть на работающий сайт :)

Сохраняем образ тома

Чтобы не потерялась проделанная работа, нужно сохранить образ настроеного экземпляра. Сохраненный образ также пригодится, если экземпляр нужно будет перезапустить, для поднятия кластера и др.
  1. Копируем ключи и сертификат - они будут нужны на экземпляре. pupkin@local$ cd /home/pupkin/mega-project/ec2/id_rsa-pstam-keypair pupkin@local$ scp -i id_rsa-pstam-keypair id_rsa-pstam-keypair root@ec2-75-101-241-247.compute-1.amazonaws.com: pupkin@local$ scp -i id_rsa-pstam-keypair pk-11111111111111.pem root@ec2-75-101-241-247.compute-1.amazonaws.com: pupkin@local$ scp -i id_rsa-pstam-keypair cert-11111111111111.pem root@ec2-75-101-241-247.compute-1.amazonaws.com:
  2. Собираем пакет с файлами root@domU-12-31-39-01-59-41# ec2-bundle-vol -e /tmp -d /mnt -k pk-11111111111111.pem -c cert-11111111111111.pem -u <Account ID без символов -> -p mega-project-image -s 1500 1500 - размер образа. На стоимость хранения не оказывает влияния, но при небольших размерах быстрее архивируется (перед хранением) и быстрее стартует экземпляр.
    Размер образа должен быть не меньше, чем размер примонтированной на / файловой системы.
    Если значение размера будет слишком маленьким, команда ec2-bundle-vol может выдать сообщение об ошибке execution failed: "rsync ... "
  3. Заливаем собранный пакет в Amazon Structured Storage Service (S3). root@domU-12-31-39-01-59-41# ec2-upload-bundle -b pupkin-images -m /mnt/mega-project-image.manifest.xml -a <Access Key Id> -s <Secret Access Key>
  4. С локальной машины регистрируем пакет как образ.
  5. pupkin@local$ ec2-register pupkin-images/mega-project-images.manifest.xml Всё, дело сделано :).

Возникшие проблемы и вопросы

  1. Почему-то MySQL сразу при старте начинает сильно загружать процессор. Полечилось перезапуском MySQL.
UPD. При переносе данных MySQL в другую папку нужно также поправить настройки apparmor (в /etc/apparmor.d/usr.sbin.mysqld) и logrotate (в /etc/logrotate.d/mysql-server)

Sunday, July 20, 2008

Веломандрівка 12-13 липня

Веломандрівка 12-13 липня 2008.
В яку міні-відпустки вирішив проїхатися велосипедом по дорогам Центральної України. Маршрут планувався на два дні такий. 12 липня - Київ-Васильків-Фастів-Сквира. 13 липня - Сквира-Погребище-Турбів-Вінниця-Гнівань. За перший день вийшло записати звіт, за другий уже бажання сидіти за комп'ютером пропало, видно, відстань далася взнаки :).

Отже, почалося все звечора 11 липня.

Звечора 11-го боролися дві ідеї. Одна - тепер середина літа, їхати буде жарко, треба пораніше (о 6-ій, наприклад), встати, аби відповідно рано виїхати, і по спеці не їхати. Інша - останні дні я не висипався, тож треба подовше поспати аби бути в формі. За підтримки ліні друга ідея перемогла :)

0 км. Отже, виїхав я без десяти дев'ять. Вирішив з Києва виїзжати черед Одеську площу на трасу Київ-Одеса до Василькова. Виявилося, що виїхати з Києва в суботу зранку - напряжна штука. Машин - тьма, на Московській площі вічна реконструкція, повітря сизе, всюди пилюка. Побачивши врешті-решт табличку з перекресленим написом "Київ", я вже геть вхеканий. Але, правда, далі було краще.

Приблизно 20 км. Доїхав без особих пригод до Великої Окружної за Глевахої. То була перша помилка - те, що прийняв за окружну, виявилось поворотом Одеської траси ). Я ж повівся на вказівник "Васильків", і поїхав прямо на міст (там під міст - Одеська траса, а на міст - дорога на Васильків. З одного боку у Василькові цікаво - бачив базу тактичної авіації, ліцей екології НАУ (рідна альма-матір), саме місто таке нерівне, вверх і вниз. З іншого боку, то був вийшов гак кілометрів з 10, ще й по нерівному. В центрі Василькова дядько показав, як доїхати до Фастова - для того треба було вернутися на знову на Одеську. Добре хоч не в те місце, з якого з'їхав ). На виїзді на окружну стояли дайці. В одного з них я попитав, як проїхати на Фастів - він впевнено назвав кілометрах в 10 в напрямку Одеси. І я йому повірив, хоча треба було всього лише переїхати Одеську трасу ). Але в результаті воно на краще й вийшло. Даїшник ще довго допитувався - чи я спортсмен, чи нє. Видно, йому за власне пузо було соромно )).

Трохи про карту, по якій їхав. Може то карта для авто і непогана, але на велосипеді по ній їхати неможливо. По ній можно тільки брати орієнтири - наступне село таке-то, а потім - таке-то. А дорогу роспитувати. Занадто вже крупний масштаб - на поворотах зорієнтуватися неможливо. Та що там повороти, там досить великі села попропущені, навіть по кілька зараз.

40 км. Доїхавшли до села, про яке сказав даїшник, і подившись на карту, я зрозумів, що повертати на Фастів пізно - занадто велике коло буде, якщо на Сквиру їхати. Вирішив їхати далі по Одеській, і не доїзжаючи Білої Церкви звернути і виїхати на Сквиру селами. Це було дуже прикольне рішення. Дорога - мрія (краще, ніж Одеська траса), машин - одна на 10 хвилин, справа соняхи, жита-пшениця. В одному місці гречка так пахла, що в пору було падати ).

Десь 80 км. Це було трохи пізніше. А перед цим вирішив пообідати якраз на з'їзді з Одеської траси, у містечку Гребінки (не путати з Гребінкою). Напитав обід аж у третьому кафе - всюди весілля були, видно на Петра-і-Павла одружуватися - хороша прикмета ). Кафе знайшов якраз на повороті на село, через яке мені їхати треба було - Устимівку. Поворот той, до речі, тяжко знайти - треба бути уважним. В кафе ціни виявилися більшими, ніж в Києві, а от якість гірша. Прийшлося брати об'ємом. Почав обідати в 12.40.

Після обіду вирішив повалятися, повідпочивати - якраз година дня була. Знайшов наче гарну місцину, розвалився. Тут напали комарів, за 15 хвилин обкусали здорово, тим самим відразу появилося бажання їхати далі ). Виїхав в 14.05. По дорозі безліч раз доводилося питати дорогу - в тому місці карта зовсім не відповідала дійсності (трохи пізніще згадаю, і опишу села, через які проїзжав).

Десь 90 км. Після обіду виявилось їхати напряжно. Якщо до обіду намагався тримати 30 км за годину, то перші години після обіду ледве тримав 26, а далі і 20 не міг втримати. До Сквири виявилося далі, ніж я очікував. Це такий психологічний момент - ніколи не треба розраховувати, що до цілі залишилося мало. Краще сказати більше, але не буде неприємного розчарування і упадку сил, як наслідок, коли тієї цілі все не буде і не буде.

По дорозі проїзжав багато сіл із дуже гарними ставками. Підходив до води, умивався, але купатися не ризикнув, хоча багато людей сиділо у воді.

130 км. Нарешті (була 18.00) доїхав до Сквири, чому порадувався дуже ). Останніх 10 км їхалося на нервах ). Напитав дорогу до хлібзаводу, де був готель, поселився (18.15) - і чудо, у них була гаряча вода. Покупавшись, вирішив прогулятися, і натрапив у центрі міста інет-кафе, з якого і пишу. По дорозі в інет-кафе випив півлітри кваси, і півлітри коли - дуже вже присушило. Не забути зайти в магазин, купити на завтрашню дорогу водички (тра попробувати на зміну мінералці солодкої), і цукерок.

Умови їзди. Після обіду трохи стих вітер (а зранку добре південно-західний, від чого було прохолодно, але тяжкувати їхати). Після Василькова переважно дорога йшла вниз, і було менше перепадів, ніж до нього.
Асфальт був переважно хорошої якості по всій дорозі.
Дуже допомагали їхати гарні поля навколо доріг, особливих захват викликали соняхи.

Із проблем - попік руки коло ліктів і ще трішки ноги над колінами (де закінчилися шорти). І німіли постійни долоні - мізинці не розніміли до сих пір.

Середня швидкість до обіду трималася 24 км, після обіду впала до 21,5. Трохи перетружені стегна, і досить сильна крепатура на плечах і особливо шиї. Ще хочу відмітити якість тупість по дорозі - тяжко було запамёятати по дві назви сіл підряд, тільки на одне вистачало, далі приходилося знову карту дивитися )).

Ще відпочивав трохи частіше, ніж очікував, але менше. Думаю, це через те, що убився трохи при виїзді з Києва (і при подоланні Василькова).

В результаті, за перший день було проїхано 130 км, за другий - 160 км. Отримав масу цікавих та нових вражень.

Wednesday, May 21, 2008

Докатились... 4,55 грн за доллар

Сегодня НБУ официально объявил о снижение официального курса доллара США к гривне до 4,85 грн за доллар. На протяжение последних несколько недель коммерческий курс доллар постоянно падал, на сегодня на межбанке доллар покупали на 4,55. Наличный курс также опустился до 4,55.

С инфляцией бороться нужно конечно, но это как то уж слишком. Хроники кризиса ликдвидности:

Январь-апрель 2008. НБУ и Кабмин проводят активную стерилизацию средств (накапливают деньги на счетах Казначейства). Остатки банков на корсчетах в НБУ понижаются с 20 млрд в январе до 13 млрд на 18 апреля.
21-13 апреля 2008. Недостаток денежных средств давит на позиции банков в ценных бумагах. Ставки overnight поднялись до 30%, при среднем значение 11%. Проблемы с ликвидностью ведут к обвалу фондового рынка. Индекс ПФТС падает за два дня 21-13 апреля на 10%.
19-21 мая. Скоро опять 20-е число, банкам и предприятиям пора платить в бюджет, но у них нет гривны, поэтому они продают валюту себе в убыток. Курс USD начинает снижаться, и достигает в среду значения 4,55 (и даже 4,5). Ситуация разогревает заявление чиновников НБУ о возможности ревальвация гривни. Большое количество людей, получающих зарплату в долларах, начинает нервно подсчитывать падение своих доходов.
20-21 мая. По слухам, с ПФТС выходят нерезиденты, ловя курсовую разницу. На ПФТС начинается падение, 5% за два дня.
21 мая. НБУ объявляет о снижении курса доллара.

Ситуация для меня непонятная. Почему в стране с ухудшающейся экономической обстановкой, с отрицательным сальдо внешнеторгового баланса, растет нац.валюта ? Чем этот рост будет поддерживаться ?

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

UPD. Похоже, намечается тенденция - 20 числа ужесточаются проблемы с ликвидностью, и доллар падает. После 20 (21, 22) доллар начинает расти. Два месяца уже так. Нужно посмотреть, можно ли этим воспользоваться.

Friday, May 16, 2008

OpenAds и русские буквы

Уже достаточно долго для показа баннеров я использую баннеровертелку OpenX (раньше называлась OpenAds, http://www.openx.org/). Для интеграции с сайтами, которые не используют PHP (а большинство у меня на Java), в OpenX используется XML-RPC.

Ну почему софт на PHP всегда такой глючный!

XML-RPC сервер в OpenX всегда возвращает ответ в кодировке UTF-8. Однако среди поддерживаемых OpenX кодировок нет UTF-8. Для русских символом есть koi8r и windows-1251. И когда в описании баннера присутствуют русские символы (в моем случае - в windows-1251), они не преобразовываются в UTF-8. В результате мой XML-RPC клиент от Apache выдает сообщение:
org.apache.xmlrpc.client.XmlRpcClientException: Failed to read servers response: Invalid byte 2 of 2-byte UTF-8 sequence.
at org.apache.xmlrpc.client.XmlRpcStreamTransport.readResponse(XmlRpcStreamTransport.java:179)
at org.apache.xmlrpc.client.XmlRpcStreamTransport.sendRequest(XmlRpcStreamTransport.java:145)
at org.apache.xmlrpc.client.XmlRpcHttpTransport.sendRequest(XmlRpcHttpTransport.java:94)
      ...
В списке рассылки Apache XML-RPC пользователи жалуются на похожую проблему, на что разработчики XML-RPC резонно отвечают, что это проблема сервера, и решать ее они в принципе не будут. Но баннеры нужно показать. Поэтому правим немного XML-RPC клиент. В метод
org.apache.xmlrpc.client.XmlRpcStreamTransport.readResponse
ставим первую строку
InputSource isource = new InputSource(ResponseFilter.filter(pStream));
и сам клас ResponseFilter
public class ResponseFilter {
  public static InputStream filter(InputStream input) {
      StringWriter s = new StringWriter();
    
      try {
          InputStreamReader r = new InputStreamReader(input, "windows-1251");
        
          int ch;
          while ((ch = r.read()) != -1) {
              s.write(ch);
          }
        
          input.close();
      } catch (IOException e) {
          throw new RuntimeException(e);
      }
    
      return new ByteArrayInputStream(s.toString().getBytes());
  }
}
Теперь работает.

Wednesday, February 13, 2008

Литература всякая нужна ...

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

Если пользу от таких книг можно назвать тактической, то чтение хорошей художественной литературы приносит пользу в большем масштабе.

Художественная литература позволяет лучше понять самого себя, тем самым способствует постановке действительно ценных и важных целей. А ничто так не повышает личную эффективность, как осознанная и важная для себя цель.

Пример из личного. Только прочитав недавно "Вино из одуванчиков", я окончательно определился, что для меня будет более подходить дом в пригороде, нежели квартира в центре города.

Желаю и Вам, и себе правильного баланса времени между срочными и важными и задачами :).

Tuesday, February 12, 2008

Поехали

Буду писать в этом блоге о деньгах и проектах, о профессиональном и личном росте, о сайте Мой инвестиционный портфель, о разработке софта и просто свои мысли.

Пописав личный дневник в ЖЖ, хочется теперь уделить внимание темам, которые, как я надеюсь, будут интересны большему большому количеству читателей.