gerenciamento.xml
15.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" []>
<chapter id="gerenciamento">
<title>Monitoração e Gerenciamento de Recursos</title>
<section>
<title>Por que monitorar e gerenciar aplicações</title>
<para>Ao implantar um sistema para produção, muitas vezes é necessário monitorar aspectos sobre o funcionamento desse sistema. Quanta memória
ele está utilizando? Qual o pico de MIPS utilizados? Quantas sessões estão autenticadas no momento?</para>
<para>Além de monitorar um sistema, as vezes é necessário gerenciá-lo alterando aspectos de seu comportamento. Se o sistema está implantado em um
servidor alugado, talvez seja necessário ajustar o uso de MIPS para reduzir custos ou talvez deseje-se solicitar que o sistema limpe dados de sessão
de autenticação abandonados por usuários que desligaram suas estações sem efetuar "logoff".</para>
<para>Para esse fim existem diversas tecnologias que permitem ao desenvolvedor expor aspectos monitoráveis e gerenciáves de seu sistema
para clientes de gerenciamento. Exemplos dessas tecnologias incluem o <emphasis>Simple Network Management Protocol</emphasis> (SNMP) e o
<emphasis>Java Management Extension</emphasis> (JMX).</para>
<para>O <emphasis>Demoiselle Framework</emphasis> dispõe de uma série de ferramentas para nivelar
o conhecimento do desenvolvedor e facilitar o uso e integraçao de várias tecnologias de gerenciamento e
monitoração. Através de seu uso o desenvolvedor pode facilmente integrar tais tecnologias, despreocupando-se
com detalhes de implementação de cada uma delas.</para>
</section>
<section>
<title>Introdução ao mecanismo</title>
<para>Para expor aspectos monitoráveis da sua aplicação, o primeiro passo é criar uma interface contendo os atributos monitoráveis e as operações
de gerenciamento que serão expostas para clientes de gerenciamento. Isso é feito através de uma simples classe Java (<emphasis>ou POJO</emphasis>)
anotada com o estereótipo <code>@ManagementController</code>.</para>
<programlisting role="JAVA"><![CDATA[
@ManagementController
public class GerenciadorUsuarios]]></programlisting>
<para>Essa anotação é suficiente para o mecanismo de gerenciamento descobrir sua classe e disponibilizá-la para ser monitorada e gerenciada.</para>
<para>Contudo, a simples anotação acima não informa ao mecanismo quais aspectos da classe serão expostos. Por padrão, um <emphasis>Management Controller</emphasis>
não expõe nenhum aspecto seu. Para selecionar quais aspectos serão expostos usamos as anotações
<emphasis>@ManagedProperty</emphasis> e <emphasis>@ManagedOperation</emphasis>. Além disso outras anotações podem ser usadas para personalizar o funcionamento
de classes anotadas com <code>@ManagementController</code>.</para>
<informaltable>
<tgroup cols="3" rowsep="1" colsep="1">
<thead>
<row>
<entry>Anotação</entry>
<entry>Descrição</entry>
<entry>Atributos</entry>
</row>
</thead>
<tbody>
<row valign="top">
<entry>
<emphasis role="BOLD">@ManagedProperty</emphasis>
</entry>
<entry>
<para>Marca um atributo na classe como uma propriedade gerenciada, significando que clientes externos podem ler e/ou escrever valores nesses atributos.</para>
<para>Um atributo marcado pode estar disponível para leitura e/ou escrita. Por padrão, o que determina a visibilidade de um atributo
marcado é a presença dos métodos <emphasis>getAtributo</emphasis> e <emphasis>setAtributo</emphasis>, respectivamente disponibilizando o atributo
para leitura e escrita.</para>
<para>Para sobrescrever esse comportamento existe na anotação <emphasis role="BOLD">@ManagedProperty</emphasis> o atributo <emphasis>accessLevel</emphasis>.
Com ele é possível criar um atributo apenas para leitura, mas que contenha um método <emphasis>set</emphasis>. O contrário também é possível.</para>
</entry>
<entry>
<itemizedlist>
<listitem><emphasis role="BOLD">description</emphasis>: Um texto descritivo documentando o propósito da propriedade.</listitem>
<listitem><emphasis role="BOLD">accessLevel</emphasis>: Sobrescreve o nível padrão de acesso de uma propriedade. Os valores possíveis são
READ_ONLY, WRITE_ONLY e DEFAULT, que significa que a presença de métodos <emphasis>get</emphasis> e <emphasis>set</emphasis> vai determinar o nível de acesso.</listitem>
</itemizedlist>
</entry>
</row>
<row valign="top">
<entry>
<emphasis role="BOLD">@ManagedOperation</emphasis>
</entry>
<entry>
<para>Marca um método da classe gerenciada como uma operação, o que significa que clientes externos podem invocar esse método remotamente.</para>
<para>Operações gerenciadas normalmente são criadas para executar intervenções em um sistema já em execução. Por exemplo, é possível criar uma
operação que, ao ser invocada, destrua todas as seções abertas no servidor e não utilizadas nos últimos 30 minutos.</para>
</entry>
<entry>
<itemizedlist>
<listitem><emphasis role="BOLD">description</emphasis>: Um texto descritivo documentando o propósito da operação.</listitem>
<listitem><emphasis role="BOLD">type</emphasis>: Documenta o propósito da operação. <emphasis>ACTION</emphasis> informa que a operação modificará
o sistema de alguma forma. <emphasis>INFO</emphasis> diz que a operação coletará e retornará informações sobre o sistema. <emphasis>ACTION_INFO</emphasis>
informa que a operação modificará o sistema de alguma forma e retornará informações sobre o resultado. <emphasis>UNKNOWN</emphasis> é o padrão
e significa que o resultado da execução da operação é desconhecido.</listitem>
</itemizedlist>
</entry>
</row>
<row valign="top">
<entry>
<emphasis role="BOLD">@OperationParameter</emphasis>
</entry>
<entry>
<para>Esta anotação opcional pode ser usada para cada parâmetro de um método anotado com <emphasis role="BOLD">@ManagedOperation</emphasis>.</para>
<para>Ele permite detalhar melhor parâmetros em uma operação gerenciada. O efeito desta anotação é dependente da
tecnologia utilizada para comunicação entre cliente e servidor. Na maioria das tecnologias, essa anotação meramente permite ao cliente
exibir informações sobre cada parâmetro: nome, tipo e descrição.</para>
</entry>
<entry>
<itemizedlist>
<listitem><emphasis role="BOLD">name</emphasis>: O nome do parâmetro quando exibido para clientes.</listitem>
<listitem><emphasis role="BOLD">description</emphasis>: Um texto descritivo documentando o propósito do parâmetro.</listitem>
</itemizedlist>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section>
<title>Expondo aspectos de sua aplicação para monitoração</title>
<para>Uma vez que uma classe esteja anotada com <emphasis>@ManagementController</emphasis> e seus atributos e operações estejam expostos, a classe está pronta para
ser monitorada.</para>
<para>Suponha que a aplicação deseje expor o número de usuários que efetuaram login. A operação de <emphasis>login</emphasis> será processada em
uma classe de negócio <emphasis>ControleAcesso</emphasis>. Vamos supor também que existe uma classe chamada <emphasis>MonitorLogin</emphasis> responsável
por expor o número de usuários que efetuaram login no sistema.</para>
<programlisting role="JAVA"><![CDATA[
@BusinessController
public class ControleAcesso{
@Inject
private MonitorLogin monitorLogin;
public boolean efetuarLogin(String usuario , String senha){
// codigo de login
monitorLogin.setContadorLogin( monitorLogin.getContadorLogin() + 1 );
}
}]]></programlisting>
<programlisting role="JAVA"><![CDATA[
@ManagementController
public class MonitorLogin{
@ManagedProperty
private int contadorLogin;
@ManagedOperation
public void setContadorLogin(int qtdUsuarioLogados){
contadorLogin = qtdUsuarioLogados;
}
@ManagedOperation
public int getContatorLogin(){
return contadorLogin;
}
}]]></programlisting>
<para>Como é possível ver, classes anotadas com <emphasis>@ManagementController</emphasis> podem ser injetadas em qualquer ponto do código. Valores definidos
para seus atributos retêm seu estado, então um cliente que acesse remotamente o sistema e monitore o valor do atributo <emphasis>contadorLogin</emphasis> verá
a quantidade de logins efetuados no momento da consulta.</para>
<section>
<title>Enviando notificações da aplicação</title>
<para>
É comum que aplicações monitoradas permaneçam em estado de espera - é função do cliente de monitoração acessar a aplicação e obter
as informações necessárias. No entanto existem casos onde é necessário que a aplicação comunique clientes de eventos ocorridos no sistema. Um exemplo é um monitor
de espaço em disco que envia um alerta quando esse espaço for menor que 20% do total.
</para>
<para>
Para essa funcionalidade o <emphasis>Demoiselle Framework</emphasis> disponibiliza o utilitário <emphasis>NotificationManager</emphasis>, que
pode ser injetado em sua aplicação a qualquer momento para notificar clientes externos de eventos importantes.
</para>
<para>Considere o exemplo abaixo:</para>
<programlisting role="JAVA"><![CDATA[
public class DiskWritter{
@Inject
private NotificationManager notificationManager;
public void writeFile(byte[] data , File fileToWrite){
// ... implementação da escrita de arquivo
if (fileToWrite.getUsableSpace() / (float)fileToWrite.getTotalSpace() <= 0.2f){
Notification notification = new DefaultNotification("O espaço disponível no disco é inferior a 20% do total");
notificationManager.sendNotification( notification );
}
}
}]]></programlisting>
<para>
Como é possível ver no exemplo, o utilitário <emphasis>NotificationManager</emphasis> é usado para enviar notificações em decorrência
de eventos ocorridos na sua aplicação. O uso mais comum é notificar avisos ou problemas para que ações sejam tomadas, mas é possível também
usar essa técnica para tomar ações preventivas ou informativas - uma notificação que o backup noturno foi feito com sucesso por exemplo.
</para>
<para>
A interface <emphasis>Notification</emphasis> é a base das notificações enviadas e possui apenas um método:
<emphasis>Object getMessage()</emphasis>. A API de monitoração não força o tipo específico da mensagem e usualmente essa mensagem
será uma <emphasis>String</emphasis> (como no exemplo acima), mas algumas extensões podem utilizar tipos específicos de mensagem
capazes de carregar mais informações.
</para>
<para>
O <emphasis>demoiselle-core</emphasis> disponibiliza por padrão o tipo concreto de notificação <emphasis>DefaultNotification</emphasis> - uma
implementação direta da interface <emphasis>Notification</emphasis> que permite definir a mensagem a ser retornada por <emphasis>getMessage()</emphasis>.
Além disso o <emphasis>demoiselle-core</emphasis> disponibiliza o tipo especial de mensagem <emphasis>AttributeChangeMessage</emphasis>, que permite
especificar além do texto da mensagem enviada, dados sobre a mudança de valor de um atributo, como o nome do atributo alterado, o valor antigo e o novo.
</para>
<para>
Notificações contendo mensagens do tipo <emphasis>AttributeChangeMessage</emphasis> são automaticamente enviadas por padrão pelo framework quando um
agente de monitoração altera o valor de uma propriedade anotada com <emphasis>@ManagedProperty</emphasis>, mas você também pode enviar mensagens desse tipo
quando propriedades de sua aplicação são alteradas. Extensões e componentes compatíveis com a API de monitoração do <emphasis>Demoiselle Framework</emphasis>
(por exemplo, a extensão <emphasis>demoiselle-jmx</emphasis>) podem fornecer implementações específicas da interface <emphasis>Notification</emphasis> e
tipos especializados de mensagem. Consulte a documentação desses componentes para aprender sobre seus usos.
</para>
</section>
</section>
<section>
<title>Conectando um cliente de monitoração</title>
<para>O <emphasis>demoiselle-core</emphasis> contém as funcionalidades necessárias para marcar aspectos monitoráveis de sua aplicação,
mas não conta com nenhum mecanismo para estabelecer uma conexão com um cliente de monitoração. Para isso utiliza-se extensões do framework.</para>
<para>A extensão padrão do framework <emphasis>Demoiselle</emphasis> responsável pela tecnologia de monitoração é a <emphasis>demoiselle-jmx</emphasis>.
Essa extensão utiliza a especificação JMX (JSR 3) e permite registrar as classes marcadas para monitoração como <emphasis>MBeans</emphasis>.
Uma vez que as classes sejam registradas como <emphasis>MBeans</emphasis>, seus atributos e operações expostos para monitoração podem ser
acessados via JMX por um cliente adequado, como o <emphasis>JConsole</emphasis> que acompanha por padrão o JDK da Oracle.</para>
<tip>
<para>Para acrescentar a extensão <emphasis>demoiselle-jmx</emphasis> em um projeto Maven, adicione a dependência abaixo no arquivo <emphasis>pom.xml</emphasis>.</para>
<programlisting role="XML"><![CDATA[
<dependency>
<groupId>br.gov.frameworkdemoiselle</groupId>
<artifactId>demoiselle-jmx</artifactId>
<scope>compile</scope>
</dependency>]]></programlisting>
</tip>
<tip>
<para>A API de monitoração é compatível com o uso de múltiplas extensões simultãneas. Adicione em seu projeto a dependência às extensões desejadas e configure-as
individualmente, as classes monitoradas serão então expostas para todas as extensões escolhidas.</para>
</tip>
<para>A figura <xref linkend="exemplo_jconsole" /> mostra como uma classe monitorada é exibida no <emphasis>JConsole</emphasis>.</para>
<programlisting role="JAVA"><![CDATA[@ManagementController
public class HelloWorldManager {
@Inject
private HelloWorld helloWorld;
@ManagedOperation(type=OperationType.ACTION)
public void saySomething(String whatToSay){
helloWorld.say(whatToSay);
}
}]]></programlisting>
<figure id="exemplo_jconsole"><title>JConsole acessando uma aplicação monitorada</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/jmx-jconsole-example.png" width="90%" />
</imageobject>
<textobject><phrase>JConsole acessando a aplicação <emphasis>Bookmark</emphasis></phrase></textobject>
</mediaobject>
</figure>
<para>
É possível perceber os seguintes elementos nessa imagem:
<itemizedlist>
<listitem>Uma classe gerenciada <emphasis>HelloWorldManager</emphasis> com uma operação chamada <emphasis>saySomething</emphasis></listitem>
<listitem>Uma classe geradora de notificações <emphasis>NotificationBroadcaster</emphasis> responsável por converter as notificações para a API JMX</listitem>
</itemizedlist>
</para>
<para>
Através do <emphasis>JConsole</emphasis> é possível invocar comandos e acessar atributos em todas as classes anotadas com <emphasis>@ManagementController</emphasis>
em aplicações que usam o <emphasis>demoiselle-jmx</emphasis>. Também é possível inscrever-se às notificações enviadas por <emphasis>NotificationBroadcaster</emphasis>
e receber todas as notificações enviadas pela aplicação.
</para>
</section>
</chapter>