2010-06-08 15 views
5

Esta es una pregunta más sobre la estrategia de arquitectura de servicio, estamos construyendo un gran sistema web basado en servicios de descanso en back-end. Y actualmente estamos tratando de construir algunos estándares internos a seguir mientras desarrollamos servicios de descanso.Arquitectura de servicios RESTful pregunta

Algunas consultas lista de entidades devoluciones, por ejemplo, permite considerar que tenemos galerías de imágenes recuperación de servicio:/gell_all_galeries, volviendo respuesta siguiente:

<galleries> 
    <gallery> 
     <id>some_gallery_id</id> 
     <name>my photos</name> 
     <photos> 
      <photo> 
       <id>123</id> 
       <name>my photo</name> 
       <location>http://mysite/photo/show/123</location> 
       ...... 
       <author> 
        <id>some_id</id> 
        <name>some name</name> 
        ....... 
       <author> 
      </photo> 
      <photo> ..... </photo> 
      <photo> ..... </photo> 
      <photo> ..... </photo> 
      <photo> ..... </photo> 
    </photos> 
    </gallery> 
    <gallery> .... </gallery> 
    <gallery> .... </gallery> 
    <gallery> .... </gallery> 
    <gallery> .... </gallery> 
</galleries> 

Como se ve aquí, la respuesta bastante grande y pesado, y no siempre necesitamos un nivel de información tan profundo. solución habitual es usar o http://ru.wikipedia.org/wiki/Atom elementos para cada galería en lugar de datos completos galería:

<galleries> 
    <gallery> 
     <id>some_gallery_id</id> 
     <link href="http://mysite/gallery/some_gallery_id"/> 
    </gallery> 
    <gallery> 
     <id>second_gallery_id</id> 
     <link href="http://mysite/gallery/second_gallery_id"/> 
    </gallery> 
    <gallery> .... </gallery> 
    <gallery> .... </gallery> 
    <gallery> .... </gallery> 
    <gallery> .... </gallery> 
</galleries> 

La primera pregunta, es lo siguiente: tal vez ni siquiera deberíamos usar y tipos, y sólo tiene que utilizar genéricos y de todos los recursos Esa lista retorno de objetos:

<list> 
    <item><link href="http://mysite/gallery/some_gallery_id"/></item> 
    <item><link href="http://mysite/gallery/other_gallery_id"/></item> 
    <item>....</item> 
</list> 

Y la segunda pregunta, cuando el usuario intenta recuperar información sobre alguna galería de concreto, que va a utilizar, por ejemplo, http://mysite/gallery/some_gallery_id enlace, ¿qué debe ver como los resultados?

Si fuese:

<gallery> 
     <id>some_gallery_id</id> 
     <name>my photos</name> 
     <photos> 
      <photo> 
       <id>123</id> 
       <name>my photo</name> 
       <location>http://mysite/photo/show/123</location> 
       ...... 
       <author> 
        <id>some_id</id> 
        <name>some name</name> 
        ....... 
       <author> 
      </photo> 
      <photo> ..... </photo> 
      <photo> ..... </photo> 
      <photo> ..... </photo> 
      <photo> ..... </photo> 
    </photos> 
    </gallery> 

o:

<gallery> 
     <id>some_gallery_id</id> 
     <name>my photos</name> 
     <photos> 
      <photo><link href="http://mysite/photo/11111"/></photo> 
      <photo><link href="http://mysite/photo/22222"/></photo> 
      <photo><link href="http://mysite/photo/33333"/> </photo> 
      <photo> ..... </photo> 
    </photos> 
    </gallery> 

o

<gallery> 
     <id>some_gallery_id</id> 
     <name>my photos</name> 
     <photos> 
      <photo> 
       <link href="http://mysite/photo/11111"/> 
       <author> 
        <link href="http://mysite/author/11111"/> 
       </author> 
      </photo> 
      <photo> 
       <link href="http://mysite/photo/22222"/> 
       <author> 
        <link href="http://mysite/author/11111"/> 
       </author> 
      </photo> 
      <photo> 
       <link href="http://mysite/photo/33333"/> 
       <author> 
        <link href="http://mysite/author/11111"/> 
       </author> 
      </photo> 
      <photo> ..... </photo> 
    </photos> 
    </gallery> 

quiero decir si utilizamos enlace en lugar de información completa del objeto, qué tan profundo que deberíamos ir allí ? ¿Debo mostrar un autor dentro de una foto, etc.?

Probablemente mi pregunta sea ambigua, pero lo que estoy tratando de hacer es crear una estrategia general en tales casos para que todos los miembros del equipo la sigan en el futuro.

Respuesta

0

Siempre puede usar los atributos.

<gallery id = "1" name = "Gallery 1"> 
     <photos> 
      <photo id="1" link="http://mysite/photo/11111" /> 
      <photo id="2" link="http://mysite/photo/22222" /> 
      <photo id="3" link="http://mysite/photo/33333" /> 
     </photos> 
    </gallery> 

O puede usar JSON Lo prefiero porque es más fácil y más ligero que XML.

{ 
    "gallery": { 
     "id": "1", 
     "name": "Gallery 1", 
     "photos": [ 
      { 
       "id": "1", 
       "link": "http://mysite/photo/11111" 
      }, 
      { 
       "photo": "2", 
       "link": "http://mysite/photo/22222" 
      }, 
      { 
       "photo": "3", 
       "link": "http://mysite/photo/33333" 
      } 
     ] 
    } 
+0

Estoy usando Java y Apache CXF para servir un servicio RESTful. Eso tiene la ventaja de poder servir * tanto * XML como JSON para el mismo recurso, dependiendo de lo que el cliente dice que prefiere (es decir, a través de la negociación de contenido). –

2

Una buena cosa a tener en cuenta es cómo pretende que los clientes recuperen los datos. Si tiene la intención de que un cliente obtenga un montón de información sobre muchas fotos, entonces una lista de solo <photo href="..."/> podría no ser óptima, ya que el cliente se vería obligado a realizar una solicitud GET para cada recurso fotográfico del que necesita información .

Se me ocurren un par de formas interesantes de evitar esto.

Puede permitir que un cliente especifique los campos que desea recuperar como parámetros de consulta al consultar la lista, p.:

GET http://www.example.com/photos?_fields=author,fileSize 

Esto podría devolver algo como:

<photos href="/photos?_fields=author,fileSize"> 
    <photo href="/photos/15"> 
     <author href="/authors/2245"/> 
     <fileSize>32MB</fileSize> 
    </photo> 
    ... 
</photos> 

Como alternativa, puede hacer que sea más fácil al permitir que el cliente especifique algún tipo de "profundidad" máxima propiedad; esto es un poco más crudo, pero podría usarse de manera efectiva. Por ejemplo, si el cliente especifica una profundidad de 2, devolverá todo lo que está debajo de <gallery>, así como todos los elementos secundarios de cada <photo>.

GET /galleries?depth=2 

podría devolver algo como:

<galleries> 
    <id>22</id> 
    <name>My Gallery</name> 
    <!-- full gallery data --> 
    <photos href="/photos?gallery=/galleries/22"> 
    <photo href="/photos/99"> 
     <id>99</id> 
     <author href="/authors/4381"/><!-- href instead of including nested author data --> 
     <fileSize>24MB</fileSize> 
     <!-- full photo data --> 
    </photo> 
    ... 
    </photos> 
</galleries> 

Junto a esto, si usted está preocupado por el cliente consultar muchos, muchos registros a la vez (por ejemplo, si hay miles de fotos o galerías), es posible que desee considerar algún tipo de paginación para sus listas. Esto podría implicar el establecimiento de un máximo duro para obtener resultados en su código y proporcionar al cliente con enlaces a páginas siguientes/anteriores:

GET /photos?gallery=/galleries/59 

podría volver:

<photos href="/photos?gallery=/galleries/59&_max=100&_first=100" next="/photos?gallery=/galleries/59&_max=100&_first=200" prev="/photos?gallery=/galleries/59&_max=100&_first=0" count="100" total="3528"> 
    .... 
</photos> 

clientes podrían controlar los _first y _max propiedades, pero nunca podría aumentar el _max en un cierto umbral configurado. Debería devolver el número de resultados "encontrados" para la página en el marcado, así como la cantidad total de resultados disponibles. Esto lo ayudaría a recortar los tamaños de respuesta, que usted mencionó podría ser una preocupación. Esto podría hacerse en paralelo con las opciones enumeradas anteriormente.

En última instancia, depende de cómo desee que su servidor instruya a los clientes a recuperar datos. Si no quieres que hagan un GET para cada foto, entonces quizás quieras proporcionarles formas más convenientes de obtener datos más profundos. Pero si cree que su servidor puede manejar una carga decente, y junto con eso puede hacer optimizaciones del lado del servidor (almacenamiento en caché, usando estados 304, etc.), entonces simplemente devolver listas poco profundas con href s es un poco más directo.

+2

Sé que la idea de dejar que el cliente elija qué elementos de datos desean recibir es muy popular, sin embargo, debe considerar cómo puede limitar seriamente su capacidad para almacenar en caché las respuestas. Si solo tiene cinco propiedades, imagine la cantidad de diferentes variaciones de respuestas que podría tener. ¿Los guardas en caché y abomba tu memoria caché, no almacena en el caché ninguno y carga el servidor de base de datos, o almacena en caché un intermediario inteligente que puede extraer subconjuntos de datos de una copia en caché completa? –

+0

@Darrel: un buen punto. Probablemente depende de si el servidor necesita o no poder almacenar los resultados. Si no, entonces es viable; pero si es así, probablemente lo evitaría. –

+0

@Rob Creo que su idea de especificar los nombres de los campos que se deben devolver tiene sentido, como recuerdo Linked In Api funciona de esta manera. Gracias. – abovesun

3

Realmente no hay una respuesta correcta o incorrecta para "cómo debería diseñar mis tipos de medios". Sin embargo, hay algunas pautas muy importantes cuando se seleccionan los tipos de medios existentes y se diseñan.

Los sistemas RESTful logran la escalabilidad mediante el uso cuidadoso de la memoria caché. Diseña tus recursos para dividir el contenido en fragmentos que tienen una volatilidad de datos similar. Por ejemplo, con su escenario, tiene una lista de galerías que contienen fotos. Me imagino que no agrega/elimina galerías con mucha frecuencia, pero agrega/elimina fotos con regularidad. Por lo tanto, tendría sentido asegurarse de que pueda obtener una lista de galerías que no tienen información de fotos. Eso haría que sea fácil guardar en caché esa respuesta.

La optimización del tamaño de las respuestas puede ser importante para el rendimiento, pero el almacenamiento en caché es mucho más importante. Enviar 0 bytes a través del cable siempre es más eficiente.

Aunque la lista de fotos puede cambiar con más frecuencia, aún puede usar el almacenamiento en caché de manera efectiva. Por utilizando el encabezado if-modified-since o etags, no se guardará el viaje de ida y vuelta de la red, pero puede ahorrar mucho ancho de banda al no transferir representaciones que no se hayan modificado.

Es extremadamente difícil de diseñar los recursos que son ideales para todas las circunstancias y debido a esto, le sugiero que no intente. Diseña recursos que funcionen bien para tus casos de uso particulares. Si surgen otros casos de uso, cree nuevos recursos para manejarlos.

No hay nada de malo en la creación:

/gallery/foo/quickview 
/gallery/foo/detailedview 
/gallery/foo/justlinks 

¿Quieres utilizar un framework de desarrollo web que hace que sea muy fácil y barato para crear nuevos recursos. Los recursos rara vez tendrán un mapeo uno a uno con las entidades de su dominio, así que siéntase libre de crear tantos recursos como necesite.

Mi último comentario es sobre la selección de un tipo de medio. Deberías considerar usar algo como Atom para un servicio como este. Atom es ideal para gestionar listas de cosas y cuenta con todos los mecanismos necesarios para manejar elementos de medios como fotos.

La mayoría de las personas, cuando comienzan a usar los servicios REST, se acostumbran a la idea de que pueden entregar application/xml o application/json directamente como un tipo de medio. Hay algunos casos especializados en los que esto es completamente factible, sin embargo, cuando empiece a implementar más restricciones REST, encontrará que estos formatos de tipo de medio genérico limitarán los beneficios que puede lograr en muchos casos. Por el momento, no te preocupes demasiado solo ten en cuenta que siempre es más seguro elegir un tipo de medio "real" como application/xhtml, RDF o Atom, y si eliges application/xml puedes tener dificultades mas tarde.

+0

Gracias Darrel, del esquema de Atom acabamos de tomar la definición de tipo de enlace, y no estamos utilizando tipos de entrada o de alimentación. Si está interesado, estamos utilizando la implementación del resto de Java Jersey. Probablemente estaría de acuerdo con su afirmación de que aquí no hay reglas de diseño comunes y la decisión de diseño final depende del caso de uso concreto. – abovesun

1

Esto realmente depende de su situación. Necesita saber cómo el cliente va a usar esto para saber cómo diseñar su Resource Proxies.

Le sugiero que no se pierda en el "cruce de opciones". Simplemente vaya con una implementación basada en lo que asume sobre el uso del cliente. Vea cómo se usa y se comporta todo, afine después si es necesario. Enjuague de lavado. Repetir. Hazlo de forma Beta permanente :)

Cuestiones relacionadas