Tema 3.6: El Estilo Arquitectónico REST

Anuncio
Tema 3.6: El Estilo Arquitectónico
REST
Índice
Introducción
Conceptos básicos de REST
Recursos y Representaciones
Conjunto fijo de operaciones
Hypermedia: Cambio de estado
Servicios auto-descriptivos
Intermediarios y caches
Ejemplo: Movies RPC vs Movies REST
Estilo REST vs Estilo RPC
Valoración y Conclusiones
Introducción
REpresentational State Transfer. Estilo arquitectónico
propuesto por Roy Fielding en 2000.
La Web es, sin duda, la aplicación distribuida más
exitosa de la historia.
REST: Estilo arquitectónico para construir
aplicaciones distribuidas inspirado en las
características de la web.
REST se basa fuertemente en HTTP 1.1:
Realmente es independiente de HTTP
Pero HTTP 1.1 es el único protocolo utilizado masivamente
diseñado para soportar los principios REST.
Introducción (y 2)
El estilo REST pretende que sea posible construir
sistemas distribuidos compuestos por miles de
servicios desarrollados y evolucionados
independientemente, escalando a niveles
comparables a la Web.
Para ello hace énfasis en minimizar el acoplamiento
entre servicios.
A menudo se les denomina servicios web “RESTful”.
Nosotros también los denominaremos servicios web
REST “puros”.
Recursos y Representaciones (1)
Una aplicación REST se compone de recursos. Cada recurso es
identificado mediante un identificador único (típicamente URLs):
http://www.boeing.com/aircraft/747
Puede representar un 747 de la compañía Boeing
http://www.movieprovider.com/movies/Amelie
Amelie en la BD de películas de movieprovider.com.
http://www.amazon.com/Ajax-REST-Recipes-Problem-SolutionApproach/dp/1590597346/
El libro “Ajax and REST Recipes: A Problem-Solution Approach” (ISBN:
1590597346) en Amazon.
http://en.wikipedia.org/wiki/HTTP
Representa la información sobre HTTP proporcionada por Wikipedia.
Los identificadores (URLs) son globales.
Todo recurso tiene un nombre único a nivel mundial.
No existen espacios de nombres restringidos a un
servicio/aplicación.
Eso no quiere decir que todos los recursos sean accesibles para
todos (mecanismos de autorización).
Recursos y Representaciones (y2)
Al invocar la URL, el cliente obtiene una representación del
recurso.
La representación de un recurso puede variar en el tiempo.
El identificador está ligado al recurso, no a la representación.
Si cambian los datos sobre HTTP en la Wikipedia, cambiará la
representación. La URL apuntará siempre a la representación
actual del recurso (entrada actual en Wikipedia).
La representación puede permitir actuar sobre el recurso.
Ejemplo: Formularios para introducir datos.
La representación puede contener nuevas URLs hacia otros
recursos.
Ejemplo: cuando atravesamos un hiperenlace (URL) en la web
estamos accediendo a un recurso cuya representación (página
web) puede contener otros hiperenlaces.
Conjunto fijo de operaciones(1)
Interfaz uniforme. Las operaciones disponibles sobre
los recursos son siempre las mismas y su semántica
es conocida por todos los clientes y servicios.
El estilo REST no dice cuáles deben ser esas
operaciones, sólo que deben ser siempre las mismas
y ser usadas consistentemente por los servicios.
En el caso de HTTP: GET, POST, PUT, DELETE.
GET: Acceso a recursos y consultas. Sin efectos secundarios.
PUT: Crear o reemplazar completamente la representación
de un recurso. Idempotente.
DELETE: Borrar un recurso. Idempotente.
POST: Acciones que pueden tener efectos secundarios
(creación / modificación de recursos, coste) y pueden no ser
idempotentes.
Conjunto fijo de operaciones(y2)
Analogía con QUERY / UPDATE / INSERT /DELETE en
una Base de datos.
PUT sirve para UPDATEs idempotentes e INSERTS
(cliente decide el identificador).
POST sirve para INSERT si servidor decide URL. Sirve
para UPDATES no idempotentes. También se usa a
menudo para UPDATES parciales.
Un servicio web REST debe utilizar sólo estas
operaciones para manipular los recursos.
Esto quiere decir que cierta semántica de una invocación
(“lo que hace”) sobre un recurso es conocida sin saber nada
sobre el servicio.
Facilita la interoperabilidad entre aplicaciones. Para manipular
un recurso de otra aplicación sólo se precisa su URL.
Este conocimiento semántico limitado es suficiente para
permitir capas intermedias (e.g. cache) transparentes que
proporcionan servicios útiles.
Hypermedia: Cambio de Estado
La representación recibida por el cliente cambia
(transfer) su estado (state).
Una aplicación REST (web) puede verse como el
grafo de transición de estados de un autómata.
Las representaciones de recursos (páginas) son estados del
autómata.
Las URLs (hiperenlaces) son transiciones entre estados.
El estado en el que estamos determina qué otros estados
(recursos) tenemos accesibles.
No hay estado específico para cada cliente en el
servidor:
Cada petición del cliente debe incluir todo lo necesario para
que el servidor pueda responderla.
Facilita escalabilidad y replicación.
Servicios Autodescriptivos (1)
Idealmente, un cliente de un servicio REST
necesitaría conocer a priori una única URL (la de
entrada al servicio).
El resto de sus interacciones serían guiadas por las
representaciones por las que va navegando:
Hiperenlaces para operar sobre otros recursos.
Plantillas de consulta/actualización que permitan
operar sobre otros recursos usando parámetros
especificados por el cliente:
Equivalente a formularios en la web.
Permite que el servicio varíe los parámetros de la
operación o la URL sobre la que actúan dinámicamente.
Servicios Autodescriptivos (2)
Las representaciones devueltas deben intentar
expresarse en formatos conocidos a priori por todos
los clientes posibles del servicio:
Intentar evitar formatos propietarios de cada servicio. En lo
posible, utilizar tipos MIME con semántica conocida (e.g.
ATOM).
Si los clientes posibles están dentro de una organización
intentar usar estándares de la organización.
Si hay que añadir información específica, intentar
proporcionar también una representación en un formato
estándar (e.g. ATOM)
Así, cualquier cliente podrá al menos obtener parte de la
información.
Servicios Autodescriptivos (y 3)
Si esto se consigue, el cliente y el servicio están muy
desacoplados:
El servicio puede cambiar totalmente su funcionamiento
interno (e.g. esquemas de URL, campos consultables para
un recurso) sin que el cliente rompa.
Análogo a un usuario humano que accede con su browser a
una web que ha cambiado totalmente -> aún eres capaz de
usar el servicio.
En muchos casos, puede ser muy difícil / imposible
de conseguir totalmente:
¿Cómo expresar forms entendibles por programas?. Existen
varias propuestas, aún no muy usadas (e.g. Xforms).
No hay vocabularios estándar para todo !
Intentar ajustarse lo más posible o adoptar soluciones parciales
(e.g. tener una representación en ATOM además de la
representación en un formato específico)
Intermediarios y Caches (1)
Soporte para Cache:
Las representaciones deben poderse marcar como
cacheables o no por capas intermedias.
Soporte para tiempos de expiración, detección de si hay o
no nuevas versiones de un recurso,…
El uso de una interfaz uniforme permite introducir
intermediarios de forma transparente entre los
clientes y los recursos:
Servicios de eficiencia, seguridad,… Ejemplos :
Proxies . Pueden implementar reintentos de forma
transparente con peticiones idempotentes.
Servidores de cache. Sabe que las peticiones GET de un
recurso invalidan su copia, las otras sí.
Filtros de contenido. Pueden decidir actuar sólo sobre
peticiones GET.
Intermediarios y Caches (2)
La interfaz uniforme permite que los clientes también
pueden realizar ciertos procesamientos sobre los
recursos de un servicio sin conocimiento a priori:
E.g. un crawler sabe que puede hacer GETS de
representaciones.
En un enfoque RPC típico, la semántica de una
operación no es conocida para el
intermediario/cliente a menos que se le configure
específicamente para cada servicio.
Si además de respetar la interfaz uniforme, se
consigue que el sistema sea auto-descriptivo en un
grado alto, los clientes / intermediarios pueden
realizar operaciones más sofisticadas.
Intermediarios y Caches (y 3)
Intermediarios:
Servicio-1
Cache
HTTP
Cliente
HTTP
HTTP
Servicio-2
HTTP
...
Servicio-N
Ejemplo: Movies RPC (1)
Ejemplo películas al estilo RPC (CORBA,
DCOM, SOAP,…)
Proveedor proporciona una interfaz que
consiste en, entre otras, las siguientes
operaciones:
MovieSummary [] findMovies()
MovieSummary [] findMoviesByDate(Calendar date)
MovieInformationDetail getMovieInformation (String
movieId)
String addMovie(MovieInformationDetail info)
void updateMovie (String
movieId,MovieInformationDetail info)
void removeMovie (String movieId)
void addGross (double amount, movieId, Calendar
week)
NOTA: usamos notación “a la JAVA”.
Ejemplo: Movies RPC (2)
Los clientes del proveedor suelen utilizar:
findMovies permite obtener la lista de todas las películas.
findMoviesByDate permite obtener la cartelera de un día
determinado.
Ambos métodos devuelven la información más importante
de una película (objeto MovieSummary):
Se incluye un identificador numérico para cada película.
No se devuelve toda la información porque puede ser bastante
grande y normalmente no se necesita toda.
Si se quiere toda la información de una película puede
llamarse a getMovieInformation pasándole el
identificador de la película.
Ejemplo: Movies RPC (y 3)
Las aplicaciones que editan los contenidos del
proveedor (internas o externas) suelen utilizar
addMovie permite añadir una película.
removeMovie permite eliminar una película.
updateMovie. Permite reemplazar la información completa
de una película.
addGross. Permite especificar la recaudación semanal de
una película. Modifica el atributo recaudación total de la
misma sumándole la nueva recaudación. No es idempotente.
Las operaciones pueden lanzar exceptions ad-hoc
como las que vimos en temas anteriores.
Ejemplo: Movies REST (1)
Cada película es un recurso con una URL asociada:
http://www.moviesprovider.com/movies/Amelie
http://www.moviesprovider.com/movies/The_Godfather_Part_II
Su representación es un documento XML.
Similar al ejemplo utilizado en el tema 2 con elementos de
datos adicionales (e.g. recaudación, productora, puntero al
trailer, punteros a biografías de los actores, …).
Podría utilizarse una representación alternativa en ATOM
(del estilo de la que vimos en el Tema 3.2) para los clientes
que no entiendan nuestro formato:
A través de cabeceras HTTP es posible para el cliente
especificar qué formatos acepta.
Podría no utilizarse XML:
Si los datos son sencillos. Ejemplo: CSV.
Si al cliente puede facilitarle su procesamiento. Ejemplo: desde
clientes Javascript, es más fácil usar JSON.
Ejemplo: Movies REST (2)
http://www.moviesprovider.com/movies es un
recurso colección que contiene:
Su representación es un documento XML:
La información resumida de todas las películas.
Una referencia al recurso de cada película.
Un “formulario” que indica como buscar por fecha.
Incluye alguna información de resumen de cada película.
Usa Xlink (http://www.w3.org/TR/xlink/) para especificar
referencias a otros recursos.
Usa una URI Template (http://bitworking.org/projects/URITemplates/spec/draft-gregorio-uritemplate-03.html) para
especificar como consultar la colección por fecha.
Podría haber una representación alternativa en ATOM para
los clientes que no entendiesen nuestro formato (no serviría
para la interfaz de consulta).
Análogo a una página web convencional.
Ejemplo: Movies REST (3)
<?xml version="1.0"?>
<mov:Movies xmlns:mov="http://www.movieprovider.com"
xmlns:xlink= http://www.w3.org/1999/xlink
xmlns:xf="http://www.w3.org/2002/xforms>
<Movie title=“Amelie“
director=“Jean Pierre Jeunet”
xlink:href="http://www.moviesprovider.com/movies/Amelie"/>
<Movie title=“The Godfather Part II“
director=“Francis Ford Coppola”
xlink:href="http://www.moviesprovider.com/movies/The_Godfather_Part_
II"/>
<mov:Filter url=“http://www.example.com/?{-join|&|day,month,year}”>
</mov:Movies>
Ejemplo: Movies REST (4)
http://www.movieprovider.com/movies puede recibir
parámetros de “consulta”.
http://www.movieprovider.com/movies?day=19&month=3&year=
2007
Pero los clientes no tienen que saber cuál es
exactamente el formato de URL utilizado. El patrón
de URL especifica esto.
¿Qué hacen los clientes ahora?
Invocan http://www.moviesprovider.com/movies
Parsean el XML para obtener la información resumida.
Si quieren la información completa de una película, invocan
a su referencia y parsean el XML.
Si quieren la cartelera, interpretan la URI Template y
componen la invocación con parámetros.
Todas son peticiones GET.
Ejemplo: Movies REST (5)
¿Qué hacen las aplicaciones que editan los contenidos ahora?
Para añadir una película, realizan una petición PUT indicando la
URL asociada
Ejemplo: http://www.moviesprovider.com/Movies/Seven
Los datos de la película van como un documento XML en el
cuerpo del mensaje.
Otra opción es hacer una petición POST a un recurso
colección (http://www.movieprovider.com/movies) que nos
devuelva la nueva URL:
De esta forma es el servicio en lugar del cliente el que controla
la generación de identificadores.
Para borrar una película invocan el recurso que representa a la
película con el método DELETE.
Para reemplazar la información de una película invocan el recurso
que representa a la película con el método PUT.
Los datos de la película van como un documento XML en el
cuerpo del mensaje.
Ejemplo: Movies REST (6)
Para la operación addGross hay varias opciones:
El cliente obtiene el recurso (GET), lo modifica y lo
sobreescribe (PUT).
Definimos la recaudación como un recurso.
Obliga al cliente a descargarse la representación completa.
El cliente puede descargarlo y actualizarlo sin descargarse la
representación completa de la película.
Forzado, ya que la recaudación no parece realmente un recurso
con entidad suficiente para ser referenciada por sí misma.
Definimos un recurso
http://www.moviesprovider.com/movies/XXXX/ al que
accedemos vía POST:
Recibe como parámetro la cantidad a incrementar y un
indicador de la operación a realizar (e.g. addGross).
Los intermediarios sabrán que es una operación no
idempotente y con posibles efectos secundarios sobre el
recurso, aunque no entiendan toda su semántica.
Quizás la mejor opción.
Ejemplo: Movies REST (y 7)
En lugar de usar exceptions ad-hoc se utilizan los
códigos de error de HTTP.
De esta forma, clientes genéricos pueden interpretar
los mensajes de error sin saber nada a priori sobre el
servicio.
HTTP, entre muchos otros, define códigos de error
para situaciones tales como recurso duplicado o
intentar eliminar un recurso no existente.
Ejemplo: REST vs RPC (1)
Espacio de nombres global vs local
El enfoque RPC utiliza un espacio de nombres local basado en
identificadores de película.
Los identificadores del enfoque REST son globales.
Si otro servicio web (e.g. que proporciona críticas de películas) quiere
incluir una referencia a una película de movieprovider.com puede
sencillamente incluir su URL en una de sus respuestas.
Hace más fácil reusar recursos y servicios.
El cliente debe aún conocer el vocabulario (formato XML) utilizado por
movieprovider.com. Si existe una representación en un formato
estándar como ATOM, un cliente genérico podrá aún hacer cierto uso
del servicio sin conocer nuestro vocabulario específico.
No existe una posibilidad equivalente en el enfoque RPC.
Se usan identificadores numéricos no globales.
Para acceder a un servicio siempre es necesario crear los stubs y
los objetos asociados, que son propietarios.
La causa principal del éxito de la Web no fueron HTML ni HTTP,
cuya principal virtud era la simplicidad. La causa principal fue la
utilización de un espacio de nombres global que permitía reusar
muy fácilmente (mediante enlaces) los contenidos ya existentes.
Ejemplo: REST vs RPC (2)
Operaciones estándar vs Operaciones no estándar.
RPC permite que cada servicio defina sus propias
operaciones pero no expone ninguna semántica de las
mismas. No puede saberse, por ejemplo, que:
La operación addGross no es idempotente y además tiene
efectos secundarios.
La operación updateMovie es idempotente y tiene efectos
secundarios.
La operación findMovies es idempotente y no tiene efectos
secundarios.
REST intenta modelar aplicaciones en términos de recursos y
usar un conjunto fijo de operaciones: GET, POST, PUT,
DELETE. Cierta semántica de estas operaciones es conocida:
POST tiene efectos secundarios y no tiene porque ser
idempotente.
PUT, DELETE tienen efectos secundarios pero son
idempotentes.
GET es idempotente y no tiene efectos secundarios.
Ejemplo: REST vs RPC (3)
Operaciones estándar vs Operaciones no estándar (cont.)
Conocer algo sobre la semántica de las operaciones permite
tener intermediarios/clientes que proporcionan valor añadido
a CUALQUIER servicio (sin tener que saber nada sobre él a
priori). Ejemplos:
Un servidor de cache sabe que un recurso al que se haya
emitido una petición PUT, DELETE o POST debe ser invalidado.
Un proxy que, cuando una petición falla, la reintenta de forma
transparente al cliente, sabe que puede reintentar una petición
GET sin riesgo (porque es idempotente).
Un crawler de recursos (“a la Google”) sabe que debe acceder
sólo a recursos usando sólo GET (ausencia de efectos
secundarios).
Las invocaciones RPC no pueden beneficiarse directamente
de los servicios de estos intermediarios, salvo que se
configure específicamente para cada servicio.
RPC permite tener el API más adecuado a las características
de tu aplicación. REST obliga a modelar todas las
aplicaciones de la misma forma, y puede no ser fácil o
cómodo en todos los casos.
Ejemplo: REST vs RPC (4)
Servicios auto-descriptivos:
Si se consigue, permite que un cliente pueda usar un
servicio sin saber nada a priori sobre él.
El cliente debe entender la forma de especificar las
opciones.
El servicio guía al cliente a través de las opciones posibles
mediante hypermedia y especificaciones de formatos de
consulta / actualización (e.g. URITemplates, Xforms)
El uso de formatos estándares universales (e.g. ATOM y otros
tipos MIME) permite que el cliente sepa interpretar los datos.
Ejemplo: crawler / buscador de recursos accesibles a través de
servicios web REST.
No existen estándares suficientemente extendidos.
No existen vocabularios estándar para todo.
Intentar dar salida en algún formato estándar y complementar
con formatos menos estándar para clientes con mayor
conocimiento.
Ejemplo: REST vs RPC (5)
Accesibilidad
REST usa directamente URLs y HTTP:
Fácil ver y manipular datos para humanos: puedo acceder a un
recurso directamente con un navegador (XML suele ser legible
para humanos).
Fácil devolver distintas representaciones del recurso. Ejemplo:
HTML para usuarios humanos y XML para aplicaciones
(cabecera HTTP Agente de Usuario + XSLT).
Prácticamente cualquier aplicación (desde Office a los sistemas
de integración de datos) puede acceder recursos HTTP.
Interoperabilidad garantizada
El cliente debe ocuparse de los detalles de ejecutar peticiones
HTTP y parsear documentos XML
Es bastante fácil en casi todos los lenguajes de programación.
Ejemplo: REST vs RPC (6)
Accesibilidad (cont.)
RPC utiliza librerías y protocolos específicos:
No es fácil para un humano acceder rápidamente a los
recursos. Hay que construir aplicaciones ad-hoc para ello.
Cualquier operación que involucre acceso al recurso implica
programar.
Para acceder a un servicio RPC, las aplicaciones deberán
utilizar librerías generadas específicamente para nuestro
servicio. Menor interoperabilidad.
El programador no se preocupa de cómo se envían peticiones
ni de parsear XML. El sistema RPC le da todo eso resuelto.
El cliente pasa a ser dependiente de todo el XML de salida.
Cualquier cambio en el mismo puede afectarle aunque sea en un
campo que no usa.
Puede haber problemas de interoperabilidad entre
implementaciones (problema temporal).
Ejemplo: Debido a bugs, un servicio SOAP programado con una
toolkit puede tener problemas con otro servicio programado con
otra toolkit.
Ejemplo: REST vs RPC (7)
Reusar mecanismos genéricos de diseño de HTTP vs
Nuevos mecanismos
Aunque REST es un estilo en teoría independiente de HTTP,
este es el único protocolo actual que tiene las características
necesarias para soportar este estilo.
Con REST, pueden reusarse directamente los mecanismos
de autorización (permisos de acceso), cifrado y
autenticación de HTTP.
Con esquemas RPC, deben crearse nuevos mecanismos para
esto:
En algunas tecnologías como CORBA ya existen.
En el mundo SOAP no existen pero se están construyendo.
Pueden crearse para que mejoren a los de HTTP.
HTTP no tiene todo lo necesario (e.g. transacciones
distribuidas, servicios de mensajería,…).
Los defensores de REST proponen extender HTTP en lugar de
crear nuevos protocolos.
Ejemplo: REST vs RPC (y 8)
Transporte fijo vs Independiente Transporte
Con REST, en la práctica, el protocolo encargado de
transferir las peticiones es siempre HTTP.
Los sistemas RPC pueden utilizar diversos protocolos:
Ejemplo: SOAP puede funcionar sobre HTTP, SMTP, JMS,…
Los defensores de REST dicen que prácticamente siempre se
usa HTTP también en RPC (SOAP casi siempre va sobre
HTTP).
Defensores de RPC dicen que HTTP a veces es inadecuado:
Es poco eficiente.
Hay cosas que no soporta:
Ejemplo: HTTP no puede garantizar la entrega de un mensaje.
Hay servicios web reales que utilizan SOAP sobre JMS, porque JMS
sí proporciona esa funcionalidad.
REST en la Práctica (1)
La mayor parte de servicios que se autodenominan
REST se parecen más a lo que hemos visto en el
Tema 3.3 que al enfoque RESTful.
Normalmente sólo se utilizan GET (lectura) y POST
(escritura)
Prácticamente siempre hay recursos que realmente
implementan operaciones no estándar.
Pocas veces se asignan URLs a recursos que no
representen realmente operaciones sino objetos.
REST en la Práctica (y 2)
Incluso en los servicios autodenominados RESTful es
raro ver algunas características (hypermedia,
servicios autodescriptivos).
A pesar de esto, algunas de las ventajas más
importantes se mantienen:
Caches
Accesibilidad sigue siendo mejor.
Aprovechamiento de los mecanismos de HTTP.
El estilo REST no supone una decisión de “todo o
nada”:
El que nuestro servicio tenga sólo algunas de las
características de REST puede ser útil todavía.
Conclusiones
REST es un nuevo estilo arquitectónico para construir
aplicaciones distribuidas basadas en los principios que hicieron
exitosa a la web.
REST modela un servicio como la aplciación de una serie de
operaciones fijas sobre un conjunto de recursos referenciables
universalmente.
REST tiene el potencial para permitir la construcción de
aplicaciones distribuidas mucho más escalables e interoperables,
compuestas por cientos de servicios muy desacoplados entre sí.
RPC es más flexible (REST “obliga” a modelar la aplicación de
una forma concreta) y más amigable para el programador
(independiente de XML y HTTP).
La mayoría de aplicaciones distribuidas corporativas y B2B
siguen modelándose según la arquitectura RPC, aunque REST
tiene su importancia y gana terreno.
A menudo, REST se usa para referirse a servicios web que usan
exclusivamente HTTP / XML (en lugar de SOAP), incluso si la
arquitectura de dichos servicios es básicamente RPC. Estos
servicios se benefician de parte de las ventajas de REST.
Descargar