-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRelatório.tex
236 lines (181 loc) · 16.3 KB
/
Relatório.tex
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
% Setup -------------------------------
\documentclass[a4paper]{report}
\usepackage[a4paper, total={6in, 10in}]{geometry}
\setcounter{secnumdepth}{3}
\setcounter{tocdepth}{3}
\PassOptionsToPackage{hyphens}{url}
\usepackage{hyperref}
\usepackage{indentfirst}
% Encoding
%--------------------------------------
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
%--------------------------------------
% Portuguese-specific commands
%--------------------------------------
\usepackage[portuguese]{babel}
%--------------------------------------
% Hyphenation rules
%--------------------------------------
\usepackage{hyphenat}
%--------------------------------------
% Capa do relatório
\title{
Paradigmas de Sistemas Distribuídos
\\ \Large{\textbf{Trabalho Prático}}
\\ -
\\ Mestrado em Engenharia Informática
\\ \large{Universidade do Minho}
\\ Relatório
}
\author{
\begin{tabular}{ll}
\textbf{Grupo}
\\\hline
PG41080 & João Ribeiro Imperadeiro
\\
PG41081 & José Alberto Martins Boticas
\\
PG41091 & Nelson José Dias Teixeira
\end{tabular}
}
\date{\today}
\begin{document}
\begin{titlepage}
\maketitle
\end{titlepage}
% Índice
\tableofcontents
% Introdução
\chapter{Introdução} \label{intro} {
Neste trabalho prático é requerido o desenvolvimento de um protótipo de uma plataforma de negociação entre fabricantes e importadores de produtos.
Este protótipo é composto por cliente, servidor de \textit{front-end}, negociador e catálogo de entidades e negociações em curso. Os clientes podem existir em elevado número, sendo que
cada um deles desempenhará sempre o papel de fabricante ou de importador. Cada fabricante indicará a disponibilidade para produzir um determinado artigo, numa quantidade mínima e máxima,
a um preço mínimo (unitário), bem como o período de tempo durante o qual os importadores poderão fazer ofertas de encomenda (período de negociação). Por sua vez, cada importador indica a quantidade
e valor unitário a que está disposto a pagar por um determinado artigo de um fabricante. Os clientes autenticam-se no servidor de \textit{front-end}, o qual encaminha as suas ordens para um (de entre vários)
negociadores. O catálogo disponibilizará uma interface \textit{RESTful}, que permitirá obter informação sobre os fabricantes, importadores, e negociações em curso. Como tal, por forma a implementar este protótipo,
foi utilizada a linguagem de programação \textit{Java} (cliente, negociador e catálogo), \textit{Erlang} (servidor \textit{front-end}), e, ainda, \textit{Protocol Buffers}, \textit{ZeroMQ} e \textit{Dropwizard}.
Através do conjunto de requisitos que é possível extrair do primeiro parágrafo, os elementos que compõem este grupo deram início à concepção e desenvolvimento do protótipo pretendido, indicando e expondo, ainda,
como cada interveniente opera neste sistema.
}
\chapter{O sistema}
\section{Funcionamento}
O sistema é dividido em quatro partes principais: servidor \textit{front-end}, cliente, negociador e catálogo.
O cliente é a entidade que representa importadores ou fabricantes.
O mesmo apresenta uma interface rudimentar que permite ao utilizador fazer ofertas ou encomendas, dependendo se é um importador ou fabricante, e um conjunto de operações pedidas nos requisitos.
O servidor, por sua vez, é responsável por receber estas encomendas e fazê-las chegar ao negociador correspondente. Tem ainda um pequeno mecanismo de autenticação para os seus clientes.
Foi ainda tomada a decisão de que cada produto seria atribuído a um negociador, sendo esse negociador o responsável por todas as negociações que existam com esse produto.
Um negociador é responsável por intermediar as negociações entre importadores e fabricantes, fazendo corresponder ofertas e encomendas que satisfaçam os requisitos de ambas.
Quando uma negociação chega ao fim do seu tempo, envia as informações de fabricante, importadores e respetivas quantidades e preços para o servidor.
Por fim, o catálogo apresenta uma interface que se assemelha a uma \textit{RESTful} e ainda um sistema de \textit{publish-subscribe}, utilizando o \textit{ZeroMQ}, sendo que os subscritores são importadores e são notificados quando um fabricante, que eles subscreveram, publica um oferta, sendo que esta chega pelo negociador responsável.
As comunicações entre todas as partes intervenientes neste trabalho é feita utilizando \textit{Protocol Buffers}, o que facilita a troca de mensagens entre entidades desenvolvidas em diferentes linguagens de programação.
Por forma a facilitar a execução de todas as entidades envolvidas, é incluído, junto à implementação deste trabalho, um ficheiro \textbf{\textit{Makefile}} com todas as intruções necessárias para garantir o arranque correto do sistema.
\section{Implementação}
\subsection{Servidor}
A implementação do servidor foi feita em \textit{Erlang}. O servidor divide-se em diversos ficheiros, cada um dos quais corresponde a um tipo de ator, que se dividem em seis tipos:
\begin{itemize}
\item Servidor;
\item \texttt{loginHandler};
\item Clientes;
\item Importadorers;
\item Fabricantes;
\item \texttt{negotiatorsHandler};
\item Negociadores.
\end{itemize}
O servidor é apenas um ponto de ligação entre clientes e negociadores, sendo que decide ainda quais os negociadores que tratarão de determinadas ofertas/encomendas.
Vejamos em mais detalhe o trabalho de cada tipo de atores e a forma como o servidor reage a cada situação.
\subsubsection{Servidor central}
Este é o primeiro ator criado, responsável pela criação de todos os outros atores e por aceitar novas conexões (clientes), criando um novo ator por cada uma.
É ainda responsável pela conexão inicial de todos os negociadores, criando um ator por cada conexão.
Assim, cada cliente e cada negociador terá um correspondente ator no servidor, com o qual comunicará diretamente, já que cada um destes atores será o responsável pelo \textit{socket} correspondente.
\subsubsection{\texttt{loginHandler}}
Este ator é registado e criado pelo anterior. É o responsável pela autenticação e registo dos clientes, guardando todas as informações nesse sentido.
De realçar que só é contactado diretamente por outros atores do servidor, nomeadamente os criados a cada nova conexão de clientes, que veremos de seguida.
\subsubsection{Clientes}
Ator criado a cada nova conexão. Espera a receção de uma comunicação \textit{TCP} com a autenticação do cliente e, usando o \texttt{loginHandler}, confirma a sua identificação.
Segue-se a criação de novo ator, importador ou fabricante, que fica responsável pela comunicação com esse cliente. O ator atual é substituído pelo novo.
\subsubsection{Importadores e Fabricantes}
Ator criado pelo anterior, sempre que um cliente, do tipo importador ou fabricante, se autentica com sucesso.
Fica então responsável pela comunicação com o cliente, recebendo as suas encomendas/ofertas e fazendo com que as mesmas cheguem ao respetivo negociador, através do \texttt{negotiatorsHandler}.
\subsubsection{\texttt{negotiatorsHandler}}
O \texttt{negotiatorsHandler} é um ator, registado pelo servidor central, aquando da conexão de todos os negociadores, que é contactado pelos atores dos importadores ou fabricantes que queiram fazer encomendas ou ofertas.
Ao recebê-las, consoante o produto, passa-as para o respetivo negociador. Cada novo produto é atribuído a um negociador, em estilo \textit{round-robin}.
\subsubsection{Negociadores}
Existirá um ator deste tipo para cada negociador (quantidade pré-definida). Um negociador é responsável por um certo número de produtos, tratando de todas as ofertas e encomendas desse produto.
Quando um cliente faz uma oferta ou encomenda, a mesma acaba por chegar ao ator (negociador) responsável pelo produto, fazendo-a depois chegar ao negociador propriamente dito (exterior ao servidor).
\subsection{Cliente}
Tal como pedido nos requisitos do trabalho, a implementação do cliente foi feita em \textit{Java}. Para além de todas as classes nativas, foram ainda usadas funcionalidades da biblioteca \textit{Protocol Buffers}, um formato de serialização de dados desenvolvido pela \textit{Google} e da ferramenta \textit{ZeroMQ}, para troca assíncrona de mensagens. Posto isto, passaremos ao detalhe do funcionamento do cliente.
O cliente, aquando do início da sua utilização por parte de um utilizador, começa por pedir os dados de autenticação e entra em contacto com o servidor para verificar a sua validade. Em caso afirmativo, é criada uma \textit{thread} adicional que recebe informações do servidor e o utilizador é enviado para um de dois menus: o de fornecedor ou de importador. É lançada ainda outra \textit{thread}, responsável por receber updates do catálogo quanto a fabricantes que o utilizador subscreveu.
De seguida, após toda esta configuração inicial, é mostrado um dos seguintes menus com as operações indicadas:
\begin{enumerate}
\item \textbf{Importador}:
\begin{itemize}
\item Oferta de encomenda;
\item Obter lista de importadores/fabricantes;
\item Efetuar/cancelar subscrições;
\item Obter negociações em curso.
\end{itemize}
\item \textbf{Fabricante}:
\begin{itemize}
\item Oferta de produção;
\item Obter lista de importadores/fabricantes.
\end{itemize}
\end{enumerate}
Começando pelas operações do importador, temos que este pode encomendar um produto, tendo para isso de indicar o nome do produtor/produto, o número de unidades e o preço que está disposto a pagar por unidade. Pode ainda subscrever ou cancelar a subscrição de atualizações sobre um determinado produtor e produto.
Passando ao fornecedor, este pode apenas colocar uma oferta de produção, indicando o nome do produto, quantidade mínima/máxima, preço mínimo por unidade e período de negociação (em segundos) e obter uma lista dos importadores/fabricantes.
Quanto às mensagens do servidor e do catálogo, estas são apresentadas sempre que há informações para mostrar, num terminal à parte, passado na invocação inicial do cliente.
Em ambos os casos, é dada a opção ao utilizador para sair da interface.
\subsection{Negociador}
No que toca ao desenvolvimento do negociador, este foi implementado em \textit{Java} com recurso à linguagem neutra \textit{Protocol Buffers}, para efetuar a serialização de dados envolvidos nos processos de comunicação, e, ainda, foi utilizado a ferramenta \textit{ZeroMQ} para lidar com troca assíncrona de mensagens entre componentes de maneira a obter alto desempenho.
Por forma a satisfazer os requisitos impostos, foram declaradas duas variáveis relativas às negociações em curso no sistema e, ainda, aos importadores que não possuem de momento nenhum conjunto de produtores associado.
De forma a instanciar o negociador em causa, foi declarado um \textit{socket} que irá comunicar com o servidor, processando vários pedidos em simultâneo.
O negociador presente neste protótipo, ao receber pedidos do servidor, consegue processar se o mesmo corresponde a um pedido proveniente de um fabricante ou de um importador.
Caso este seja de um fabricante, é aberto um período limitado de negociação para determinar quais os importadores que serão escolhidos para proceder à produção de um determinado produto. O critério adotado nestas situações
é escolher qual o importador que possui o maior valor total de encomenda para o artigo em questão. Antes de se iniciar a negociação, é verificado se os importadores que ainda não têm nenhum fabricante associado possuem ou não a informação correta para se associar ao novo pedido do fabricante em questão. Se houver conformidade, o importador que se encontra isolado é associado
a este último, caso contrário é atualizada a segunda variável mencionada acima com a respetiva informação. Desta forma é dada prioridade aos importadores que ainda se encontram desassociados neste aspeto.
Caso o pedido seja de um importador, é, como se seria de esperar, verificado se o mesmo está associado à produção de um determinado tipo de artigo. Em caso afirmativo, é atualizada, com essa informação, a variável relativa às negociações
em curso. Caso contrário, procede-se de forma semelhante ao que foi dito anteriormente.
As mensagens que circulam na comunicação entre negociador e servidor encontram-se serializadas (através da linguagem \textit{Protocol Buffers}) por forma a garantir o mesmo grau de interpretabilidade dos dados em ambas as entidades.
\subsection{Catálogo}
Relativamente ao catálogo presente neste sistema, este é um componente onde se guarda informação útil acerca dos fabricantes e negociações em curso. Esta entidade do protótipo pode ser vista como um ficheiro de \textit{logs}, que é
atualizado e acedido sempre que for necessário. Isto possibilita guardar um histórico do estado momentâneo do funcionamento da aplicação. Como seria de esperar, este componente foi implementado em \textit{Java} com recurso à ferramenta \textit{ZeroMQ} e à linguagem \textit{Protocol Buffers}.
Quanto à troca assíncrona de mensagens, foi instanciado um \textit{broker} em \textit{ZeroMQ} que trata de receber as publicações e subscrições que circulam no sistema.
Para além disso, foram declaradas 3 variáveis na classe deste componente por forma a armazenar toda a informação pertinente:
\begin{itemize}
\item \textbf{negociations}: variável com os dados das negociações vigentes;
\item \textbf{importers}: variável correspondente ao conjunto dos importadores;
\item \textbf{producers}: variável correspondente ao conjunto dos fabricantes.
\end{itemize}
Sobre este componente podem ser exercidos 4 tipos distintos de operações:
\begin{enumerate}
\item \textbf{POSTNegotiation}: inserção da informação relativa à iniciação de um novo periodo de negociação;
\item \textbf{DELETENegotiation}: remoção da informação relativa à negociação em vigor;
\item \textbf{GETProducerInfo}: obtenção da informação relativa ao produtor;
\item \textbf{GETEntities}: obtenção dos dados de todas as entidades (importador e produtor).
\end{enumerate}
Com estas operações é possível reconhecer o estado atual do funcionamento do sistema implementado, acedendo e alterando o mesmo consoante o desenrolar da execução do protótipo.
\section{Arranque do sistema}
Enunciados os vários intervenientes deste sistema, passamos agora à explicação de como colocar a plataforma em funcionamento:
\begin{enumerate}
\item começa-se por executar o servidor, fazendo \textit{make compileServer} e executando a função \textit{server:server()};
\item executa-se o catálogo, fazendo \textit{make runCatalog};
\item executa-se um negociador (ou vários, tendo para isso de alterar o ficheiro do servidor), fazendo \textit{make compileJava} e \textit{make runDealer};
\item colocam-se os clientes a correr, ao executar \textit{make runClient}.
\end{enumerate}
\chapter{Conclusão}
Após a realização deste projeto prático, foi possível identificar e especificar as entidades principais que intervêem neste protótipo, e, ainda, as suas respetivas caraterísticas. Para cada uma destas, impôs-se um desafio
de implementação na medida em que as linguagens de programação adotadas são heterógeneas entre si.
Para além disso, foi possível constatar a dificuldade de integrar diferentes linguagens com diferentes paradigmas, bem como os desafios da construção de um sistema distribuído deste tipo, apesar de haver ferramentas que facilitam esta integração.
Dos requisitos do trabalho, apenas não foi utlizado o \textit{DropWizard}, sendo que o grupo, em alternativa, adotou uma interface seguindo o modelo \textit{REST}, disponibilizando métodos \textit{GET}, \textit{POST} e \textit{DELETE}.
\chapter{Webgrafia}
\begin{itemize}
\item \textbf{\textit{Protocol Buffers}}:
\par \textit{\url{https://developers.google.com/protocol-buffers}}
\item \textbf{\textit{Protocol Buffers - Java}}:
\par \textit{\url{https://developers.google.com/protocol-buffers/docs/reference/java-generated}}
\item \textbf{Documentação - \textit{ZeroMQ}}:
\par \textit{\url{https://zeromq.org/get-started/}}
\item \textbf{Documentação - \textit{Java}}:
\par \textit{\url{https://docs.oracle.com/en/java/javase/11/docs/api/index.html}}
\end{itemize}
\end{document}