PDA

Ver la Versión Completa : Estabilidad aplicación Datasnap Android


vicens22
24-12-2015, 10:47:29
Buenos días,

Estoy intentando avanzar en el desarrollo de una aplicación para smartphones (Android/IOS).
La aplicación conecta, utilizado una aplicación servidor Datasnap, con una base MS-SQL y también accede a ficheros de fotografías utilizando el componente http de Indy.
La aplicación recupera datos de clientes y productos mediante diversas consultas.
A nivel de operatividad y funcionalidad estoy consiguiendo lo que buscaba, pero no así en cuanto a velocidad/estabilidad de la aplicación, ya que al probarla en diversas circunstancias de conexión a la red me encuentro con los siguientes problemas:

A) Lentitud al recuperar datos que con frecuencia acaba en un mensaje de la aplicación de que no responde (obligando a cerrarla).
B) Errores de "Socket error 104 y 110 - reset by peer"

Estoy utilizando en las pruebas Delphi Seattle 10.

Las pruebas las he realizado conectando con la base mediante Wifi y 4G y utilizando un terminal Android de gama alta (One Plus One). Los errores se suceden con más frecuencia al conectar por 4G que por Wifi, pero en ninguno de los dos casos consigo la estabilidad deseada.

Supongo que estoy haciendo algo mal al recuperar datos o en la configuración de la aplicación servidor Datasnap, pero ahora mismo ya no sé que cambiar.
Tampoco quiero continuar con el desarrollo, mientras no consiga un mínimo de estabilidad con lo que llevo hecho hasta ahora.

Hay otras opciones más estables para conectar en mi caso con MS-SQL que Datasnap o realmente debo estar haciendo algo mal ??

Gracias por cualquier ayuda o sugerencia.

Un saludo

AgustinOrtu
24-12-2015, 15:18:20
Yo mando tablas enteras de varios miles de registros usando wifi o 3g/4g y no tengo problemas
Fotos ya es otro tema.. obviamente una foto de 5mb va a tardar mas

Como no nos digas como esta configurado el servidor y como envias/recibis los datos no sabemos si el problema de eficiencia esta en tu codigo o en datasnap

vicens22
24-12-2015, 17:23:00
Gracias Agustín, me tranquiliza tu comentario ya que llevo bastante tiempo invertido en el proyecto y espero poder aprovecharlo.

Te intento a continuación explicar ambos aspectos: el servidor Datasnap y el cliente.
Para la creación de la aplicación Datasnap Server me basé en el código de ejemplo descargado de la siguiente página:

https://jachguate.wordpress.com/2014/03/13/codigo-de-ejemplo-de-la-sesion-de-datasnap-en-coderage-america-latina-2014/#more-693

El enlace de descarga del ejemplo es:

http://http://goo.gl/brGgaH

En el Servidor Datasnap utilizo un objeto TAdoConnection para la conexión a MSSQL y varios TDataSetProvider y TADOQuery (uno para cada tabla o vista que necesito consultar).

El ejecutable Datasnap Server lo subí al servidor donde se encuentra el servidor MSSQL y está siempre activo. (El puerto utilizado es el 211).

En el cliente hay un ClientModule que contiene:

A) Un objeto TSQLConnection que conecta con el servidor Datasnap.
B) Un TDSProviderConnection que conectado con el objeto TSQLConnection permite a varios TClientDataSet recuperar los datos mediante Querys.

En los formularios de la aplicación cliente, utilizo los TCLientDataSet para recuperar los datos, por ejemplo de la siguiente forma:

procedure TForm8.SpeedButton1Click(Sender: TObject);
var cStr: string;
begin
with ClientModule1 do
begin

cdsClientes.Close;

cStr:= 'select * from '+ form1.cDataBaseName +'.dbo.Vista_Clientes order by cApeCli desc';

cdsClientes.CommandText := cStr;
cdsClientes.Open;

end;

Form9.Show;
end;


Como te he explicado aunque la operativa funciona, es completamente inestable, al realizar varias consultas seguidas siempre acaba dando algunos de los errores mencionados o bloqueándose la aplicación.

En cuanto a las fotografías entiendo que tampoco debería ser problema su tamaño, ya que todas están reducidas a un tamaño que oscila entre 40 y 120 Kb.

Espero que la información pueda ayudarte a ver donde puede encontrarse el problema.
Si necesitas que te envíe el código de la aplicación Servidor o cliente tan solo dímelo.

Muchas gracias de nuevo.
Saludos

AgustinOrtu
24-12-2015, 17:43:40
Yo tengo configurado Datasnap de la siguiente manera:

En el server, tambien usamos MSSQL. No uses ADO; es lento, es inestable, nunca me gusto

Ya que tenes 10 Seattle, opta por FireDAC.

El sevidor exopne un par de metodos para obtener datos, y uno o dos para insertar/actualizar. Es muy sencillo

Todo gira en torno a la clase "TFDJSONDataSets": es decir, los clientes mandan "TFDJSONDataSets", y el server devuelve "TFDJSONDataSets"; es basicamente un DataSet codificado en json y luego en base64 para que sea lo mas rapido posible de transportar.

En el uses necesitas agregar:

Data.FireDACJSONReflect,
FireDAC.Stan.StorageJSON,

Los metodos "Get" tienen la forma:


function TServerMethods1.GetClientes: TFDJSONDataSets;
begin
// refresh query
qClientes.Active := False;
Result := TFDJSONDataSets.Create;
TFDJSONDataSetsWriter.ListAdd(Result, qClientes);
end;


Los metodos "Insert" tienen mas "truco". Lo que yo hago es, recibir la instancia de TFDJsonDataSets y cargarlo en un FDMemTable; de alli, la recorro y se trata de un "DataSet normal". No hay que asustarse por el "alarmante" numero de operaciones; en realidad es todo bastante rapido


function TServerMethods1.InsertPedidos(Pedidos: TFDJSONDataSets): Boolean;
begin
// cabeceras
mtPedidos.AppendData(TFDJSONDataSetsReader.GetListValue(Pedidos, 0));
// detalles
mtDetalles.AppendData(TFDJSONDataSetsReader.GetListValue(Pedidos, 1));

mtPedidos.First;
while not mtPedidos.Eof do
begin
{ blabla }
mtPedidos.Next;
end;
end;


Del lado del cliente:


var
MemTab: TFDMemTable;
JsonData: TFDJSONDataSets;
begin
MemTab := TFDMemTable.Create(NIL);
// pedir clientes al server
JsonData := Client.Methods.GetClientes;

// volcar en FDMemTable
MemTab.AppendData(TFDJSONDataSetsReader.GetListValue(JsonData, 0));
MemTab.Open;
end;


Espero te sirva

vicens22
24-12-2015, 17:49:55
Muchas gracias Agustín por tu rápida respuesta y extensa explicación.

Voy a intentar aplicar todo lo que comentas a ver si finalmente consigo la estabilidad necesaria para poder continuar con el proyecto.

Saludos

wflorest
16-01-2016, 06:01:24
Hola,

Ante todo te agradezco la respuesta la pregunta del compañero, yo quisiera hacerte otra pregunta.

Como manejas las validaciones de los campos, como ejemplo las ventas sean menores a... u otras que pudieramos necesitar.

En la práctica estas deben darse en el aplicativo cliente, pero de ninguna manera programarlos ahi, verdad.
Entonces como se programan estos en el servidor y como los llamamos luego en el cliente.

Te agradecería puedas ayudarme en este tema.

Saludos desde Perú.

birmain
26-01-2016, 12:29:59
El problema que describes lo traté hace más de un año y llegué a varias conclusiones.

1ª) Hay varias formas de conectar DataSnap. Una de ellas es utilizar una conexión tcp, que es una conexión con estado. Por tanto, hay que mantener la conexión viva en el servidor, y muy a menudo se producen desconexiones y lentitud de servicio. Esto no es muy adecuado para una aplicación web, ni tan siquiera para una app nativa. Lo más adecuado es establecer conexiones sin estado, donde la identificación vaya en la cabecera de cada petición. Esto nos lleva a un servidor REST

2ª) Llegados a este punto, también se puede configurar DataSnap como servidor REST bajo el protocolo http, pero el rendimiento y la estabilidad deja mucho que desear.

3ª) Para mi, la mejor solución es recurrir a un servidor de robustez contrastada, como Apache, y resolver las conexiones a la base de datos con PHP y devolverlos en formato JSON, donde se pueden tratar perfectamente en Delphi, y devolverlos al servidor en el mismo formato. Aún mejor solución es crear un servidor con Node JS, si se domina JavaScript.

4º) Yo dejaría Delphi vara resolver la parte cliente, y poder hacer aplicaciones multiplataforma nativas. Embarcadero quiere abarcarlo todo, pero en lo referente al servidor deja mucho que desear.

Es una opinión. Un saludo.

rastafarey
09-09-2016, 16:16:24
Mira tendras que leer esto, y espero no te decepciones.
https://www.clubdelphi.com/foros/showthread.php?p=508632#post508632

clauxs88
19-01-2017, 20:01:23
Todo espectacular, pero a mi me daba un error tipo:
EFDException with message '[FireDAC][Stan]-716. Unknown storage format [BIN]. Hint: To register it, you can drop component [TFDStanStorageXxxLink] into your Project

Lo solucioné colocando el uses FireDAC.Stan.StorageBin en el ServerMethods y en el form del Cliente donde se usa el TFDJSONDataSetsReader.

Neftali [Germán.Estévez]
20-01-2017, 09:43:19
Tal vez podrías probar un acceso directo a SQLServer utilizando UNIDAC (http://blog.devart.com/connecting-to-sql-server-on-android-and-ios-in-direct-mode-using-sdac.html).
No creo que sea lo recomendable (Al menos en teoría), pero UniDAC permite hacerlo.

Siempre puedes hacer una prueba con la trial a ver qué tal.