Amazon Glacier es un servicio de almacenamiento en el que podemos guardar cualquier tipo de archivo por tiempo indefinido. Entre sus características destacamos:
Ventajas
- durabilidad, guardando los archivos por tiempo indefinido
- coste, razonable comparando los servicios ofrecidos con otras opciones
Desventajas
- tiempo de latencia: el acceso a sus ficheros no es inmediato, siendo su tiempo de acceso medio por operación de cuatro horas
Dadas estas características, a nosotros nos parece una buena opción para guardar de una manera segura archivos a los que no accederemos a menudo, siendo por ello ideal para el almacenamiento de copias de seguridad. Para ver un ejemplo práctico de uso, a continuación mostramos una solución para explotar el API Java que ofrece Amazon para la operación con su servicio, viendo cómo guardar, obtener y ver los ficheros nuestros archivos en Amazon Glacier.
Configuración del entorno
Para la preparación del entorno de desarrollo necesitaremos:
- Crear un proyecto Maven e introducir la dependencia:
1 2 3
com.amazonaws aws-java-sdk 1.3.21
- Establecer las propiedades de acceso a nuestro servicio de Amazon Glacier. Podremos configurar un archivo de propiedades. Podría ser algo de estilo:
1 2 3 4 5 6 7 8 9 10 11 12 13
aws.accessKeyId=NOC2EYUVO8B3Y2FO9CY3 aws.secretKey=3i384BvySo8w4ycor82ny38o/Dydr98J5tyvc8yn glacierRegion=eu-west-1 glacierEndPoint=https://glacier.eu-west-1.amazonaws.com/ vaultName= sqsEndPoint=sqs.eu-west-1.amazonaws.com sqsQueueName= snsEndPoint=sns.eu-west-1.amazonaws.com snsTopicName=
Una vez configurado el entorno y el acceso con Amazon Glacier podremos comenzar a realizar las operaciones que describimos a continuación.
Guardado de archivos
Para guardar archivos en Glacier a través de Java podremos utilizar el siguiente código:
1 2 3 4 5 6 7 8 9 |
String vaultName = PropertiesManager.getVaultName(); SystemPropertiesCredentialsProvider credentials = new SystemPropertiesCredentialsProvider(); AmazonGlacierClient glacierClient = new AmazonGlacierClient(credentials); glacierClient.setEndpoint(PropertiesManager.getGlacierEndPoint()); ArchiveTransferManager atm = new ArchiveTransferManager(glacierClient, credentials); UploadResult result = atm.upload(vaultName, archiveToUpload, new File(archiveToUpload)); System.out.println("File uploaded! File ID: '" + result.getArchiveId() + "'. File name: '" + archiveToUpload+"'"); |
Recuperación de archivos
Para recuperar archivos guardados en Glacier a través de Java podremos usar el código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
String vaultName = PropertiesManager.getVaultName(); //there are several ways to import the credential. we choose this one, through SystemProperties SystemPropertiesCredentialsProvider credentials = new SystemPropertiesCredentialsProvider(); //set up the glacier client AmazonGlacierClient glacierClient = new AmazonGlacierClient(credentials); glacierClient.setEndpoint(PropertiesManager.getGlacierEndPoint()); //we use the SQS client to enqueue the storage request AmazonSQSClient sqsClient = new AmazonSQSClient(credentials); sqsClient.setEndpoint(PropertiesManager.getSqsEndPoint()); //we use the SNS client to receive the notification of Amazon operation ending AmazonSNSClient snsClient = new AmazonSNSClient(credentials); snsClient.setEndpoint(PropertiesManager.getSnsEndPoint()); //download file ArchiveTransferManager atm = new ArchiveTransferManager(glacierClient, sqsClient, snsClient); atm.download(vaultName, archiveId, new File(downloadFilePath)); |
Listado de archivos (recuperación de inventario)
Aquí mostramos un ejemplo más completo de cómo recibir el inventario de nuestros archivos guardados en Amazon Glacier en formato JSON.
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 |
public class DownloadInventoryWithSQSPolling { public static String vaultName; public static String snsTopicName; public static String sqsQueueName; public static String sqsQueueARN; public static String sqsQueueURL; public static String snsTopicARN; public static String snsSubscriptionARN; public static String fileName = "glacierInventory"; public static long sleepTime = 600; public static AmazonGlacierClient client; public static AmazonSQSClient sqsClient; public static AmazonSNSClient snsClient; public static void main(String[] args) { try { if (args.length!=1) { throw new Exception("Incorrect values. Filename expected"); } fileName = args[0]; SystemPropertiesCredentialsProvider credentials = new SystemPropertiesCredentialsProvider(); client = new AmazonGlacierClient(credentials); client.setEndpoint(PropertiesManager.getGlacierEndPoint()); sqsClient = new AmazonSQSClient(credentials); sqsClient.setEndpoint(PropertiesManager.getSqsEndPoint()); sqsQueueName=PropertiesManager.getSqsQueueName(); snsClient = new AmazonSNSClient(credentials); snsClient.setEndpoint(PropertiesManager.getSnsEndPoint()); snsTopicName=PropertiesManager.getSnsTopicName(); vaultName = PropertiesManager.getVaultName(); setupSQS(); setupSNS(); String jobId = initiateJobRequest(); System.out.println("Jobid = " + jobId); Boolean success = waitForJobToComplete(jobId, sqsQueueURL); if (!success) { throw new Exception("Job did not complete successfully."); } downloadJobOutput(jobId); cleanUp(); } catch (Exception e) { System.err.println(e); e.printStackTrace(); System.exit(-1); } } private static void setupSQS() { CreateQueueRequest request = new CreateQueueRequest() .withQueueName(sqsQueueName); CreateQueueResult result = sqsClient.createQueue(request); sqsQueueURL = result.getQueueUrl(); GetQueueAttributesRequest qRequest = new GetQueueAttributesRequest() .withQueueUrl(sqsQueueURL) .withAttributeNames("QueueArn"); GetQueueAttributesResult qResult = sqsClient.getQueueAttributes(qRequest); sqsQueueARN = qResult.getAttributes().get("QueueArn"); Policy sqsPolicy = new Policy().withStatements( new Statement(Effect.Allow) .withPrincipals(Principal.AllUsers) .withActions(SQSActions.SendMessage) .withResources(new Resource(sqsQueueARN))); Map<String, String> queueAttributes = new HashMap<String, String>(); queueAttributes.put("Policy", sqsPolicy.toJson()); sqsClient.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueURL, queueAttributes)); } private static void setupSNS() { CreateTopicRequest request = new CreateTopicRequest() .withName(snsTopicName); CreateTopicResult result = snsClient.createTopic(request); snsTopicARN = result.getTopicArn(); SubscribeRequest request2 = new SubscribeRequest() .withTopicArn(snsTopicARN) .withEndpoint(sqsQueueARN) .withProtocol("sqs"); SubscribeResult result2 = snsClient.subscribe(request2); snsSubscriptionARN = result2.getSubscriptionArn(); } private static String initiateJobRequest() { JobParameters jobParameters = new JobParameters() .withType("inventory-retrieval") .withSNSTopic(snsTopicARN); InitiateJobRequest request = new InitiateJobRequest() .withVaultName(vaultName) .withJobParameters(jobParameters); InitiateJobResult response = client.initiateJob(request); return response.getJobId(); } private static Boolean waitForJobToComplete(String jobId, String sqsQueueUrl) throws InterruptedException, JsonParseException, IOException { Boolean messageFound = false; Boolean jobSuccessful = false; ObjectMapper mapper = new ObjectMapper(); JsonFactory factory = mapper.getFactory(); while (!messageFound) { List msgs = sqsClient.receiveMessage( new ReceiveMessageRequest(sqsQueueUrl).withMaxNumberOfMessages(10)).getMessages(); if (msgs.size() > 0) { for (Message m : msgs) { JsonParser jpMessage = factory.createJsonParser(m.getBody()); JsonNode jobMessageNode = mapper.readTree(jpMessage); String jobMessage = jobMessageNode.get("Message").textValue(); JsonParser jpDesc = factory.createJsonParser(jobMessage); JsonNode jobDescNode = mapper.readTree(jpDesc); String retrievedJobId = jobDescNode.get("JobId").textValue(); String statusCode = jobDescNode.get("StatusCode").textValue(); if (retrievedJobId.equals(jobId)) { messageFound = true; if (statusCode.equals("Succeeded")) { jobSuccessful = true; } } } } else { Thread.sleep(sleepTime * 1000); } } return (messageFound && jobSuccessful); } private static void downloadJobOutput(String jobId) throws IOException { GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest() .withVaultName(vaultName) .withJobId(jobId); GetJobOutputResult getJobOutputResult = client.getJobOutput(getJobOutputRequest); FileWriter fstream = new FileWriter(fileName); BufferedWriter out = new BufferedWriter(fstream); BufferedReader in = new BufferedReader(new InputStreamReader(getJobOutputResult.getBody())); String inputLine; try { while ((inputLine = in.readLine()) != null) { out.write(inputLine); } }catch(IOException e) { throw new AmazonClientException("Unable to save archive", e); }finally{ try {in.close();} catch (Exception e) {} try {out.close();} catch (Exception e) {} } System.out.println("Retrieved inventory to " + fileName); } private static void cleanUp() { snsClient.unsubscribe(new UnsubscribeRequest(snsSubscriptionARN)); snsClient.deleteTopic(new DeleteTopicRequest(snsTopicARN)); sqsClient.deleteQueue(new DeleteQueueRequest(sqsQueueURL)); } } |
Más recursos
Aquí sólo mostramos sencillos ejemplos a modo introductorio, pero el API permite de realizar más operaciones, como subida de ficheros en varias partes. Por ello, para profundizar, os recomendamos:
- Tutorial de Amazon en inglés
- Consultar la documentación oficial de Amazon Glacier
- Integrar esta solución para el almacenamiento de copias de seguridad con el tutorial de copias de seguridad en linux que ya tratamos.
« Presentamos dogoplay Dogoplay seleccionado para el Galicia Open Future »