Pull to refresh

Comments 34

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

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

Хотелось бы понять, конечно.

У вебсокета асинхронная двусторонняя связь — push нотификации. Он работает по http — не требуется дополнительной настройки сетевых экранов. Добавляем https и мы не видны для антивирусов — по умолчанию они не сканируют защищенный канал (некоторые блокируют ответ от сервера по незащищенному каналу). Установка клиента на рабочее место заключается в простом копировании ярлыка, который скачивает бинарники и без дополнительных настроек запускает клиента. Ранее использовалась технология RMI, которая работала на сокете по определенному порту и требовался администратор для установки на новое рабочее место. Так как к окружению применялись высокие требования безопасности, то все порты кроме 80 были закрыты по умолчанию.

Лично мне ещё больше стало непонятно. Ну сделайте сокет на 80/443, он тоже асинхронный и полнодуплексный. Всё что тут написано делится на «то же самое в обычном сокете» либо «причём тут вообще веб-сокеты» (копирование ярлыка? бинарники?).
То есть, вы предлагаете создать ServerSocket на 80 порту в рамках сервера приложений, и ServerSocket на 443 порту клиента. Реализовать дуплексное общение через две пары сокетов, а также взять на себя всю инфраструктуру сессий, обработки исключительных ситуаций, например, обрыв соединения, работу через прокси сервер и многое другое, что уже есть в готовых решениях с реализацией веб-сокетов. Думаю, что тогда бы мой серверный сокет на 80 порту (если бы он вообще запустился) нарушил бы корректную работу сервера приложений, на котором есть и другие приложения, например, с веб-интерфейсом.

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

На стороне java-сервера крутится javaee — сервер приложений, с готовой реализацией веб-сокетов. Библиотека, которую он использует предлагает готовый веб-сокет клиент. В моем случае нецелесообразно было вестись на мнимую производительность собственного кода и обременять себя поддержкой еще и сокетных решений.

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

Не читал статью, но хочу сказать, что вебсокеты вполне можно использовать вместо обычных сокетов, оверхед фактически только на подключение, дальше идёт очень простой бинарный протокол вида <размер пакета><данные>, что все равно придется придумывать для обычных

Зато если, как водится, внезапно захочется перейти на тонкий клиент, то придется переписывать только клиент.
Нет. Там передаются сериализованные Java объекты. Придется как-то имитировать эти объекты на стороне JS и тащить сложную сериализацию/десериализацию вместо того же JSON.
Java-cериализация при необходимости может быть заменена на любой другой способ. Берем тот же Jakson и сериализуем в JSON. На java-сериализацию завязки нет. Просто не было смысла, так как обе стороны java.
Тот же jackson объекты просто и понятно сериализует в json и обратно, так что сторона js будет как раз очень рада, поскольку json ей родной и близкий.
Если не ошибаюсь, есть проблема, когда у тебя Date лежит в Map. Приходится что-то дополнительно прописывать, а то он дату сериализует в число, а обратно, не может понять к чему это число привести.

Задачи интеграции с js-клиентом и обменом json не ставилось.
Если не ошибаюсь, есть проблема, когда у тебя Date лежит в Map. Приходится что-то дополнительно прописывать, а то он дату сериализует в число, а обратно, не может понять к чему это число привести.

Я в работе, по привычке использую JodaTime, плюс никогда не перевожу в-из json непосредственно в бизнес-сущности, у меня всегда есть промежуточное звено назначение которого как раз в конвертации. Позволяет держать нутро «не осведомленным» о том, что его в какой-то момент времени будут конвертировать и представлять в json, или обратно.
Делал похожее на Spring + REST. github.com/StanislavLapitsky/SpringSOAProxy

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

Еще надо бы Service Discovery впилить, но руки не доходят пока.

Согласен с предыдущими комментаторами. Если нужна двусторонняя связь проще просто на сокетах, а не втаскивать вебсокеты.
В том то и дело, что не просто двусторонняя связь, нужны и все плюшки контейнера сервера приложений.
В WildFly/JBoss что то похожее есть «из коробки». Не знаю, используются ли web-сокеты, но рукоблудить с кодом точно не нужно:

env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
env.put(Context.PROVIDER_URL, "http-remoting://localhost:8080");
Интересно, что лежит под этой фабрикой в WildFly. В Glassfish/Payara, тоже есть из коробки, правда работает оно по устаревшей RMI-технологии. Увы, но на WildFly переехать в свое время не получилось — слишком много надо было менять в инфраструктуре серверного кода (вот такая вот заменяемость контейнеров в javaee).
слишком много надо было менять в инфраструктуре серверного кода (вот такая вот заменяемость контейнеров в javaee)

— сделать приложение не переносимым, это заслуга разработчика/архитектора, технология тут не виновата. Если в кроссплатформенной Java написать:
File f = new File("C:/myfile.txt");

она тоже перестанет быть кроссплатформенной, но это не значит что виновата технология. Во всяком случае на JavaEE можно писать приложения с минимальными модификациями при переносе, если об этом побеспокоиться изначально.
Согласен с тем, что, если об этом беспокоится заранее, то переехать можно. Но на практике убедился, что каждая реализация стандарта отходит от него в той или иной степени, создавая полезный функционал, которого в стандарте нет. Если этим полезным функционалом не пользоваться, то при переезде проблемы будут минимальны. А если от него отказаться, то приходится платить временем разработки и тешить себя при этом мыслью о том, что вот если мы будем переезжать… Это уже каждый сам решает, технологии не при чем.
использование ws позволяет их использовать как для связи сервера с браузером, так и с десктопным/андроид приложением. по поводу портов — библиотека tomcat работает по 80 порту. github.comту./TooTallNate/Java-WebSocket работает по любому порту.
Самый простой способ связать клиент и сервер в Java это JAX-WS. Обращаю внимание что это работает начиная с Java 6 и не требует ни одной библиотеки или сервера, только голый SDK

Фрагмент Кода
	// server side
        MyService serv = new MyService();
        Endpoint.publish("http://localhost:9000/", serv);

	// client
        QName portQName = new QName("my", "MyServiceService");
        Service service = Service.create(new URL("http://localhost:9090/services/hello?wsdl"), portQName);
        IService client = service.getPort(IService.class);
        System.out.println(client.echo("hello"));


        @WebService(name = "MyService", targetNamespace = "my")
        public interface IService {
            String echo(String s);
        }

А если передавать не простые типы, а экземпляры своих классов, разве не потребуется дополнительных аннотаций на стороне сервера или клиента?
Кое-где надо будет. Особенно если что-то хитрое сериализуется а-ля енамы, но в целом всё гуманно. Сервер и клиент могут шарить DTO, а также интерфейс.

Привык делать так, чтобы не отвлекаться на подобные ситуации. Одно дело, когда только сам используешь для себя, другое дело еще всем коллегам надо помнить о том, что где-то надо что-то подписать. По моему опыту этого никто не помнит, а когда выстреливает, то тратится большое количество времени на решение проблемы.

Там где требуется сериализация, без аннотаций не обойтись. Как минимум, надо пометить какие поля не надо сериализовывать. А если коллега не может правильно подписать, то это неправильный коллега
ws — full duplex, и для браузера и для приложения. один для всех. и очень маленький трафик.

Джавовский RMI в его основе — это совсем не про то, как клиенту что-то вызвать на сервере через Java Proxy. RMI — это распределенная сеть, там нет ни сервера, ни клиента, есть только peer-s. Любой Remote-объект может быть передан по сети любому из peer-ов точно также как и обычный, например в качестве параметра к удаленному методу или поля объекта. При реализации истинного RMI вам придется решать такие задачи как call-routig, call-forwarding, service discovery, и distributed garbage collector.


Может быть то, что вы хотели сделать, уже существует?

Feign, очень интересная библиотека. Надо будет ее подробнее изучить. Спасибо! На момент написания основы библиотеки (~2015г.) про feign не знал, да и если честно не искал. Почему-то был уверен, что подобного никто не пишет. Сейчас бы, наверное, доработал бы его под свои нужды.

Ну как это никто не пишет? Даже джавовский почти стандартный Jersey умеет уже давно проксировать клиента. Причем один и тот же аннотированный интерфейс можно использовать как для клиента, так и для сервиса.

JAX-WS и REST не стал использовать, так как в серверном коде требуются дополнительные аннотации на каждый метод, а при сериализации сложных структур еще и на классы передаваемые в качестве аргументов или возвращаемые в качестве результата. Мой подход требует, чтобы ejb (
@Stateless
или
@Singleton
) реализовывал интерфейс и имел определенное имя. Этого достаточно, чтобы его можно было вызвать с клиента через proxy.
не требуются аннотации на каждый метод

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

Теоретически — да. Но если в системе много разных сервисов и необходимо поддерживать работу с интерфейсами разных версий, то стандартная сериализация уже не очень удобна, так как в ней нет удобных механизмов разрешения конфликтов. Jackson тут заметно удобнее.
Многоверсионность никогда поддерживать не приходилось. Обновляю клиента и сервер за раз.
Ну, если нужно обновлять большой кластер с кучей сервисов без простоя, то без версионности не обойтись.
Sign up to leave a comment.

Articles