Допустим вам нужно обрабатывать http-запросы в своём приложении... Пишем на servlet-ах! Spring!! ЕщёКакойТоФреймворк!!!
A теперь нам нужно слушать websocket... Выбор сужается? А завтра потребуется добавить поддержку SMPP или какого-нибудь ещё "необычного" протокола? Рано или поздно вам прийдётся создать консольное java-приложение и начать изучать "встраиваемые" сервера. Встроить можно много чего, но что если фантазия разработчиков "с той стороны internet-а" родит совсем уже неведомый протокол? И тут мы вспомним о Netty. На его основе можно реализовать практически что угодно, при чём такая универсальность не пойдёт в ущерб ни производительности ни простоте. Чтобы подтвердить свою мысль я ниже сделаю свой "крошечный" http-сервер, в который можно будет добавлять "сервлетообразные" обработчики, "навешивая" их на url с помощью аннотаций.
Решения конкретных задач программирования. Java, Android, JavaScript, Flex и прочее... Настройка софта под Linux, методики разработки и просто размышления.
четверг, 6 февраля 2014 г.
пятница, 24 января 2014 г.
Handler - маленький помошник Android разработчика
Всем привет, хочу поделиться методологией применения инструмента созданного облегчить разработку приложений (на сцену выходит Handler).
В кратце android.os.Handler это абстракция позволяющая "выполнять" в указаной очередности другие абстракции - события. А что же такое событие? На реализации событиями являются android.os.Message и обычные Runnable.
В кратце android.os.Handler это абстракция позволяющая "выполнять" в указаной очередности другие абстракции - события. А что же такое событие? На реализации событиями являются android.os.Message и обычные Runnable.
Немного по делу. Знакомо CalledFromWrongThreadException? Если да, то runOnUiThread не будет открытием, иначе все впереди:). Рано или поздно у каждого из нас возникает необходимость обновить views после получения данных которое чаще всего выполняется в другом(не главном) потоке. "AsyncTask!" - скажите вы, "Отлично!" - отвечу я. Что общего между runOnUiThread и AsyncTask? Версия выхода не считается;)
Давайте посмотрим на реализацию в фреймфорке.
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
}
private static class InternalHandler extends Handler {
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]);
break;
.........................
}
}
}
Давайте посмотрим на реализацию в фреймфорке.
Случай №1:
public final void runOnUiThread(Runnable action) {if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
Случай №2. Реализация вызова onPostExecute в AsyncTask:
private Result postResult(Result result) {Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
}
private static class InternalHandler extends Handler {
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]);
break;
.........................
}
}
}
четверг, 16 января 2014 г.
Делаем алгоритм шардинга. Два решения: простое и красивое
Надеюсь все знают что такое шардинг. Ну а если вы всего лишь "слышали об этом где-то", то вы по-своему счастливый человек. Шардинг данных это решение "последнего выхода", когда никакие другие оптимизации системы хранения данных вроде индексации, денормализации и кластеризации уже не помогают. При шардинге вы берёте свою таблицу (или коллекцию для noSQL) размером в десять миллионов записей и разрезаете её, к примеру, на 10 таблиц по миллиону. Эти таблицы могут лежать в разных базах (нодах) на разных серверах. Так мы получаем то, за что разработчики высоконагруженных проектов так любят шардинг: бесконечное горизонтальное масштабирование. Чтобы определить для каждой записи ноду в которую её нужно положить или где её следует потом искать мы должны реализовать алгоритм определения ноды исходя из ключа и общего числа нод. Для записей определённой структуры с заранее известным "ключевым" полем это сделать несложно. Если вы режете таблицу пользователей с инкрементным id в качестве ключа, то можно просто определить диапазоны id для каждой ноды. То же самое при разбиении набора записей с датой в качестве ключа. Но возьмём тяжёлый случай: ключ имеет произвольную структуру. Это не последовательное число и не дата. Просто строка. Как гарантированно отнести такой ключ к определённой ноде?
Ниже я предложу два решения: первое я сочинил сам, второе "подсмотрел" в исходниках jedis - популярного "драйвера" для подключения java-приложений к noSQL хранилищу Redis.
Подписаться на:
Сообщения (Atom)