Akka HTTP 소개

1. 개요

이 튜토리얼에서는 Akka의 Actor & Stream 모델의 도움으로 기본 CRUD 작업을 제공하는 HTTP API를 생성하도록 Akka를 설정하는 방법을 배웁니다.

2. Maven 종속성

시작하려면 Akka HTTP 작업을 시작하는 데 필요한 종속성을 살펴 보겠습니다.

 com.typesafe.akka akka-http_2.12 10.0.11   com.typesafe.akka akka-stream_2.12 2.5.11   com.typesafe.akka akka-http-jackson_2.12 10.0.11   com.typesafe.akka akka-http-testkit_2.12 10.0.11 test 

물론 Maven Central에서 이러한 Akka 라이브러리의 최신 버전을 찾을 수 있습니다.

3. 액터 생성

예를 들어 사용자 리소스를 관리 할 수있는 HTTP API를 구축 할 것입니다. API는 두 가지 작업을 지원합니다.

  • 새로운 사용자 생성
  • 기존 사용자로드

HTTP API를 제공하기 전에 필요한 작업을 제공하는 액터를 구현해야합니다.

class UserActor extends AbstractActor { private UserService userService = new UserService(); static Props props() { return Props.create(UserActor.class); } @Override public Receive createReceive() { return receiveBuilder() .match(CreateUserMessage.class, handleCreateUser()) .match(GetUserMessage.class, handleGetUser()) .build(); } private FI.UnitApply handleCreateUser() { return createUserMessage -> { userService.createUser(createUserMessage.getUser()); sender() .tell(new ActionPerformed( String.format("User %s created.", createUserMessage.getUser().getName())), getSelf()); }; } private FI.UnitApply handleGetUser() { return getUserMessage -> { sender().tell(userService.getUser(getUserMessage.getUserId()), getSelf()); }; } }

기본적으로 AbstractActor 클래스를 확장 하고 createReceive () 메서드를 구현합니다 .

createReceive () , 우리가하고 수신 메시지 유형을 매핑 방법으로 각각의 유형의 핸들 메시지가.

메시지 유형은 특정 작업을 설명하는 일부 필드가있는 간단한 직렬화 가능한 컨테이너 클래스입니다 . GetUserMessage 에는 로드 할 사용자를 식별 하는 단일 필드 userId 가 있습니다. CreateUserMessage 에는 새 사용자를 만드는 데 필요한 사용자 데이터가 있는 User 개체가 포함되어 있습니다 .

나중에 들어오는 HTTP 요청을 이러한 메시지로 변환하는 방법을 살펴 보겠습니다.

궁극적으로 우리 는 영구 사용자 개체를 관리하는 데 필요한 비즈니스 논리를 제공 하는 UserService 인스턴스에 모든 메시지를 위임 합니다.

또한 props () 메서드를 확인하십시오. 그동안 () 소품 방법 연장 불필요 AbstractActor를 , 생성 원 나중에 때 편리 할 ActorSystem를 .

배우에 대한보다 심층적 인 논의는 Akka Actors 소개를 참조하십시오.

4. HTTP 경로 정의

우리를 위해 실제 작업을 수행하는 액터가 있으므로, 우리가해야 할 일은 들어오는 HTTP 요청을 액터에게 위임하는 HTTP API를 제공하는 것입니다.

Akka는 경로 개념을 사용하여 HTTP API를 설명합니다. 각 작업마다 경로가 필요합니다.

HTTP 서버를 생성하기 위해 프레임 워크 클래스 HttpApp을 확장 하고 route 메소드를 구현합니다 .

class UserServer extends HttpApp { private final ActorRef userActor; Timeout timeout = new Timeout(Duration.create(5, TimeUnit.SECONDS)); UserServer(ActorRef userActor) { this.userActor = userActor; } @Override public Route routes() { return path("users", this::postUser) .orElse(path(segment("users").slash(longSegment()), id -> route(getUser(id)))); } private Route getUser(Long id) { return get(() -> { CompletionStage
    
      user = PatternsCS.ask(userActor, new GetUserMessage(id), timeout) .thenApply(obj -> (Optional) obj); return onSuccess(() -> user, performed -> { if (performed.isPresent()) return complete(StatusCodes.OK, performed.get(), Jackson.marshaller()); else return complete(StatusCodes.NOT_FOUND); }); }); } private Route postUser() { return route(post(() -> entity(Jackson.unmarshaller(User.class), user -> { CompletionStage userCreated = PatternsCS.ask(userActor, new CreateUserMessage(user), timeout) .thenApply(obj -> (ActionPerformed) obj); return onSuccess(() -> userCreated, performed -> { return complete(StatusCodes.CREATED, performed, Jackson.marshaller()); }); }))); } } 
    

여기에는 상당한 양의 상용구가 있지만 매핑 작업 이전과 동일한 패턴 , 이번에는 경로를 따릅니다 . 좀 더 자세히 살펴 보겠습니다.

getUser () 내에서 GetUserMessage 유형의 메시지에 들어오는 사용자 ID를 래핑하고 해당 메시지를 userActor 로 전달하기 만하면 됩니다.

액터가 메시지를 처리하면 onSuccess 핸들러가 호출 되어 특정 HTTP 상태 및 특정 JSON 본문과 함께 응답을 전송하여 HTTP 요청을 완료 합니다. Jackson 마샬 러를 사용하여 액터가 제공 한 답변을 JSON 문자열로 직렬화합니다.

postUser () 내 에서 HTTP 요청에서 JSON 본문을 예상하기 때문에 약간 다른 작업을 수행합니다. 엔터티 () 메서드를 사용하여 들어오는 JSON 본문을 CreateUserMessage 로 래핑 하고 액터에 전달 하기 전에 User 개체 에 매핑합니다 . 다시 말하지만 Jackson을 사용하여 Java와 JSON을 매핑하거나 그 반대로 매핑합니다.

HttpApp 은 단일 Route 객체 를 제공 할 것으로 예상하기 때문에 두 경로를 경로 메소드 내에서 단일 경로로 결합합니다 . 여기서는 path 지시문을 사용하여 API를 사용할 수있는 URL 경로를 마지막으로 제공합니다.

postUser () 가 제공하는 경로를 / users 경로에 바인딩합니다 . 수신 요청이 POST 요청이 아닌 경우 Akka는 자동으로 orElse 분기 로 이동 하여 경로가 / users / 이고 HTTP 메소드가 GET이 될 것으로 예상합니다 .

HTTP 메소드가 GET이면 요청이 getUser () 경로 로 전달됩니다 . 사용자가 없으면 Akka는 HTTP 상태 404 (찾을 수 없음)를 반환합니다. 메서드가 POST 또는 GET이 아니면 Akka는 HTTP 상태 405 (Method Not Allowed)를 반환합니다.

Akka로 HTTP 경로를 정의하는 방법에 대한 자세한 내용은 Akka 문서를 참조하십시오.

5. 서버 시작

위와 같이 HttpApp 구현 을 생성했으면 몇 줄의 코드로 HTTP 서버를 시작할 수 있습니다.

public static void main(String[] args) throws Exception { ActorSystem system = ActorSystem.create("userServer"); ActorRef userActor = system.actorOf(UserActor.props(), "userActor"); UserServer server = new UserServer(userActor); server.startServer("localhost", 8080, system); }

우리는 간단하게 만들 ActorSystem 유형의 단일 배우와 UserActor을 하고에 서버를 시작 로컬 호스트 .

6. 결론

이 기사에서는 REST API와 유사하게 HTTP 서버를 설정하고 엔드 포인트를 노출하여 리소스를 생성 및로드하는 방법을 보여주는 예제를 통해 Akka HTTP의 기본 사항에 대해 배웠습니다.

평소처럼 여기에 제시된 소스 코드는 GitHub에서 찾을 수 있습니다.