Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Архитектура проекта, взаимодействие между компонен 
:(
    Опции темы
slippery
Дата 23.4.2016, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 2.7.2007

Репутация: нет
Всего: нет



Добрый день. Попробую описать задачу: был большой проект на JAVA, со временем проект еще больше рос и вносить правки в монолитное приложение было все тяжелее. Тогда было принято решение часть функционала выносить в «сервисы» с которыми ядро будет общаться по REST, но при этом сервисы выполняя вынесенную логику напрямую обращались в базу ядра для записи и чтения данных. То есть это не сервисы, а просто вынесенная часть бизнес логики за пределы монолитного ядра. Между собой сервисы информацией не обмениваются, они работают либо как демоны(выполняя какую-то логику по крону например и изменяя данные в бд), либо принимают http запросы со стороны ядра, вынимают данные из бд, преобразовывают из и отдают ядру. Так же есть сервисы со своим хранилищем(азой), к примеру полнотекстовой поиск, но он опять таки для составления поискового индекса сервис напримую ходит в БД за данными. Со временем появилась идея все же сделать так называемые сервисы более независимыми и начать с того, перекрыть им возможность прямого доступа к данным.

Доступ к данным был разделен на 2 категории:

1. модификация(было решено делать через события и шины сообщений(брокер))
2. Чтения данных. И вот тут возник вопрос, как лучше его сделать. Пока на ум приходят 3 варианта:
2.1. оставить возможность сервисам читать данные напрямую из БД
2.2. делать методы внутренного api на стороне ядра(не хотелось бы, так как лищний раз трогать ядро не стоит)
2.3. оборачивать sql запрос построенный в сервисе в какой-то объект, пересылать его ядру http запросом, уже в ядре проверить, что это именно select, выполнить и вернут ответ обратно сервису в ввиде массива json. А сервис уже его пропарсит в нормальный список объектов с которым и будет работать.

К сожалению проект очень большой и переписать его нет возможности, стоит задачу как можно меньшей кровью улучшить его архитектуру и взаимодействие ядра с сервисами «сервисами».

Хотелось бы узнать мнение знатоков по вопросам:

1. нормальная ли это схема в данном случаи(разделение чтения и записи)?
2. какой из вариантов для чтения предпочесть?
3. если все же использовать вариант с пересылкой упакованного sql запроса и выполнения его ядром, какой фрэймворк посоветуете? Я вот обратил внимание на JOOQ не знаю подойдет ли он для этого или нет?

Заранее благодарен.

PM MAIL   Вверх
drgnav
Дата 24.4.2016, 12:59 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Добрый день.
Как видно, имеем приложение с прохой архитектурой, в которой слои бизнес-логики, представления и доступа к данным тесно переплетены. Согласно теории J2EE архитектуры, для рефакторинга Вам следует применить шаблоны Front Controller и Serwice to Worker, но это потребует серьезной переработки кода. В вашем случае, если запись и чтение  разнесли, то прямой доступ к данным допустим, можно использовать шаблон Fast Lane Reader, но нужно иметь в виду его рекомендации - только для чтения больших объемов данных.


Этот ответ добавлен с нового Винграда - http://vingrad.com
  Вверх
jsharp36
Дата 24.4.2016, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



Ой.
Тут даже в постановке вопроса ошибки. Я лично яростно против, когда думают об "архитектурах", отдельно от задачи. Т.е. ошибка в том, что вы создаете конструкции. Отдельно от смысла. Код - это передача смысла, а не конструкции. Так он должен восприниматься.
Как текст в книге. Не пишут же:
"Катасрел корнокрнул белза, зактрев накрязь." - Сложноподчиненное предложение, красивая правильная структура. Только полная фигня написана. Вот так выглядят люди, которые "строят архитектуры", не ставя в первую очередь смысл.

В общем, могу только проранжировать в сторону ухудшения, какие решения лучше/хуже, но в зависимости от задачи иногда то что лучше, не всегда лучше, приходится выбирать из многих зол.
1. Лучше делать слои, в одном монолите.
2. Нужно понимать, чем код от экземпляров. Не нужно дублировать работу. Но можно дублировать экземпляры. Например, можно написать одну библиотеку, а использовать в разных модулях многократно и одновременно. Поэтому написав слой доступа к базе данных и, например, единственную библиотеку с сущностями для ORM, можно использовать в разных модулях. Это к вопросу от том, дергать ли ядро при доступе к базе.
не обязательно. Минус только в том, что не будет единой точки доступа и не будет способа какого-то общего кеширования.

И скажу, что разделять код на сервисы - самое ужасное что можно придумать. Три проекта видел, которые так убили. Просто нереально стало и поддерживать и смерть с т.з. производительности. Причем каждый раз "архитекторы" задумывали такую архитектуру, полагая, что она будет самой оптимальной и производительной - на разные машины поставят. В итоге это работало хуже, чем калькуляторы в 2000м году. Всё съедали комуникации между сервисами и простаивание. Т.е. с сервисами и код усложняется, работы программистам увеличивается. И еще и с т.з. производительности идея тупиковая.

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

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

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
jsharp36
Дата 24.4.2016, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



Цитата

   2.3. оборачивать sql запрос построенный в сервисе в какой-то объект, пересылать его ядру http запросом, уже в ядре проверить, что это именно select, выполнить и вернут ответ обратно сервису в ввиде массива json. А сервис уже его пропарсит в нормальный список объектов с которым и будет работать.
   


В текущем проекте моему серверу веб-клиенты должны сами формировать любые запросы-фильтры, с order by. Т.е. без group by.
Я он них не получаю никаких селектов, опасно это. Специальный оговоренный объект получаю в json, в котором абстрактное синтаксическое дерево фильтра, order by указан. Всё это разбирается и формирую правильный SQL-запрос. И возвращаю им выборку в джейсоне.
Можно и так. Я как разработчик сервера, разгрузил себя и разработчики клиентов не дергают меня по каждому поводу. Плюс появилась возможность пользователям самим настраивать динамически фильтры, какие они захотят.

Вы смотрите, что у вас за сервис, насколько он ваш и безопасен. Чтобы не дать возможность для sql иньекции.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
drgnav
Дата 24.4.2016, 15:36 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











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

Извините что потревожил ваше самолюбие.

До свидания.

Этот ответ добавлен с нового Винграда - http://vingrad.com
  Вверх
mbasil
Дата 24.4.2016, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 399
Регистрация: 4.5.2007
Где: Москва

Репутация: 9
Всего: 13



1. Раз у вас уже имеются работающие сервисы, зачем отступать назад в сторону монолитного приложения ?
2. Если SQL предложение готовиться внутри сервиса, а не на клиенте использование использование PreparedStatement и bind (в случае JDBC)? а также тщательная проверка вводимых клиентом параметров обезопасят от впрыскивания злонамеренного SQL кода.
3. Читать и писать отдельными сервисами это нормально. При использовании мелкогранулированныйх сервисов "писателей" возникает проблема транзакционной безопасности, но надо только обеспечить жесткий контроль и разделение "писателей".
4. Конечно разделение на слои крайне желательнодля обеспечения масштабируемости, возможностей быстрой модификации и контроля кода. Кто будет возражать сегодня против отделения Web слоя от бизнес слоя и доступа к базе. Неукоснительное следование паттерну DAO нам поможет.
5. Похоже вы уже двигаетесь в направлении микросервисов. Почитайте статью М.Фаулера (хоть она и давнишняя). Рядом с вашей темой затесался мой вопрос по REST, как то он с вашим вопросом перекликается (я думаю).
6. Архитектурные решения не догма, а руководство к действию. И конечно нет смысла, вы правы, бросаться рефакторить систему в целом (ругать чужую архитектуру легко - а надо ли, коли дело уже сделано).
7. Важнейшим вопросом в случае вашего решения является поиск стандартных решений и подходов к точкам интерфейса между сервисами и ядром. Количество сервисов наверняка будет расти, а старые будут изменяться. Возможно в дальнейшем некоторые функции ядра будут переноситься в новые сервисы. И в этом случае интрфейс взаимодействия это то место, где легко споткнуться.
И я бы не стал слушать критику тех, кто ратует за возврат к монолиту от сервисов под предлогом критики "плохой" архитектуры. Каждый сервис сам по себе может (и должен) иметь четко определенную структуру разбитую на слои (как минимум выделенный DAO). Главное, чтобы все это хозяйство было (по возможности) типизированным со стандартными интерфейсами взаимодействия и строго документированным. А в остальном архитектура часто диктуется множеством факторов (проблемной обастью, историей проекта и т.д), которые нам на сей момент неизвестны.

PM MAIL   Вверх
jsharp36
Дата 24.4.2016, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



Коллега, 12 лет опыта (все время проектировал). Каждая моя фраза говорит не об не знании, что такое архитектура, а о презрении к дебилизму, который на каждом шагу встречается, от "архитекторов".

Понимаете, всё что городят, вот так, такое мирровозрение складывается на втором третьем году работы. Так называемое подражание. Когда почитают книгу "банда 4-х" и тыкают куда не попадя патерны, городят конструкции и онанируют на архитектуры )) Сори что грубо, но это так.

А те люди, которые разрабатывают как я, это уже люди с 7-10 лет опыта работы, которые изучали много языков, отлично понимают, что такое KISS, YAGNI, DRY. Которые в одиночку делают проекты, серверы, которые не снились команде из 10 человек (якобы опытных, считающих себя синьйорами).

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

Мое себялюбие не потревожено, пока )

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
jsharp36
Дата 24.4.2016, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



Цитата

   1. Раз у вас уже имеются работающие сервисы, зачем отступать назад в сторону монолитного приложения ?
   


Ничего по этому поводу не могу сказать, я текущий код не видел. Вдруг там еще не далеко зашли?
Поясню, почему монолит (в смысле, один процесс, без модулей) лучше. Язык программирования - это язык. Т.е. подобен естественному. На нем пишутся "мысли". Т.е. помните у Платона был мир идей и мир вещей? Например, чертеж поезда - это мир идей. Чернила, которыми нарисован чертеж - мир вещей.
Создавая границы в виде разных сервисов, вы смешиваете мир идей и мир вещей. Т.е. представьте, что автор в книге бы писал роман, и разбивал бы не на главы, а ссылался на книги с каким-то переплетом, с каким-то цветом обложки. (следующую главу вы прочитаете в красненькой книжке).
Вот такая же фигня по сути происходит, когда делают инкапсуляцию с помощью физических границ, а не смысловых.

Когда как в языке программирования, прямо в языке, есть все конструкции, чтобы выражать инкапсуляцию.
Да, я не утверждаю, что это на все случаи жизни хватит. Конечно, нужны и модули и разные сервера и сервисы иногда. Но чтобы понимали. Мое мировоззрение - всё что мы делаем - это плохо. Но можно сделать еще хуже. Выбираем меньшее зло. Пока можно обходиться без сервисов, без чего-то усложняющего - обходимся. Может случиться, что не сможем и сервисы будут полезными.

В общем, может вы правы, может нет, я не в курсе что там в проекте, пусть решает ТС.

Цитата

   2. Если SQL предложение готовиться внутри сервиса, а не на клиенте использование использование PreparedStatement и bind (в случае JDBC)? а также тщательная проверка вводимых клиентом параметров обезопасят от впрыскивания злонамеренного SQL кода.
   


Да, всё верно. Я и писал, пусть ТС смотрит, насколько безопасный модуль и насколько свой. У нас пару модулей индусы пишут, я бы не полагался на их SQL запрос )) Если внутри сервиса - Ок, не надо усложнять. В моем текущем проекте это не упрощение, потому что клиент, и потому что я сам тоже использую это же внутри сервера. Проект на .net и там лямбды генерятся, так что с шарпа напрямую пишутся легко запросы (почему не стандартная ORM, долго рассказывать).

Цитата

   3. Читать и писать отдельными сервисами это нормально. При использовании мелкогранулированныйх сервисов "писателей" возникает проблема транзакционной безопасности, но надо только обеспечить жесткий контроль и разделение "писателей".
   


Да как сказать. И всё нормально и всё плохо. В общем случае это плохо, в некоторых частных, нормально и отлично решает задачу.
Поясню. Реляционная СУБД делается так, чтобы можно было сравнительно легко моделировать предметную область, СУБД проверяет целостность данных. Так вот, практически вся работа СУБД - это разруливание очереди запросов. Приходят запросы на чтение и запись, в некоторой очередности. Они собираются в очередь и вся хитроумная работа СУБД в том и заключается, как бы разрулить эту транзакционность.

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

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

Цитата

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


Смайликов нету. Все архитектуры плохие. Но дна нет, бывают хуже )) Вопрос баланса. Пусть ТС смотрит, что ему проще.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
mbasil
Дата 24.4.2016, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 399
Регистрация: 4.5.2007
Где: Москва

Репутация: 9
Всего: 13



Вот ссылочка https://habrahabr.ru/post/249183/ на перевод статьи о микросервисах Мартина Фаулера и Джеймса Льюиса, о которой я писал.
Мы же помним о современной тенденции "loose coupling", которая в противовес монолитным приложениям имеет явную тенденцию движения по направлению к микросервисам. Не думайте, что я поборник этой архитектуры в противовес монолитной (может и мне этот подход кажется для небольших приложений чрезмерно сложным и могущим приводить к серьезным проблемам).
И конечно, если бы я захотел похвастаться, то сообщил бы сразу, что имею сертификаты OCP по разработке и администрированию Oracle (версий от 8 до 10) и уже 15 лет читаю авторизованные курсы Oracle и еще 12 лет назад начал читать авторизованные курсы SUN java (включая архитектурные). Но что толку меряться..., мы все, как вы совершенно справедливо изволили заметить коллеги.
И все же хотел бы добавить, что при использовании множества мелких "писателей" в базу проблему транзакционной целостности данных простыми средствами СУБД не решить, так как в силу архитектурых особенностей (не ругайте только за чрезмерное употребление слова "архитектура") Вы, либо вынуждены фиксировать транзакцию в рамках одного сервиса, либо использовать распределенные транзакции. И то и другое - не подарок при проектировании. Но кто сказал, что микросервис обязательно должен быть "мелким". Во всяком случае эту проблему нельзя считать незначительной и надеяться на СУБД.
PM MAIL   Вверх
jsharp36
Дата 24.4.2016, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



ну да, меряться не стоит, я хотел бы на этом ресурсе оставаться "инкогнито". ))

Я в курсе про некоторые тенденции у Фаулера. Я с ним не согласен. И не только я (чтобы не пришло в голову кому-то, что мое эго вдруг противопоставило себя Фаулеру ))

Тут дело вот в чем. Многие любители "архитектурить" действительно любят говорить о гибкости, о "loose coupling".
А я вот считаю, что программа должна быть жесткой.
Ну не совсем, просто у меня приоритеты другие. Я не считаю, что программа должна быть изначально гибкой и гибкость для меня не является первейшим приоритетом.

Это отсылка к YAGNI. Вопрос о предугадывании требований.

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

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

Т.е. гибкость тоже важна, только она не должна быть "преждевременной".


Я не против архитектур и сервисов и микросервисов. Лишь бы это было обосновано. Не вижу в этом ничего "красивого". Нужны основания для того, чтобы использовать этот подход. Возможно, такие основания у ТС есть и возможно вы не так поняли мою критику. Не критикую я, а просто советую смотреть на развитие проекта такими глазами как у меня. А они точно не такие, раз не описав ни разу задачу, хотя бы приблизительно, что проект решает, ТС просит совета - как решить эту задачу.

Ну это долгий разговор, и видимо не нужно здесь в такую философию ударяться

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
jsharp36
Дата 24.4.2016, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



Спасибо за статью, почитал. Я это и так знал, но именно на хабре не читал.

Ну в общем, стремно всё это. Давайте разберем. Там много пространных рассуждений о легкости развертывания. Ну я бы сказал, что чушь ) Не видел ни разу, чтобы сервисы упрощали развертываение. Но, если вы скажете, что это можно автоматизировать и довольно безболезенно развертывать, соглашусь. но точно так же и монолит можно разверывать, автоматизировать. Я такой ерундой не занимался, но сделайте два сервака, или два процесса, и при развертывании запускается другой новый монолит, а старый живет до конца обработки запроса. Да, это стремно, база еще. Но не вижу чем лучше микросервисы. Каждый из них создает маленькую проблему, а в сумме получается большая. Каждый может быть недоступным.

Но все это немного лукавство. Потому что дело в языке, в выражении смысла, в кодировании. Это работа программиста, а не развертывание. Он решает задачу, бизнес-требования, а инфраструктура - это сопуствующая работа, не прямая. Так вот сопуствующая работа не должна становиться главной.
Я вот к чему. Для того, чтобы писать безболезненно такие микросервисы, возможно стоит подумать про подходящий язык. Erlang. Вот на нем такое пишется, и вы не думаете о том, как что там будет разворачиваться, как подменяться процессы. Бывшие мои колеги успешно его применили в автоматизации работы одной платежной системы.

А вот в Java (или C#) это чревато. И вот почему. Что такое шина данных? Ладно, если это будет RabbitMQ. Куда ни шло. Он хорош, что скроет полностью каналы при минимум кодирования. Будет порождать объекты уже на концах. Поэтому стиль кодирования не намного изменится. Но боюсь, что любители архитектур лукавят. И на самом деле хотят часто писать свою шину просто потому, что это приводит к динамической типизации. Т.е. я сколько не видел говнокода астронавтов архитектурных, вся их любовь к гибкости выражается другими словами: "ненавижу статическую типизацию". Ведь статическая типизация - это жестко. А они хотят гибко. Чтобы можно было подменять что угодно, любые компонетны.

Не тот язык они выбрали. Писали бы на каком-то object-C. Слали бы любому объекту сообщения.


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

В общем, если там уже так оно есть, то у меня такой же совет как в статье: минимизируйте общение между сервисами. Если сервис просто целиком решает задачу, от приема запроса клиента, до базы данных, не общаясь с другими - гуд. Поэтому лучше если сервис надежный и свой, на своей машине - работал бы прямо с базой. И заметьте, что если запрос и обработка происходит вертикально, без общения с другими сервисами, то то же самое, что написать всё в одном  сервисе/сервере, а потом их накопировать и написать менеджер, который будет перенаправлять менее загруженным сервисам запросы. Горизонтальное масштабирование.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.1491 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.