Связка Windows Azure & Java позволяет разработчику подключаться по удаленному рабочему столу (Remote Access, Remote Desktop Protocol (RDP)) к виртуальным машинам, выполняющим приложение. Для конфигурации удаленного доступа вам необходимо сконфигурировать соответствующим образом вкладку Remote Access в свойствах проекта (рис.1).
Рис.1. Окно свойств проекта – настройки удаленного доступа
По умолчанию каждый новый проект Windows Azure имеет включенную возможность удаленного доступа, основанную на использовании самоподписанного сертификата (который, кстати, идёт в тестовом варианте в комплекте с Windows Azure Plugin для Eclipse, и находится в папке cert в проекте Windows Azure). Данный самоподписанный сертификат имеет две части – файл публичного сертификата (SampleRemoteAccessPublic.cer) и файл сертификата типа Personal Information Exchange (SampleRemoteAccessPrivate.pfx), который содержи�� в себе приватный ключ для сертификата и пароль по умолчанию (Password1). Естественно, что данный сертификат не должен быть использован в реальном развертывании (достаточно префикса Sample). Вы можете использовать для целей удаленного доступа либо этот сертификат, либо воспользоваться способом, приведенным в данной статье.
В первой статье цикла был создан проект, поэтому этого касаться в данной статье я не буду.
Давайте настроим удаленный доступ для вашего проекта. Для этого:
Рис.2. Настройка удаленного доступа к ролям приложения.
Рис.3. Настройки самоподписанного сертификата.
Рис.4. Настройка самоподписанного сертификата.
Рис.5. Настройка удаленного доступа – окончание.
Перейдите на вкладку Windows Azure (рис. 6).
Рис. 6. Настройка облачного проекта для развертывания в облако.
На вкладке Windows Azure выберите Deployment to cloud.
Соберите ваш проект – Project –> Build All (CTRL + B).
Залогиньтесь на портал управления Windows Azure под своим аккаунтом.
Создайте вычислительный сервис, который будет выполнять код вашего приложения. На левой панели нажмите Hosted Services и нажмите кнопку New Hosted Service, расположенную в меню. В диалоговом окне Create a new Hosted Service выберите вашу подписку из выпадающего списка Choose a subscription.
Введите имя сервиса в текстовое поле Enter a name for your service и укажите URL, введя соответствующее значение Enter a URL prefix for your service, например, <yourname>guestbook, где <yourname> должно быть уникальным именем. Windows Azure использует это значение для создания URL точек входа в сервис.
Примечание: Портал производит проверку доступности и соответствия правилам имени. Если имя не пройдёт проверку, будет выведено сообщение об ошибке.
Рис. 7. Добавление нового сервиса.
Как вы видите, нам доступно развертывание нашего сервиса в облако сразу же при создании сервиса-контейнера. Нажмите Browse Locally для обоих файлов и найдите их в папке deploy вашего проекта. После этого нажмите на кнопку Add Certificate для добавления сертификата.В открывшемся диалоге Upload Certificate нажмите в поле Certificate file кнопку Browse. В диалоге Open укажите местоположение вашего файла PFX. Далее укажите пароль в текстовом поле Password, который вы задавали ранее для вашего файла сертификата.Нажмите Ok.
Рис. 8.
При нажатии OK вам будет выведено предупреждение о том, что для выполнения SLA необходимо как минимум два экземпляра для роли. Нажмите Close и Ok.
Дождитесь окончания развертывания роли.
Рис. 9.
Убедитесь, что развертывание прошло успешно и имеет статус Ready.
Рис. 10. Успешное развертывание.
Теперь необходимо подключиться удалённо. После успешного развертывания вы можете подключиться к вашей виртуальной машине приложения. Для этого перейдите на вкладку Hosted Services, Storage Accounts & CDN на портале управления Windows Azure, выберите необходимый для подключения экземпляр роли и нажмите кнопку Connect (в секции Remote Access).
Рис. 11.
При нажатии на кнопку Connect вам будет предложено подключиться к экземпляру роли по RDP с помощью файла подключения. Откройте файл и введите пароль, который указали для подключения в настройках удаленного доступа To enable Remote Access in your package.
Session Affinity
Windows Azure Plugin для Eclipse with Java позволяет использовать HTTP session affinity (другое название – “липкие сессии для ролей”). Настройки данной функциональности находятся в диалоге Load Balancing.
Рис. 12. Настройки Session Affinity.
Для того, чтобы найти данный диалог, необходи��о либо на вкладке Roles нажать Add, либо сконфигурировать уже имеющийся экземпляр роли – щелкнув правой кнопкой мыши на WorkerRole1 и нажав Properties, после чего необходимо развернуть Windows Azure Role и нажать Load Balancing. В появившемся диалоге Properties for WorkerRole1 Load Balancing отметьте опцию Enable HTTP session affinity (sticky sessions) for this role и выберите конечную точку входа для использования (Input endpoint to use). Если у вас еще не сконфигурирована точка входа, плагин предложит вам создать стандартную точку входа http (public:80, private:8080). Естественно, что можно сконфигурировать множество точек входа, но для липких сессий можно указать только одну.
Рис. 13.
Соберите ваш проект – Project –> Build All (CTRL + B). Теперь, после включения липких сессий, запросы HTTP, приходящие от клиентов, будут обрабатываться одним и тем же экземпляром ролей. Это позволяет делать гибкую обработку и реализовывать хранение состояния сессий. Необходимо уточнить, что данный механизм реализуется тем, что плагин установливает модуль IIS Application Request Routing в каждый из экземпляров вашей роли и, таким образом, маршрутизирует HTTP-запросы, сначала заворачивая их на себя, после чего отправляя их по соответствующим экземплярам.
Что необходимо учитывать при работе с липкими сессиями:
Липкие сессии и Session Affinity не работают в локальном эмуляторе вычислений. Здесь всё понятно – так как вычисления только эмулируются, не может быть никаких дополнительных установок модулей.
К уже и так разросшемуся архиву вашего приложения добавляется дополнительный объем за счет скачивания дополнительных приложений.
Запуск и инициализация ролей происходят дольше.
Добавляет внутренняя конечная точка входа для реализации маршрутизации.
Сохранение состояния сессий с помощью механизма Session Affinity
Так как у нас уже имеется готовый проект со страницей .JSP, например, как в моем случае, это NewFile.jsp, мы можем реализовать сохранение состояния сессий. Нам пригодится еще один файл для просмотра того, как всё это работает – newsession.jsp.
Ваш итоговый файл JSP должен выглядеть в соответствии с кодом ниже. Обратите внимание, что используется дополнительный код из предыдущей статьи! Код взят с MSDN.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" import="com.microsoft.windowsazure.serviceruntime.*, java.util.Map, java.util.*,java.text.DateFormat" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Hello</title></head><body> <b>Hello Azure!</b> <br/> <p> RoleEnvironment.isEmulated() возвратил <%=RoleEnvironment.isEmulated() %>.</p> <p>Идентификатор экземпляра роли равен <%= RoleEnvironment.getCurrentRoleInstance().getId() %>.</p> <p>Имя роли: <%= RoleEnvironment.getCurrentRoleInstance().getRole().getName() %>.</p> <% Map<String, RoleInstanceEndpoint> endpoints = RoleEnvironment.getCurrentRoleInstance().getInstanceEndpoints(); for (Map.Entry<String, RoleInstanceEndpoint> entry : endpoints.entrySet()) { out.println("Точка входа '" + entry.getKey() + "' : " + entry.getValue().getIpEndPoint().getAddress().getHostAddress()); } Map<String, LocalResource> localresources = RoleEnvironment.getLocalResources(); Set set = localresources.entrySet(); Iterator iterator = set.iterator(); LocalResource localResource; while (iterator.hasNext()) { Map.Entry entry = (Map.Entry)iterator.next(); localResource = (LocalResource) entry.getValue(); out.println("Локально зарезервированные файловые ресурсы: \n Название: " + localResource.getName() + "Путь: " + localResource.getRootPath()+"\n Максимальный размер (Мб): " + localResource.getMaximumSizeInMegabytes()+"\n"); }; Map<String, String> mapConfigSettings = RoleEnvironment.getConfigurationSettings(); String mysetting = mapConfigSettings.get("name"); out.println(mysetting); // Отслеживание количества визитов в сессии. Integer visits = (Integer) session.getAttribute("visits"); if (null == visits) { // Визиты в сессии не отслеживаются, при первом визите инициализация. visits = new Integer(1); } else { // Визиты отслеживаются, поэтому инкрементирование счетчика визитов. visits = new Integer(visits.intValue() + 1); } // Обновление данных сессии для включения текущего количества счетчиков. session.setAttribute("visits", visits); // проверка на наличие логина пользователя в сессии String name; name = (String) session.getAttribute("username"); if (null == name) { // если логина нет, проверяется текстовое поле логина name = request.getParameter("username"); if (null != name && "" != name) { // сохранение логина в сессии session.setAttribute("username", name); // приветствие. %> <p>Welcome <%= name %>!</p> <% } else { // логина нет. отображение формы. %> <form action="<%=request.getRequestURI() %>" method="post"> Enter your name: <input type="text" name="username" /> (Press the <b>Enter</b> key when done) </form> <% } } else { // приветствие возвратившегося пользователя. %> <p>Welcome back <%= name %>!</p> <% } // отображение инфорамации сессии. DateFormat dfDate = DateFormat.getDateInstance(DateFormat.FULL); DateFormat dfTime = DateFormat.getTimeInstance(); long creationTime = session.getCreationTime(); long lastAccessedTime = session.getLastAccessedTime(); Date dateCreated = new Date(creationTime); Date dateLastAccessed = new Date(lastAccessedTime); %> <p/> <table border=1 width=90% > <tr><th>Session information</th><th>Value</th></tr> <tr><td>Session ID</td><td><%= session.getId() %></td></tr> <tr><td>New or existing</td><td><%= (session.isNew() ? "New" : "Existing") %></td></tr> <tr><td>Created</td><td><%= dfDate.format(dateCreated) %> <%= dfTime.format(dateCreated) %></td></tr> <tr><td>Last accessed</td><td><%= dfDate.format(dateLastAccessed) %> <%= dfTime.format(dateLastAccessed) %></td></tr> <tr><td>Maximum inactive interval</td><td><%= Integer.toString(session.getMaxInactiveInterval()) %> seconds</td></tr> <tr><td>Visits or refreshes by you to this session</td><td><%= visits.intValue() %></td></tr> <tr><td>Windows Azure deployment ID</td><td><%= RoleEnvironment.getCurrentRoleInstance().getId() %></td></tr> <tr><th>Session attributes</th><th>Value</th></tr> <% // определение атрибутов сессии. Enumeration<String> e = session.getAttributeNames(); String attributeName; Object attributeValue; // отображение атрибутов. while (e.hasMoreElements()) { attributeName = e.nextElement(); attributeValue = session.getAttribute(attributeName); %> <tr><td><%= attributeName %></td><td><%= attributeValue.toString() %></td></tr> <% } %> </table> <p/> <!-- Allow the user to create a new session. --> <form action="newsession.jsp" method="post"> <input type="submit" name="newSession" value="Create new session" /> </form> %></body></html>
Файл newsession.jsp должен иметь следующий код.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>New session page</title></head><body><% // удаление текущей сессии. session.invalidate(); // возврат пользователя к главной странице response.sendRedirect("NewFile.jsp");%></body></html>
Теперь нам необходимо экспортировать пакет Java-проекта. Для этого кликните правой кнопкой мыши на проекте AzureLocApp и нажмите Export=>WAR File. В появившемся диалоговом окне нажмите Browse и выберите папку approot проекта Windows Azure (рис. 14.).
Рис. 14.
Разверните проект в облаке и просмотрите результат.
Alexander Belotserkovskiy edited Revision 2. Comment: added link to seventh part
Alexander Belotserkovskiy edited Revision 1. Comment: added link to sixth part
Fernando Lugão Veltem edited Original. Comment: alter title added ru-ru