'오픈소스'에 해당되는 글 65건

  1. 2017/02/01 용비 2. Building Microservices: Using an API Gateway - 03 Using an API Gateway
  2. 2016/12/20 용비 1. Introduction to Microservices - 03
  3. 2016/03/21 용비 (Chapter 3) 17. Actions
  4. 2015/07/22 용비 Apache Lucene - Getting Started 02
  5. 2015/07/21 용비 Apache Lucene - Getting Started 01
Using an API Gateway

일반적으로 API Gateway로 알려진 것을 사용하는 것이 훨씬 더 좋은 방법이다. API Gateway는 시스템으로 접속하는 단일 진입점 서버이다. Object-Oriented 디자인에서 Facade 패턴과 유사하다. API Gateway는 내부 시스템 아키텍처를 보호하고, 개별 클라이언트에 맞춰진 API를 제공한다. API Gateway는 Authentication(인증), monitoring, load balancing, caching, request shaping(요청 제어) and management(관리), static response handling(정적 응답 처리)를 책임지고 수행한다.

다음 그림은 아키텍처상에서 API Gateway가 어떻게 표현되는지를 보여준다.

사용자 삽입 이미지

API Gateway는 request routing, composition, protocol translation에 대해 완결적으로 수행한다. 클라이언트에서 하는 모든 요청들은 API Gateway를 통과하게 된다. 그리고 그 요청들은 적합한 micro service들에게 라우팅된다. API Gateway는 종종 하나의 요청에 대해 여러 개의 microservice들을 호출하고, 그 결과를 취합하여 응답을 제공할 것이다. API Gateway는 HTTP나 WebSocket과 같은 Web Protocol을 내부에서 사용하는 웹친화적이지 않은 프로토콜로 변환할 수 있다.

API Gateway는 개별 클라이언트에 Custom API를 제공할 수도 있다. 일반적으로 Mobile client에 대해서는 거친 API를 노출한다. 예를 들어, 상품 상세 정보 제공 시나리오를 생각해 보라. API Gateway는 모바일 클라이언트에서 한번의 요청으로 모든 상품의 상세 정보를 얻을 수 있는 하나의 endpoint(/productdetails?productid=xxx)를 제공할 수 있다. API Gateway는 그 요청을 처리하기 위해 다양한 서비스들(product info, recommendations, reviews, etc.)을 호출하고 그 결과를 조합한다.

API Gateway의 가장 좋은 예제는 Netflix API Gateway이다. Netflix streaming service는 televisions, set-top boxes, smartphones, gaming systems, tablets등등의 수백개의 서로 다른 종류의 다비이스에서 사용할 수 있다. 초기에 Netflix는 streaming service를 위해 임의의 크기(one-size-fits-all) API를 제공하려고 했다. 그러나 다양한 범위의 디바이스와 디바이스별 특정 요구사항 때문에 잘 동작하지 않는다는 것을 발견했다. 오늘날, Netflix는 device-specific adapter code를 실행하여 각각의 디바이스에 맞춰진 API르르 제공하는 API Gateway를 사용한다. Adapter는 일반적으로 평균 6~7개의 backend service를 호출하여 각 요청을 처리한다. Netflix API Gateway는 하루에 수십억건의 요청을 처리한다.

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/754

Microservices-Tackling the Complexity
   (Microservice - 복잡함에 태클을 걸다)

Amazon, eBay, Netflix 같은 많은 조직들에서 Microservice Architecture Pattern이라고 알려져 있는 기술을 채택하여 이러한 문제를 해결하고 있다. Microservice Architecture 하나의 괴물같은 monolithic application 만드는 대신에, 작고 서로 연결되어 있는 서비스들의 집합으로 application 나누는 것이다.


일반적으로 서비스는 order management(주문관리), customer management(고객관리), 등과 같은 별개의 특징이나 기능 집합으로 구현되어 있다. 각각의 microservice 자체에 다양한 어댑터에 대한 비즈니스 로직을 가진 6각형의 아키텍처를 가지는 mini-application이다. 어떤 microservice 다른 microservice application client 의해서 호출되는 API 제공하고, 다른 microservice Wen UI 구현할 수도 있다.


런타임시에는 각각의 instance 클라우드 VM이나 Docker container 상에 실행되기도 한다.


예를 들면, 앞서 기술된 시스템을 분해하면, 다음과 같은 다이어그램으로 표현할 있다.


사용자 삽입 이미지


Application 개별 기능은 각각의 microservice 구현되어 있다. 더욱이 web application 간단한 web application 집합으로 나누어져 있다. (택시 호출 서비스 예제에서 보면, 명의 운전 기사가 명의 승객과 매칭되는 경우). 이것은 특정 user, device, 혹은 특별한 use case별로 개별 경험을 쉽게 배포하게 한다.


backend service REST API 제공하고, 대부분의 service들은 다른 service 제공하는 API 사용한다. 예를 들어, Driver Management(기사 관리) 잠재적 이동에 대해 활동 가능한 운전 기사에게 알려주는데 Notification Server 사용한다. UI service들은 web page들을 렌더링하기 위해 다른 서비스들을 호출한다. 서비스들은 메시지 기반의 communication async방식을 사용한다. 서비스간의 communication 대해서는 추가로 나중에 자세히 다룰 것이다.


몇몇 REST API 기사나 승객에 의해 사용되는 mobile app에서 이용한다. 그러나 이러한 app들은 backend service 직접 접속할 없다. 대신에 communication API Gateway 알려진 중재자를 통해 가능하게 된다. API Gateway 로드밸런싱, caching, access control, API metering, monitoring 같은 부분들을 처리해야 한다. 이러한 부분들은 nignx 사용하여 효과적으로 구현할 있다.


사용자 삽입 이미지


Microservice architecture pattern scalability(확장성) 3D Model 대한 최고의 책인 "The Art of Scalability" 나오는 Scale Cube Y Scaling 대응된다. 다른 2개의 Scaling 축은 load balancer 뒤에서 실행중인 여러 개의 동일한 application 복사본으로 구성된  X Scaling 요청의 속성(예를 들면, row primary key 고객의 identity) 특정 서버에 대한 요청으로 route하는데 사용되는 Z Scaling(혹은 data partitioning) 있다.


Application들은 일반적으로 3가지 Scaling 타입을 함께 사용한다. Y Scaling 섹션 첫번째 그림에서 보여주는 대로 application microservice로 분해한다. Runtime 시점에 X Scaling load balancer 뒤에서 처리량과 가용성을 위해 서비스에 대해 여러 개의 instance 실행한다. 어떤 application들은 service partition하기 위해 Z Scaling 사용하기도 한다.


다음 다이어그램은 Trip Management 서비스가 Amazon EC2 서버 상에 Docker 어떻게 배포되는지를 보여준다.


사용자 삽입 이미지


Runtime시에 Trip Management 서비스는 여러 개의 instance 구성되어 있다. 서비스 instance Docker container 제공된다. 가용성을 높이기 위해서 docker container들은 여러 개의 cloud VM에서 돌아간다. Service instance 앞단에는 여러 instance 요청을 분산하는 nginx 같은 load balancer가 있다. Load balancer caching, access control, API metering, monitoring 같은 여러 가지 관심 사항들을 취급할 있어야 한다.


Microservice Architecture Pattern 특히 application database 사이의 관계에 중요한 영향을 준다. 서로 다른 service 하나의 database schema 공유하는 것보다는 각각의 서비스가 독자적인 database schema 갖는다. 다른 한편으로 이러한 접근은 Enterprise-Data Model 관점에서는 이상하다. 또한, 어떤 데이터들은 종종 중복되기도 한다. 그러나 서비스별 database schema 갖는 것은 microservice 통해 혜택을 보기 원한다면, 본질적인 부분이다. 왜냐하면, microservice 느슨한 연결(loose coupling) 보장하기 때문이다. 다음 다이어그램은 예제로 제시된 application 대한 database architecture 보여주고 있다.


사용자 삽입 이미지

각각의 서비스는 자체적으로 데이터베이스를 가지고 있다. 게다가, 서비스별로 소위 polyglot persistence architecture(상황에 맞게 최적화된 구조로 데이터를 구분하여 저장하는 아키텍처)라고 불리는 가장 최적의 데이터베이스 타입을 사용할 있다.


예를 들어, 잠재적인 승객에게 가장 가까운 운전 기사들을 찾아야 하는 Driver Management(기사 관리) geo-query(지리기반 질의) 지원하는 데이터베이스를 사용해야만 한다. 표면적으로는 MSA SOA 유사하다. 두가지 모두 서비스들의 집합으로 구성된 아키텍처이다. 하지만, MSA WS 표준과 ESB 없는 SOA라고 생각하면 된다.


Microservice 기반 application WS 표준보다 굉장히 단순하고, REST 같은 가벼운 프로토콜을 사용한다. 또한 ESB 사용을 지양하고, microservice 자체적으로 ESB 유사한 기능을 구현한다. Microservice Architecture Pattern 정규 스키마(canonical schema) 같은 SOA 다른 부분도 거부한다.

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/747

(Chapter 3) 17. Actions

Spark 2016/03/21 17:15 용비

그동안 서로간의 변형을 통해서 어떻게 RDD 생성하는지를 알아보았다. 하지만, 어떤 경우에는 Dataset 가지고 직접적으로 어떤 일을 하고 싶을 수도 있다. Action RDD operation 번째 형태이다. Action driver program 마지막 값을 되돌려 주거나 외부 storage system 데이터를 쓰는 작업을 수행한다. Action RDD 호출하는 곳에서 필요로 하는 변형에 대해서 평가하기 때문에 실제적인 ouput 만들어낼 필요가 있다.


앞의 섹션의 log example에서 계속해서 살펴보자면 badLinesRDD 대해 어떤 정보를 출력하고 싶을 수도 있다. 그렇게 하기 위해서는 2가지 action 사용할 있다. count() 숫자를 값을 리턴하고, take() RDD element collection 리턴한다. 샘플코드는 3-15, 3-17에서 있다.


Example 3-15. Python error count using actions

print "Input had " + badLinesRDD.count() + " concerning lines"

print "Here are 10 examples: "

for line in badLinesRDD.take(10):

     print line


Example 3-16. Scala rror count using actions

println("Input had " + badLinesRDD.count() + " concerning lines")

println("Here are 10 examples:")

badLinesRDD.take(10).foreach(println)


Example 3-17. Java error count using actions

System.out.println("Input had " + badLinesRDD.count() + " concerning lines")

System.out.println("Here are 10 examples:")

for (String line : badLinesRDD.take(10)) {

     System.out.println(line);

}


위의 예제에서, driver program에서 작은 숫자의 RDD element 추출하기 위해서 take() 사용했다. Driver 정보를 출력하기 위해서 반복하여 출력했다. RDD 전체 RDD 추출하기 위해서 collect() 함수를 가지고 있다. 만약 프로그램 필터에서 RDD 아주 작은 크기로 줄여서 내부적으로 다루고자 하는 경우에 유용하게 사용할 있다. 다만, 전체 dataset collect() 사용하여 하나의 machine 메모리 크기에 적합해야 한다는 것을 유념해야 한다. 따라서 collect() large dataset 대상으로는 사용하지 않아야 한다.


대부분의 경우, RDD driver 직접적으로 collect()함수를 사용하여 데이터를 추출할 없다. 왜냐하면 dataset 너무 크기 때문이다. 이러한 경우에는 HDFS Amazon S3 같은 분산 저장환경에 데이터를 쓰는 경우가 일반적이다. 또한 saveAsTextFile() action, saveAsSequenceFile()이나 다양한 내장된 형태로 다른 많은 action 사용하여 RDD 내용을 저장할 있다. 데이터를 추출하는 다른 option 대해서는 Chapter 5에서 다룰 것이다.


새로운 action 매번 호출할 때마다 전체 RDD " 처음부터"(from scratch) 계산되어야 한다는 것을 아는 것이 중요하다. 이러한 비효율성을 피하기 위해서 44페이지에서 "Persistence (Caching)"으로 다루는 중간 결과를 유지할 있다.

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/743

Apache Lucene - Getting Started 02

Lucene 2015/07/22 22:06 용비

Introduction to Lucene's API : 다른 Lucene Pakcages들의 high-level summary

Materials

    • Apache Lucene은 고성능의 full-featured text search engine library이다. 여기 indexing을 하고 searching을 하는데 Lucene을 어떻게 사용하는지 예제가 있다. (기대한 결과를 check하기 위해 JUnit을 이용한다.)

      Analyzer analyzer = new StandardAnalyzer();
       
          // Store the index in memory:
          Directory directory = new RAMDirectory();
          // To store an index on disk, use this instead:
          //Directory directory = FSDirectory.open("/tmp/testindex");
          IndexWriterConfig config = new IndexWriterConfig(analyzer);
          IndexWriter iwriter = new IndexWriter(directory, config);
          Document doc = new Document();
          String text = "This is the text to be indexed.";
          doc.add(new Field("fieldname", text, TextField.TYPE_STORED));
          iwriter.addDocument(doc);
          iwriter.close();
           
          // Now search the index:
          DirectoryReader ireader = DirectoryReader.open(directory);
          IndexSearcher isearcher = new IndexSearcher(ireader);
          // Parse a simple query that searches for "text":
          QueryParser parser = new QueryParser("fieldname", analyzer);
          Query query = parser.parse("text");
          ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs;
          assertEquals(1, hits.length);
          // Iterate through the results:
          for (int i = 0; i < hits.length; i++) {
            Document hitDoc = isearcher.doc(hits[i].doc);
            assertEquals("This is the text to be indexed.", hitDoc.get("fieldname"));
          }
          ireader.close();
          directory.close();
    • Lucene API는 몇가지 package로 구분된다.

      Icon

      org.apache.lucene.analysis : Reader에서 TokenStream으로 text를 변환하는 추상화된 Analyzer API 정의.

      org.apache.lucene.codecs : index 구조를 뒤집어서 encoding/decoding하는 추상 계층 제공.

      org.apache.lucene.document : 간단한 Document class 제공. Document는 Field들의 집합이다. 값으로는 String이나 Reader를 가질 수 있다.

      org.apache.lucene.index : 2개의 주요 class 제공. IndexWriter - index에 document를 생성, 추가. IndexReader - index의 data에 access.

      org.apache.lucene.search : query를 설명하는 data 구조 제공. (ex. 개별 단어에 대한 TermQuery, Phrase에 대한 PhraseQuery, query상의 boolean 조합에 대한 BooleanQuery). IndexSearcher - TopDocs로 query를 바꿈. QueryParser의 개수는 string이나 xml로부터 query 구조를 만들어 내기 위해 제공된다.

      org.apache.lucene.store : persistent data를 저장하기 위한 추상화 클래스. Directory는 IndexOutput에 의해 쓰여지거나 IndexInput에 의해 읽혀진 named file의 집합이다. FSDirectory를 포함하여 여러 가지 형태의 구현체가 제공된다. RAMDirectory는 메모리에 데이터 구조를 쓰기 위한 구현체이다.

      org.apache.lucene.util : FixedBitSet과 PriorityQueue와 같은 몇 가지 데이터 구조와 util class를 포함하고 있다.


    • Lucene을 사용하기 위해서, Application은 다음과 같이 해야 한다.

      • Fields를 추가하기 위해서는 Document를 생성해야 한다.

      • IndexWriter를 생성하고 addDocument()를 통해서 document를 추가해야 한다.

      • String으로부터 Query를 생성하기 위해서는 QueryParser.parse()를 호출해야 한다.

      • IndexSearcher를 생성하고 search() method에 query를 전달해야 한다.

    • 간단한 code example은 다음과 같다.

      • IndexFiles.java : directory에 있는 모든 파일들에 대해서 index를 생성한다.

      • SearchFiles.java : query를 입력하고, index를 검색한다.

    • 이것을 설명하기 위해서 다음과 같이 실행해 보라.

      > java -cp lucene-core.jar:lucene-demo.jar:lucene-analyzers-common.jar org.apache.lucene.demo.IndexFiles -index index -docs rec.food.recipes/soups
      adding rec.food.recipes/soups/abalone-chowder
       [ ... ]> java -cp lucene-core.jar:lucene-demo.jar:lucene-queryparser.jar:lucene-analyzers-common.jar org.apache.lucene.demo.SearchFiles
      Query: chowder
      Searching for: chowder
      34 total matching documents
      1. rec.food.recipes/soups/spam-chowder
       [ ... thirty-four documents contain the word "chowder" ... ]
      Query: "clam chowder" AND Manhattan
      Searching for: +"clam chowder" +manhattan
      2 total matching documents
      1. rec.food.recipes/soups/clam-chowder
       [ ... two documents contain the phrase "clam chowder" and the word "manhattan" ... ]
       [ Note: "+" and "-" are canonical, but "AND", "OR" and "NOT" may be used. ]
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/735

Apache Lucene - Getting Started 01

Lucene 2015/07/21 18:01 용비

Lucene은 Java 기반 Full-text search engine이다.

Lucene은 완전한 application이 아니라, 검색 기능을 제공하고자 하는 Application에 쉽게 사용할 수 있는 code library이고 API를 제공한다.

Apache Lucene 5.2.1에 대한 official documentation에 대해서 정리해 보고자 한다. 추가적인 문서는 Wiki(http://wiki.apache.org/lucene-java)에서 살펴볼 수 있다.

Getting Started

다음 섹션은 getting started guide를 제공하고자 하는 목적으로 작성되었다.

다음 3가지 유형의 사용자를 대상으로 한다.

1) Application에 Apache Lucene을 처음 설치하고자 하는 사용자

2) Lucene 기반 Application을 개발하거나 수정하고자 하는 개발자

3) Lucene 개발에 참여하거나 기여하고자 하는 개발자

Lucene에 대한 깊은 개념이나 상세한 내용을 다루지는 않는다.

Lucene demo, its usage, and sources : Command-line Lucene demo에 대한 tutorial.

    • Lucene demo를 사용하고 실행하기 위한 getting started guide로 기획된 문서.
    • 기본적인 설치와 설정에 대해서 다루고 있음.
    • Lucene command-line demo code는 Lucene의 다양한 기능과 application에 Lucene을 어떻게 추가하여 사용할 수 있는지를 설명하는 application으로 구성되어 있음.
    • 먼저 가장 최근 배포한 Lucene을 다운로드(http://www.apache.org/dyn/closer.cgi/lucene/java/)하고 working directory 에 압축해제한다.
    • 4개의 jar가 필요하다 : Lucene jar, queryparser jar, common analysis jar, Lucene demo jar.
    • 이 4개의 jar 파일을 java CLASSPATH에 위치시킨다.

    • CLASSPATH가 잘 잡혔다면, java org.apache.lucene.demo.IndexFiles -docs {path-to-lucene}/src 로 index를 생성할 수 있다.
    • 위의 결과로 모든 lucene source code에 대한 index를 포함하고 있는 index라고 불리는 subdirectory를 생성할 것이다.
    • index를 검색하기 위해서 java org.apache.lucene.demo.SearchFiles 라고 치면, query를 입력하라는 prompt가 든다.
    • 횡설수설하는 말이나 임의의 단어를 쳐보자. 검색 결과가 없음을 볼 수 있다.
    • string이라는 단어를 쳐보자. 모든 document에 대해서 리턴할 것이다.
    • 매 10개의 결과를 보여주는 페이지가 뜨고, 계속해서 더 많은 결과를 볼 것인지 묻는다.


    • 다음 2가지 source code를 살펴보자.
      • IndexFiles.java : Lucene index를 생성하는 코드
        앞에서 논의한 것처럼, IndexFiles class는 Lucene index를 생성한다. 어떻게 동작하는지 알아보자.
        main() method는 command-line parameter를 파싱한다. 그 후, IndexWriter를 초기화하고, Directory를 open하고, StandardAnalyzer와 IndexWriterConfig를 초기화한다.

        -index command-line parameter 값은 모든 index 정보가 저장되어야 할 filesystem directory의 이름을 의미한다.
        만약, IndexFiles가 command-line에서 주어진 -index parameter에 대해 상대경로로 호출되거나 -index값이 주어지지 않는다면, "index" 경로로 default 상대 경로가 사용되기 때문에 index path는 현재 working directory의 subdirectory로 생성될 것이다. (이미 존재하지 않는다면). 어떤 플랫폼(OS)에서는 index path가 다른 directory에 생성될 것이다. (ex. user's home directory)

        -docs command-line 파라미터 값은 index된 파일들이 있는 directory의 위치를 의미한다.

        -update command-line 파라미터 값은 이미 존재하는 index에 대해서 IndexFiles가 삭제하지 않도록 한다.

        Lucene Directory는 index에 정보를 저장하기 위해서 IndexWriter가 사용한다. 게다가, 확장하여 사용하는 FSDirectory는 RAM이나 데이터베이스와 같은 곳에 write할 수 있는 몇가지 다른 Directory의 subclass들이 있다.

        Lucene Analyzer는 text를 indexed tokens로 쪼개는 pipeline 프로세스를 처리한다. 또한 소문자화, 유사어 삽입, 원치 않는 token 필터링과 같은 동작을 수행한다.
        Analyzer는 StandardAnalyzer를 사용하고, Unicode Standard Annex #29에 정의된 Unicode Text Segmentation 알고리즘에 의한 word break rule을 사용하여 token을 생성한다. token을 소문자화하고, 불용어를 걸러낸다. 불용어는 a, an, the와 같은 일반적인 단어들과 검색에 잘 쓰이지 않는 token들을 의미한다. 각 언어마다 다른 rule이 있기 때문에 각각의 경우에 적합한 analyzer를 사용해야 한다. Lucene은 현재 많은 다른 언어에 대해 Analyzer를 제공한다.

        IndexWriterConfig instance는 IndexWriter에 대한 모든 설정을 담고 있다. 예를 들면, -update command-line 파라미터에 근거하여 사용할 수 있도록 OpenMode를 설정할 수 있다.

        파일 내에서 더 아래로 내려가보면, IndexWriter가 초기화된 이후, indexDocs() code를 볼 수 있다. 재귀함수는 directory들을 크롤링하면서 Document object를 생성한다. Document는 간단한 file에 있는 text content와 생성 시간, 위치를 표현하는 data object이다. 이런 Document들은 IndexWriter에 추가된다. 만약 -update 파라미터가 주어지면, IndexWriterConfig의 OpenMode는 OpenMode.CREATE_OR_APPEND로 설정될 것이다. 그리고 index에 document를 추가하기보다 IndexWriter는 동일한 identifier로 이미 indexed된 document인지 확인한 후, 있으면 지우고 index에 새로운 document를 추가하는 방식으로 update할 것이다.

      • SearchFiles.java : Lucene index를 검색하는 코드

        SearchFiles class는 매우 간단하다. IndexSearcher, StandardAnalyzer(IndexFiles에서 사용하는 것과 동일함), QueryParser와 협업한다. Query parser는 document가 해석되는 것과 동일한 방식으로 query text를 해석하는데 사용하는 analyzer이다. word boundary를 찾고, 소문자화한 이후, a, an, the와 같이 불필요한 단어를 제거한다. Query object는 searcher로 넘겨지는 QueryParser의 결과를 담고 있다. Query Parser를 사용하지 않고 프로그램으로 Query object를 만들 수도 있다. query parser는 Query object와 일치하도록 lucene query syntax를 decoding할 수 있다.

        SearchFiles는 최대 n번의 hit를 가지는 TopDocs를 리턴하는 IndexSearcher.search(query, n) method를 사용한다. 그 결과로 score로 정렬된 page들을 print한다.

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/734