воскресенье, 19 сентября 2010 г.

GearMan: распараллелевание и комуникация

Если вы сталкиваетесь с ресурсоемкой задачей, то приходится решать вопросы связанные с балансом нагрузки внутри системы, риском единой точки отказа , повышением скорости ответа системы и т.д. Для этого используются вспомогательные системы очередей сообщений. Прочитать про подобные системы можно в статье "Очередь сообщений - что это и зачем?". В нашем текущем проекте мы используем сервер Gearman для организации и распределения задач, по сути это сервер очереди сообщений. Кроме всего прочего сервер имеет реализации API для разных языков, это Perl, PHP, Python, Java, C#/.NET, а так же для JMS и баз данных PostgreSQL и MySQL.
В двух словах что же представляет собой работа с применением сервера Gearman.  Сервер является диспетчером сообщений к которому присоединяются клиентские части системы. Эти части делятся на два вида, назовем их воркеры и клиенты. Воркеры это части системы которые производят некоторую обработку данных, эту обработку и требуется распараллелить. Клиенты это части системы, которые требуют некой обработки данных и ради этого используют воркеры через сервер Gearman. Как это выглядит в проекте? Сложные ресурсоемкие процессы реализованы на Java и являются воркерами. Вэбклиент PHP использует эти процессы через сервер Gearman. Благодаря наличию API для разных языков программирования можно организовать эффективное взаимодействие внутри очень сложной системы с высоким уровнем изоляции частей друг от друга.
Что потребуется для подключение к серверу Gearman? Понадобится сам сервер и коннектор к нему для Java. Коннектор скачать можно вот отсюда. С ним все просто, достаточно подключить jar как библиотеку к своему проекту, при желании можно порыться в исходниках. При установки самого сервера могут потребоваться добавочные реепозитории. В этом вам могут помочь, особенно если вы используете Ubuntu, следующие ссылки: статья блога PHP+Gearman и некая документация.
С чего начать? Для начала не требуется какого-то массового курения мануалов. Достаточно заглянуть в пример, который идет вместе с коннектором в том же jar файле. Для этого изучите содержимое пакета  package org.gearman.example;
 
В качестве демонстрации простоты использования приведу несколько строк кода.
Worker: создать воркер из класса "WorkerClass" и зарегистрировать его

       List<Сlass<GearmanFunction>> functions = new ArrayList<Class<GearmanFunction>>();

       Class c = null;

       try {

           c = Class.forName(WorkerClass.class.getCanonicalName());

       } catch (ClassNotFoundException ex) {

       }

       functions.add((Class) c);

       new WorkerRunner(host, port, functions).start();





Client: создать клиента и вызвать необходимый воркер


         final GearmanClient client = new GearmanClientImpl();
        boolean addJobServer = client.addJobServer(new GearmanNIOJobServerConnection("192.168.0.0", Constants.GEARMAN_DEFAULT_TCP_PORT));
        byte[] data = ByteUtils.toUTF8Bytes("some data");
        GearmanJobResult res = null;
        final GearmanJob job = GearmanJobImpl.createJob(WorkerClass.class.getCanonicalName(), data, nill);
        client.submit(job);
        try {
            res = job.get();
        } catch (InterruptedException ex) {
            System.err.println(ex);
        } catch (ExecutionException ex) {
            System.err.println(ex);
        }
        String value = ByteUtils.fromUTF8Bytes(res.getResults());
        rc.shutdown();