Obliczenia w chmurze Amazon Web Services

Wojciech Józefek

Zaktualizowaliśmy ten tekst dla Ciebie!
Data aktualizacji: 31.12.2024
Autor aktualizacji: Krzysztof Mietliński

Obliczenia w chmurze stały się powszechną praktyką stosowaną od często używanych aplikacji, przez środowiska deweloperskie, maszyny wirtualne, aż po magazyny danych.

Czym są obliczenia w chmurze?

Obliczenia w chmurze to model, który umożliwia dostęp do zasobów systemowych i usług, które mogą być szybko udostępniane użytkownikom, najczęściej przez Internet.

Współcześnie obliczenia w chmurze są popularne, ponieważ umożliwiają wykorzystanie różnych usług w zależności od naszych potrzeb, takich jak aplikacje, środowiska deweloperskie, maszyny wirtualne czy przechowywanie danych.

Modele usług

Obliczenia w chmurze są podzielone na modele usług, które są przedstawiane jako warstwy w stacku technologicznym.

Każda warstwa zapewnia wyższy poziom abstrakcji:

Infrastructure as a Service (IaaS)

Ta warstwa udostępnia zaawansowane interfejsy API do zarządzania szczegółami infrastruktury sieciowej, zapewniając dostęp do infrastruktury obliczeniowej, maszyn fizycznych lub wirtualnych, pamięci opartej na obiektach/plikach, zapór sieciowych (firewall), balansowania obciążenia (load balancer) itp.

Platform as a Service (PaaS)

Ta warstwa udostępnia platformy obliczeniowe, takie jak środowiska deweloperskie dla programistów aplikacji, zazwyczaj zawierające system operacyjny, zintegrowane środowiska programistyczne (IDE), bazy danych oraz serwery WWW.

Software as a Service (SaaS)

Ta warstwa zapewnia użytkownikom dostęp do aplikacji przez oprogramowanie klienckie za pośrednictwem chmury. Oprogramowanie jest instalowane i wdrażane przez dostawcę usług chmurowych, więc nie ma potrzeby instalowania go na komputerze użytkownika.

Przykłady dostawców chmury
  • IaaS: Amazon Web Services (AWS), Google Compute Engine, Microsoft Azure
  • PaaS: AWS Elastic Beanstalk, Heroku, Google App Engine
  • SaaS: Aplikacje pocztowe, takie jak Gmail; media społecznościowe: Facebook, Twitter

Integracja Spring Cloud z Amazon Web Services

Aby pokazać, jak działają obliczenia w chmurze, zaimplementujemy przykładową aplikację, która będzie zintegrowana z Amazon S3 (Simple Storage Service) – usługą przechowywania obiektowego w modelu IaaS i jedną z wielu usług oferowanych przez Amazon Web Services.

Pełną listę produktów Amazon Web Services można znaleźć tutaj.

Do integracji wykorzystamy moduł Spring Cloud AWS, który jest jednym z projektów w stacku Spring Cloud, oferującym łatwą i wygodną integrację z Amazon Web Services.

Stos technologiczny:

Maven

Spring Boot

Spring Cloud i Spring Cloud AWS

React: na stronie klienta, aby zapewnić wsparcie dla interfejsu użytkownika oraz przesyłania plików

Generowanie poświadczeń bezpieczeństwa AWS

Najpierw wygenerujemy poświadczenia bezpieczeństwa AWS: klucz publiczny (access key) i klucz prywatny (secret key), które będą używane do uwierzytelniania i autoryzacji w celu interakcji z usługami AWS.

Możemy to zrobić w następujący sposób:

1. Zaloguj się do konsoli AWS: https://aws.amazon.com/console/.

2. Kliknij nazwę swojego konta -> My Security Credentials.

3. Przejdź do sekcji Access Key i kliknij przycisk Create New Access Key (Utwórz nowy klucz dostępu).

Tworzenie nowego folderu S3 (bucket)

Gdy już posiadamy klucze, możemy utworzyć nowy bucket S3, w którym będą przechowywane nasze obiekty (pliki). Aby to zrobić:

1. Na głównej stronie konsoli AWS kliknij opcję S3 w sekcji Storage (Pamięć).

2. Kliknij przycisk Create bucket (Utwórz bucket).

Nazwa folderu będzie wykorzystywana w konfiguracji naszej aplikacji.

Implementacja przykładowej aplikacji

Plik pom.xml, definiujący niezbędne zależności Maven, jest dostępny w repozytorium wspomnianym na końcu artykułu, więc możesz po prostu skopiować potrzebne zależności stamtąd.

Po zainstalowaniu wszystkich zależności możemy utworzyć klasę, która uruchomi naszą aplikację.

@SpringBootApplication
public class SpringCloudAwsExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringCloudAwsExampleApplication.class, args);
    }
}

Teraz możemy dodać niezbędną konfigurację do pliku application.properties, aby zintegrować AWS S3 z naszą aplikacją:

Wyjaśnienie poszczególnych właściwości:

accessKey i secretKey – wskazują na klucze AWS, które wcześniej wygenerowaliśmy.

s3.bucket – to nazwa utworzonego przez Ciebie folderu (bucket).

region.static – reprezentuje lokalizację jednego z centrów danych AWS, które świadczą usługi dla użytkowników chmury.

Następnie utwórzmy klasę konfiguracyjną, aby zainicjalizować i skonfigurować wymagane komponenty Spring (Spring beans):

@Configuration
public class AWSConfiguration {

    @Value("${cloud.aws.credentials.accessKey}")
    private String accessKey;

    @Value("${cloud.aws.credentials.secretKey}")
    private String secretKey;

    @Value("${cloud.aws.region.static}")
    private String region;

    @Bean
    public BasicAWSCredentials basicAWSCredentials() {
        return new BasicAWSCredentials(accessKey, secretKey);
    }

    @Bean
    public AmazonS3Client amazonS3Client(AWSCredentials awsCredentials) {
        AmazonS3Client amazonS3Client = new AmazonS3Client(awsCredentials);
        amazonS3Client.setRegion(Region.getRegion(Regions.fromName(region)));
        return amazonS3Client;
    }
}

Pola oznaczone adnotacją @Value reprezentują właściwości zdefiniowane w pliku application.properties. Bean basicAWSCredentials reprezentuje klucze AWS, a bean AmazonS3Client zapewnia klienta do dostępu do usługi internetowej Amazon S3.

Zaimplementujemy usługę, która będzie korzystać z wstrzykniętego bean AmazonS3Client, aby zintegrować się z AWS S3:

public interface StorageService {
    List<PutObjectResult> upload(MultipartFile[] multipartFiles);
}

@Service
public class AWSStorageService implements StorageService {

    private final AmazonS3Client amazonS3Client;

    @Value("${cloud.aws.s3.bucket}")
    private String bucket;

    @Autowired
    public AWSStorageService(AmazonS3Client amazonS3Client) {
        this.amazonS3Client = amazonS3Client;
    }

    public List<PutObjectResult> upload(MultipartFile[] multipartFiles) {
        List<PutObjectResult> putObjectResults = new ArrayList<>();

        Arrays.stream(multipartFiles)
                .filter(multipartFile -> !StringUtils.isEmpty(multipartFile.getOriginalFilename()))
                .forEach(multipartFile -> {
                    try {
                        putObjectResults.add(upload(multipartFile.getInputStream(), multipartFile.getOriginalFilename()));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });

        return putObjectResults;
    }

    private PutObjectResult upload(InputStream inputStream, String uploadKey) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, uploadKey, inputStream, new ObjectMetadata());
        putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
        PutObjectResult putObjectResult = amazonS3Client.putObject(putObjectRequest);
        IOUtils.closeQuietly(inputStream);
        return putObjectResult;
   }
}

Tutaj wstrzykujemy bean AmazonS3Client, aby zintegrować się z usługą internetową S3.

Musimy także określić folder (bucket), do którego będziemy przesyłać obiekty. Na pewno użyjemy folderu określonego w pliku application.properties, który jest wstrzykiwany za pomocą adnotacji @Value.

Gdy nasza usługa będzie gotowa, możemy napisać kontroler, który będzie przyjmował żądania HTTP zawierające pliki do przesłania, i wstrzyknąć stworzoną usługę, aby przesłać nasze pliki.

@RestController
public class UploadController {

    private final StorageService storageService;

    @Autowired
    public UploadController(StorageService storageService) {
        this.storageService = storageService;
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public List<PutObjectResult> upload(@RequestParam("file") MultipartFile[] multipartFiles) {
        return storageService.upload(multipartFiles);
    }
}

Teraz, gdy nasze komponenty do przesyłania plików są gotowe, czas zająć się stroną klienta, aby umożliwić przesyłanie plików za pomocą przeglądarki internetowej. Aby Spring Boot współpracował z React, stwórzmy kontroler serwujący aplikację SPA w React:

@Controller
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index() {
        return "index.html";
    }
}

Kontroler zwraca dokument index.html, w którym znajduje się nasza aplikacja React, aby mogła zostać wyrenderowana, gdy odwiedzimy główny adres URL aplikacji: http://localhost:8080/ .
Na koniec zaimplementujemy kod po stronie klienta, który zostanie wysłany w odpowiedzi HTTP i wykonany w przeglądarce internetowej użytkownika:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Spring Cloud AWS Example</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"
            integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
            crossorigin="anonymous"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
    class FormUpload extends React.Component {
        upload(e) {
            var formData = new FormData();
            formData.append('file', this.refs.file.files[0]);

            $.ajax({
                url: 'http://localhost:8080/',
                data: formData,
                processData: false,
                contentType: false,
                type: 'POST',
                success (data) {
                    alert('The file has been uploaded.');
                }
            });

            e.preventDefault();
        }

        render() {
            return (
                    <div>
                        <form ref="uploadForm" className="uploader" encType="multipart/form-data" >
                            <input ref="file" type="file" name="file" className="upload-file"/>
                            <input type="button" ref="button" value="Upload" onClick={this.upload.bind(this)} />
                        </form>
                    </div>
            );
        }
    }

    ReactDOM.render(<FormUpload/>, document.getElementById('root'));
</script>
</body>
</html>

Proszę zauważyć, że kod React JS nie jest doskonały, ponieważ nie jest to celem artykułu. Istotny jest dla nas szybki, działający przykład.

Możesz skompilować i uruchomić aplikację za pomocą poniższego polecenia Maven:

mvn spring-boot:run

Domyślnie aplikacja będzie działać na porcie 8080.

Aby sprawdzić, czy plik został przesłany, odwiedź swój folder S3 w konsoli AWS, do którego możesz przejść pod adresem: https://s3.console.aws.amazon.com/s3/buckets/your-s3-bucket-name-set-in-application.

Cały projekt można znaleźć w poniższym repozytorium: https://github.com/wjoz/spring-boot-cloud-aws-reactjs-example.

Podsumowanie

Na pewno warto spróbować Spring Cloud AWS które upraszcza integrację aplikacji Spring z AWS w świetny sposób. Istnieje wiele różnych produktów AWS, które mogą przyspieszyć rozwój i wdrażanie aplikacji, dlatego wierzę, że każdy znajdzie usługi, które będą odpowiednie dla danego projektu.

Przytoczony kod oparty jest na przykładzie Branta Hwanga, do który możesz znaleźć tu: https://github.com/brant-hwang/spring-cloud-aws-example.

Źródła

Poznaj mageek of j‑labs i daj się zadziwić, jak może wyglądać praca z j‑People!

Skontaktuj się z nami