Apache Storm 버전 : Storm 1.0.0 released (12 Apr 2016)

Apache Kafka 버전 : 0.9.0.1 (2016년 4월 20일 글쓴시점) 

Spark Streaming 버전 : 1.6.1 (2016년 3월 9일)  


Apache Storm 

스톰은 메세지전달 실패시 바로잡는 능력(fault tolerant) 이 있으며,  다양한 레벨의 메세지 보증 전f략을 가지고 있다. 

  1. at-most-once:  이 모드에서는 만약 실패나 타임아웃이 발생했을때 메세지를 버릴수 있으며, 이 모드는 특별한 핸들링을 요구하지 않으며, 메세지들은 스파웃에 의해 생성된 순서대로 처리된다.
  2. at-least-once:  이 모드는 각각의 스파웃 튜플이 설정된 타임아웃 안에서 "fully" 진행상태인지 아닌지를 추적한다. 어떤 인풋 튜플이 타임아웃 안에 fully 진행 상황이 아니면 다시 발행(re-emiited) 된다.  이 의미는 동일한 튜플이 한번 더 진행될 수 도 있다는 이야기 이며, 순서가 바뀔 수 도 있다. 
  3. exactly-once: Trident 와 함께 사용될때, 스톰은 " exactly-once" 보증을 제공한다. 


읽을꺼리 : Exactly-Once Processing with Trident - The Fake Truth


Apache Kafka 

How do I get exactly-once messaging from Kafka?

Exactly once semantics has two parts: avoiding duplication during data production and avoiding duplicates during data consumption.

There are two approaches to getting exactly once semantics during data production:

  1. Use a single-writer per partition and every time you get a network error check the last message in that partition to see if your last write succeeded
  2. Include a primary key (UUID or something) in the message and deduplicate on the consumer.


If you do one of these things, the log that Kafka hosts will be duplicate-free. However, reading without duplicates depends on some co-operation from the consumer too. If the consumer is periodically checkpointing its position then if it fails and restarts it will restart from the checkpointed position. Thus if the data output and the checkpoint are not written atomically it will be possible to get duplicates here as well. This problem is particular to your storage system. For example, if you are using a database you could commit these together in a transaction. The HDFS loader Camus that LinkedIn wrote does something like this for Hadoop loads. The other alternative that doesn't require a transaction is to store the offset with the data loaded and deduplicate using the topic/partition/offset combination.

I think there are two improvements that would make this a lot easier:

  1. Producer idempotence could be done automatically and much more cheaply by optionally integrating support for this on the server.
  2. The existing high-level consumer doesn't expose a lot of the more fine grained control of offsets (e.g. to reset your position). We will be working on that soon


읽을꺼리 :  Kafka Clients (At-most-once, At-least-once, Exactly-once, and Avro Client)


Spark Streaming

Fault-tolerance Semantics

In this section, we will discuss the behavior of Spark Streaming applications in the event of failures.

Background

To understand the semantics provided by Spark Streaming, let us remember the basic fault-tolerance semantics of Spark’s RDDs.

  1. An RDD is an immutable, deterministically re-computable, distributed dataset. Each RDD remembers the lineage of deterministic operations that were used on a fault-tolerant input dataset to create it.
  2. If any partition of an RDD is lost due to a worker node failure, then that partition can be re-computed from the original fault-tolerant dataset using the lineage of operations.
  3. Assuming that all of the RDD transformations are deterministic, the data in the final transformed RDD will always be the same irrespective of failures in the Spark cluster.

Spark operates on data in fault-tolerant file systems like HDFS or S3. Hence, all of the RDDs generated from the fault-tolerant data are also fault-tolerant. However, this is not the case for Spark Streaming as the data in most cases is received over the network (except when fileStreamis used). To achieve the same fault-tolerance properties for all of the generated RDDs, the received data is replicated among multiple Spark executors in worker nodes in the cluster (default replication factor is 2). This leads to two kinds of data in the system that need to recovered in the event of failures:

  1. Data received and replicated - This data survives failure of a single worker node as a copy of it exists on one of the other nodes.
  2. Data received but buffered for replication - Since this is not replicated, the only way to recover this data is to get it again from the source.

Furthermore, there are two kinds of failures that we should be concerned about:

  1. Failure of a Worker Node - Any of the worker nodes running executors can fail, and all in-memory data on those nodes will be lost. If any receivers were running on failed nodes, then their buffered data will be lost.
  2. Failure of the Driver Node - If the driver node running the Spark Streaming application fails, then obviously the SparkContext is lost, and all executors with their in-memory data are lost.

With this basic knowledge, let us understand the fault-tolerance semantics of Spark Streaming.

Definitions

The semantics of streaming systems are often captured in terms of how many times each record can be processed by the system. There are three types of guarantees that a system can provide under all possible operating conditions (despite failures, etc.)

  1. At most once: Each record will be either processed once or not processed at all.
  2. At least once: Each record will be processed one or more times. This is stronger than at-most once as it ensure that no data will be lost. But there may be duplicates.
  3. Exactly once: Each record will be processed exactly once - no data will be lost and no data will be processed multiple times. This is obviously the strongest guarantee of the three.

Basic Semantics

In any stream processing system, broadly speaking, there are three steps in processing the data.

  1. Receiving the data: The data is received from sources using Receivers or otherwise.

  2. Transforming the data: The received data is transformed using DStream and RDD transformations.

  3. Pushing out the data: The final transformed data is pushed out to external systems like file systems, databases, dashboards, etc.

If a streaming application has to achieve end-to-end exactly-once guarantees, then each step has to provide an exactly-once guarantee. That is, each record must be received exactly once, transformed exactly once, and pushed to downstream systems exactly once. Let’s understand the semantics of these steps in the context of Spark Streaming.

  1. Receiving the data: Different input sources provide different guarantees. This is discussed in detail in the next subsection.

  2. Transforming the data: All data that has been received will be processed exactly once, thanks to the guarantees that RDDs provide. Even if there are failures, as long as the received input data is accessible, the final transformed RDDs will always have the same contents.

  3. Pushing out the data: Output operations by default ensure at-least once semantics because it depends on the type of output operation (idempotent, or not) and the semantics of the downstream system (supports transactions or not). But users can implement their own transaction mechanisms to achieve exactly-once semantics. This is discussed in more details later in the section.

Semantics of Received Data

Different input sources provide different guarantees, ranging from at-least once to exactly once. Read for more details.

With Files

If all of the input data is already present in a fault-tolerant file system like HDFS, Spark Streaming can always recover from any failure and process all of the data. This gives exactly-once semantics, meaning all of the data will be processed exactly once no matter what fails.

With Receiver-based Sources

For input sources based on receivers, the fault-tolerance semantics depend on both the failure scenario and the type of receiver. As we discussed earlier, there are two types of receivers:

  1. Reliable Receiver - These receivers acknowledge reliable sources only after ensuring that the received data has been replicated. If such a receiver fails, the source will not receive acknowledgment for the buffered (unreplicated) data. Therefore, if the receiver is restarted, the source will resend the data, and no data will be lost due to the failure.
  2. Unreliable Receiver - Such receivers do not send acknowledgment and therefore can lose data when they fail due to worker or driver failures.

Depending on what type of receivers are used we achieve the following semantics. If a worker node fails, then there is no data loss with reliable receivers. With unreliable receivers, data received but not replicated can get lost. If the driver node fails, then besides these losses, all of the past data that was received and replicated in memory will be lost. This will affect the results of the stateful transformations.

To avoid this loss of past received data, Spark 1.2 introduced write ahead logs which save the received data to fault-tolerant storage. With thewrite ahead logs enabled and reliable receivers, there is zero data loss. In terms of semantics, it provides an at-least once guarantee.

The following table summarizes the semantics under failures:

Deployment ScenarioWorker FailureDriver Failure
Spark 1.1 or earlier, OR
Spark 1.2 or later without write ahead logs
Buffered data lost with unreliable receivers
Zero data loss with reliable receivers
At-least once semantics
Buffered data lost with unreliable receivers
Past data lost with all receivers
Undefined semantics
Spark 1.2 or later with write ahead logsZero data loss with reliable receivers
At-least once semantics
Zero data loss with reliable receivers and files
At-least once semantics

With Kafka Direct API

In Spark 1.3, we have introduced a new Kafka Direct API, which can ensure that all the Kafka data is received by Spark Streaming exactly once. Along with this, if you implement exactly-once output operation, you can achieve end-to-end exactly-once guarantees. This approach (experimental as of Spark 1.6.1) is further discussed in the Kafka Integration Guide.

Semantics of output operations

Output operations (like foreachRDD) have at-least once semantics, that is, the transformed data may get written to an external entity more than once in the event of a worker failure. While this is acceptable for saving to file systems using the saveAs***Files operations (as the file will simply get overwritten with the same data), additional effort may be necessary to achieve exactly-once semantics. There are two approaches.

  • Idempotent updates: Multiple attempts always write the same data. For example, saveAs***Files always writes the same data to the generated files.

  • Transactional updates: All updates are made transactionally so that updates are made exactly once atomically. One way to do this would be the following.

    • Use the batch time (available in foreachRDD) and the partition index of the RDD to create an identifier. This identifier uniquely identifies a blob data in the streaming application.
    • Update external system with this blob transactionally (that is, exactly once, atomically) using the identifier. That is, if the identifier is not already committed, commit the partition data and the identifier atomically. Else, if this was already committed, skip the update.

      dstream.foreachRDD { (rdd, time) =>
        rdd.foreachPartition { partitionIterator =>
          val partitionId = TaskContext.get.partitionId()
          val uniqueId = generateUniqueId(time.milliseconds, partitionId)
          // use this uniqueId to transactionally commit the data in partitionIterator
        }
      }

읽을꺼리 :  Spark Streaming vs Storm Trident 


다른 읽을꺼리 
High-throughput, low-latency, and exactly-once stream processing with Apache Flink



  1. 생산자 (Sender) 테스트 

    1. 결과 
    2. 이유
      1. 카프카 생산자는 브로커로 부터의 ack 를  기다리지 않고 메세지를 보낸다.브로커가 핸들링 할수있는 만큼 빠르게 메세지를 마구 보낸다.
      2. 카프카는 좀더 효율적인 저장소 포맷을 가지고있다. 평균적으로 카프카 각 메세지들은 9byte 의 오버헤드를 가지며, 반면 ActiveMQ 에서는 144 bytes 를 가진다. 이것은 메세지 헤더때문인데  JMS 에 의해 요구되어진것과 다양한 인덱싱구조를 유지하기위한 것이다. LinkedIn 은 관찰하길  ActiveMQ 의 가장 바쁜쓰레드는 메세지 메타데이터와 상태를 유지하기위한 B-Tree 에 접근하기위해 대부분의 시간을 소비하는것을 발견했다.

  2. 소비자 (Receiver) 테스트

    1. 결과

    2. Reason
      1. 카프카는 좀더 효율적인 저장소 포맷을 가지고있다. 브로커로부터 컨슈머로 데이터 이동시 아주 적은 바이트만 소비된다.
      2. ActiveMQ 와  RabbitMQ 의 브로커는  모든 메세지에 대한 전달 상태를 유지해야한다. LinkedIn 팀은 ActiveMQ 쓰레드들 중 하나를 관찰했는데  KahaDB 페이지를 디스크에 쓰는데 매우 바쁜걸 발견했다.  대조적으로 카프카 브로커상에서는 디스크 쓰기 행위가 없다. 결론적으로 파일에 쓰는 API 를 사용하는것에 의해 카프카는 데이터이동에 관한 오버헤드를 감소시킬수있던것이다.



RabbitMQ는 push모델이고,
 Kafka는 pull 모델이다. RabbitMQ는 prefetch limit라는 소비자측 옵션으로 배압(Back pressure)을 관리하고, Kafka는 소비자가 데이터를  알아서 offset을 통해 땡겨오면서 관리한다. 

Kafka)

- 초당 100k+ 이상의 불같은 이벤트를 처리하려면 이용해라. 
- 온라인이나 배치로 파티션된 순서로 적어도 한번은 배달될 필요가있을때
- 메세지를 다시 읽을 필요가 있을때도 사용해라. 또한 노드레벨 HA 로 흐름제한을 다룰수있을것이다.

RabbitMQ) 

- 초당 20+ 메세지를 복잡한 방식으로 컨슈머에게 라우트하고 싶을때 사용하라. 
- 메세지당 전달보장을 해줄필요가 있을때 사용하라. 
- 배달 순서는 별로 관여치 않을때 사용하라. (순서를 보장하게도 할수있다) 
- 클러스터 노드레벨의 HA 가 필요할때 사용하라.

둘다 쩌는 " Filter / Query"  능력을 제공하지는 않는다. 그러기위해서는 Storm 을 아키텍처에 추가하라


RabbitMQ vs. Kafka

둘다 쩌는 솔루션이다.  
-  RabbitMQ 가 좀더 성숙하다. (Written 12 Sep, 2012)
철학은 좀 다른데, 기본적으로 RabbitMQ 는 브로커 중심적이며, 생산자와 소비자간의 보장되는 메세지 전달에 촛점을 맞추었다.  
- 반면 Kafka 는 생산자 중심적이며, 엄청난 이벤트 데이터을 파티셔닝하는데 기반을 둔다. 배치 소비자를 지원하며, 온라인, 오프라인에 저 지연율(Low latency)을 보장하며 메세지를 전달해준다. 
-  RabbitMQ 는 브로커상에서 전달 상태를 확인하기위한 메세지 표식을 사용한다. 카프카는 그런 메세지 표식이 없으며 컨슈머가 전달(배달) 상태를 기억하는것을 기대한다. 
- 둘다 클러스터간의 상태를 관리하기위해 Zookeeper 를 사용한다. 
- RabbitMQ 는 커다란 크기의 데이터를 위해 디자인되지 않았으며 만약 컨슈머가 매우 느리다면 실패할것이다.그러나 post 2.0 에  RabbitMQ  는 느린 배치 컨슈머를 핸들링 되는게 요청되어졌다.  
-  Kafka 은 오직 토픽같은 exchanges 를 사용한다. RabbitMQ 는 다양한 exchanges 를 사용한다. 토픽/큐 등
-  Kafka 는 파티션들 안에서 메세지 순서를 제공하며, 파티션들간에 엄격한 순서를 가진다. 카프카 컨슈머들은 충분히 스마트해야하며 , 그들 스스로 파티션간의 순서를 해결(resolve) 해야한다.
- Kafka 는 디스크상에서 메세지를 저장하고 데이타 손실을 막기위해 클러스터로 그들을 복제한다. 각각의 성능에 큰 문제없이 브로커는 테라바이트를 핸들링할수있다. Kafka 는 쓰기에 초당  200k 메세지를 , 읽는데는 3M 메세지를  제공되도록 테스트되었다.



이 글은 2015년에 쓰여졌는데, 이전에 ESB (JBoss Fuse, Mule ESB등) 시대에는 "똑똑한 브로커에 멍청한 엔드포인트" 였다면 2020년 현재 마이크로서비스 시대인 만큼 "멍청한 브로커에 똑똑한 엔드포인트" 가치에 적합한 비동기 브리징 모델인 Kafka는 블록체인을 포함한 다양한 분야에서 대유행하고 있으며 Apache pulsar 라는 대항마도 등장했었다. MQ시장에서 Kafka가 압도적으로 사용되는 측면에는 ( 물론 RabbitMQ와 Kafka는 트레이드 오프관계로 사용 용도가 다를 수 있다. 개인적으로는 다양한 어플리케이션의 Integration 용도면 RabbitMQ/ActiveMQ/JBoss AMQ에 조금 성격은 다르지만 Camel 인데 그 이외의 용도는 모두 카프카로 대동단결하는 듯) 먼가 어렵고 귀찮은 표준(JMS, AMQP, MQTT,XMPP)같은 것과 똑똑한 브로커의 기능셋을 신경 안써도 되는 간단한 느낌?? (exactly-once 근본적문제 제외) 그리고 헤더 및 메터데이터 필요 없이 간단한 key,value기반의 pub/sub이면 충분해 받아서 쓰는건 내가 알아서 관리 할께~!! COM+/CORBA/웹서비스가 어려워서 쪼그라들고, 좀 더 쉽다는 SOA(ESB,SOAP)도 생각보다 어려워서 쪼그라든것 처럼... 누군가에겐 너무 허접한 기술인 HTML/JSON처럼 역시 세상은 쉬운 것으로 대동단결하나보다.

Kafka말고 RabbitMQ나 ActiveMQ를 꼭 써야하는 경우에 대해서 정리하면 아래와 같다.


레퍼런스)

http://mungeol-heo.blogspot.kr/2015/01/kafka-vs-rabbitmq-vs-activemq.html  
http://prismoskills.appspot.com/lessons/System_Design_and_Big_Data/Chapter_12_-_RabbitMQ_vs_Kafka.jsp
http://prismoskills.appspot.com/lessons/System_Design_and_Big_Data/Chapter_12_-_RabbitMQ_vs_Kafka.jsp
https://suniphrase.wordpress.com/2015/05/07/messaging-system-comparison-kafka-vs-rabbitmq-vs-activemq/



Friday, January 2, 2015


역주: 메세지큐에 대한 글을 적기 전에 왜 메세지큐냐? 를 먼저 생각해봐야한다.

메세지큐는 그냥 메세지를 전달해주는 서버인건데, 기술자체에 집중할 필요는 나중에 생각해보고 , 처음 생각해볼것은 왜 메세지를 전달하냐인데.. 이것의 가장 큰 이유는 행위(메세지)를 분산시키기 위함이라고 볼수있다. 말이 좀 어려운거 같은데 쉽게 말하면  대부분의 경우 하나의 일을 하기위한 프로세스에서는 쓸 필요가 없다는 뜻이고 , 어떤 행위에 대한 프로세스가 여러갈래인 경우에 사용하면 된다. 예를들어 브라우저에서 사용자가 버튼은 클릭했을때, 서버에 전달된 행위를 디비에 전달하고 바로 리턴해주는게 하나의 프로세스이라고 보면, 그 행위를 다른곳으로 전파시킬 필요가 있을때 메세지큐를 사용한다. 

실질적인 예로는 소셜서버에 글을 올렸을때, 내가 글을 올린것을 즉시 확인해야하는 나 자신을 위한 프로세스는 가장 우선되야하며, 내가 올린글이 다른사람에게 전달(feed) 되기 위한 시간은 즉시가 아니어도 된다. 그때 처음 버튼을 눌렀던 행위를 메세지큐에 던저넣고 바로 리턴한후에 나 자신을 위한 프로세스가 즉각적으로 응답되게 하는것이다. 

또 다른 예로는 IoT 엣지디바이스가 데이터를 생성하면 그 데이터를 메인 스트리밍을 따라서는 즉각적으로 사용자한테 전달되며 , 또다른 갈래로는 스톰같은 실시간 분석도구 라든지, 다른 서버로 보내는데 사용할수있다는것이다. 역시 행위(메세지) 를 여러갈래로 분산시킨다고 보면된다.



Hello World!




 * 메세지를 차례로 보내면 차례로 받는다. 





Work Queues

Distributing tasks among workers (the competing consumers pattern) (워커에게 하나씩 균등히 나누어 준다)

Round-robin dispatching


메세지를 하나의 큐에 보내면 , 소비자들이 하나씩 사이좋게 나누어 갖는다.
* 보내는쪽은 하나 받는쪽은 여러개

Fair dispatch



메세지를 하나의 큐에 보내면 , 소비자들이 나누어갖는데, 시간배분을 해준다. (위처럼 라운드로빈이라면 홀수로 받는 워커에 일이 가중될수도있다. 홀수로 보내지는 일이 항상 많을경우) 

Publish/Subscribe

Sending messages to many consumers at once (모든 소비자에게 다 준다) 

Exchanges


 * Exchanges 를 통해 여러개의 큐에  보낸다.  

 * 워커큐와 다른점은 워커큐는 항상 하나의 메세지는 하나의 컨슈머만 받을수있다는것이고, 

   생산자/소비자 패턴에서는 하나의 메세지를 여러 워커가 받을수있다라는 점. 

Bindings


Putting it all together



Routing

Receiving messages selectively (원하는 것을 가져가게 한다)

Direct exchange

 * Exchanges 를 통해 여러개의 큐에  구분하여  보낸다.  예를들어 한쪽은 크리티컬하여 하드에 저장될필요가있는것들이고 하나는 그냥 콘솔에 보여지고 버리는 로그 메세지들.

Multiple bindings



Putting it all together



Topics

Receiving messages based on a pattern (topics) (특정 패턴에 기반해 나누어 가진다) 

Topic exchange





RPC

Request/reply pattern




레퍼런스: https://www.rabbitmq.com/getstarted.html  


MQTT 시작하기 좋은 글 

https://dzone.com/refcardz/getting-started-with-mqtt


MQTT 란?

(http://www.codejs.co.kr/mqtt-mq-telemetry-transport%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0/ 펌)


[MQTT 프로토콜 설계의 의도]
  • 프로토콜이 차지하는 모든 면의 리소스 점유(footprint)를 최소화
  • 느리고 품질이 낮은 네트워크의 장애와 단절에 대비
  • 클라이언트 애플리케이션 동작에 자원 활용이 극히 제한적임을 고려
  • 다수의 클라이언트 연결에 접합한 Publish/Subscribe 네트워크 채용
  • 신뢰성 있는 메시징을 위한 QoS(Quality of Service) 옵션 제공.
  • 개방형 표준 메시징 프로토콜을 지향 –  제 3자(3rd Party) 기기 제조업체와 소프트웨어 개발업체의 용이한 도입, 적용을 유도
[주요 특징]
  • IBM과 Eurotech(Arcom)에 의해 1999년 최초 개발
  • 센서/장치 + 모바일 기기들의 연결을 위한 프로토콜
  • MQTT 프로토콜 오픈소스로 공개 (http://www.mqtt.org)
  • 단순하고 미니멀한 Pub/Sub 메시징 체제
    – 기업 경계 박의 Edge 네트워크 장치와 기업 내의 백엔드 애플리케이션 간 메시지 교환에 접합
    – 간편한 메시징을 위한 직관적 verb set(connect/disconnect publish/subscribe) 제공
  • 오버헤드를 최소화
    – 가장 작은 메시지 사이즈는 2byte: 가변길이 MQTT헤더 + 애플리케이션 Payload
    – Payload 데이터에 중립적: 별도의 다른 애플리케이션 헤더 불필요
    – 클라이언트 라이브러리: C버전은 30KB, Java 버전은 100KB 내외
  • Pub/Sub에 있어서 메시징 신뢰성을 위한 세가지 QoS(Quality of Service) 레벨 제공
    – 반드시 전달되어야하는 중요 메시지에 대한 전달 보장
    – 0 메시지가 최대 1번 전달, 유실 가능성 있음
    – 1 메시지가 최소 1번 전달, 중복 전달 가능성 있음
    – 2 메시지가 단한번, 정당성 있게 전달
  • 클라이언트와 서버간의 연결을 잃었을때 이를 보정하기 위한 자체 기능
    – Last will and testament: 클라이언트가 예고 없이 연결을 잃을 경우 이벤트가 서버에서 발생,
    서버 측에서 연결의 유실 여부 인지
    – Durable subscription: 서버에 클라이언트의 구독(subscription)정보 저장됨,
    세션 종료 후 재접속 시에도 재작업 없이 Pub/Sub유지
    – Clean session 기능: 연결 해제 후 다시 연결되었을 때의 이전 세션 유지/삭제 선택
[이외 특징]
  • FB 메신져가 이걸 사용. 국내 통신사 PUSH 서버도 이걸 사용함
  • 일단 FB가 쓰니, 동남아권 Telco에서 패킷 걸리는 문제는 없을듯
  • Qos 0,1,2로 해서, 2 의 경우 message delivery를 gurantee함
  • 저전력!! 이게 중요.
  • XMPP에 비해서 훨씬 경량. (XMPP는 XML, MQTT는 byte로 보내는데, 2바이트부터 시작)
  • MQTT 서버를 라즈베리와 같은 임베디드 서버에도 넣을 수 있음. IOT용!! 즉 Things가 서버가 될 수 있다!!
  • 대부분 사용자 인증만 제공 (user id/password 방식) 이것도 대부분 서버들이 파일에 저장한다. (IDM이나 KEY 시스템과 연계 필요)
  • TLS/SSL은 지원. X.509 인증서를 이용한 양방향 인증도 지원


mosquitto 

- 간편해서 좋기는 한데. C 기반. 그리고 클러스터링이 안됨.  (HA, Fail over는 어케 한다냐?). Facebook이 쓴다고 하는데. Consistent hashing같은걸 써야 하는데, Fail back이 복잡할듯

- user authentication을 이건. file에 넣고 한다.

- 테스트 해보니 일정 시간 패킷이 안오면 하트비트 메세지 보내기 시작하고, 메세지가 안오면 끊어 버린다.


HiveMQ (저가 상용)

- Clustering 됨 (Infinispan 씀)

- JMX 모니터링 디는 걸로 봐서. 이것은 JAVA

- MultiCast로 클러스터링을 하지만, TCP로 Fixed Size 클러스터나, AWS EC2 클러스터 지원이 가능함.

- AWS/Azure 모두 지원

- 근데 회사가 좀 작아 보인다?? 독일 SI회사


Rabbit MQ

- shared memory 구조가 없어서 어떻게 하는가 궁금하기는 하지만, federation이나 shovel 컨셉을 쓰면 WAN 구간도 가능하기 때문에, 주의깊게 볼만함. 무엇보다 무료에다가 상대적으로 Learning curve가 낮음.

- MQTT 3.1 지원

- QoS0과 1만 지원 (2는 지원 안함)

- SSL 지원

- Session stickiness 지원


IBM MQ 

- http://www-03.ibm.com/software/products/en/wmq-telemetry 이게 갑인듯




Mosquitto (http://mosquitto.org/) 


모스키토는 MQ Telemetry Trasport  프로토콜 버전 3.1 과 3.1.1 을 구현한 오픈소스 메세지브로커이다. MQTT 는 생산자/소비자 모델을 사용한 메세지 이동에 관한 가벼운 메소드를 제공한다. 이것은  저전력 파워센서 나 모바일 디바이스 , 임베디드 컴퓨터나 아두이노 마이크로 컨트롤러  같은 "디바이스 to 디바이스 " 간의 메세징을 처리하기에 적합하다. 



관련 내 블로그 글 

http://brad2014.tistory.com/389



실제 빅데이터 플랫폼 속의 위치 (http://brad2014.tistory.com/185)





http://opentsdb.net/overview.html를 번역했다. OpenTSDB 는 사물인터넷 분야에서 많이 사용되며, 잘 알려진 에너지 IoT 기업인 OPower (http://blog.opower.com/category/technology/) 에서도 사용중이다.


OpenTSDB 는 타임 시리즈 데몬(
Time Series Daemon (TSD)) 들로 구성된다.(몇몇 커맨드라인 유틸리티셋 포함)
OpenTSDB  상호작용은 TSD 하나 혹은 그 이상이 작동하면서 이루어진다. 각각의  TSD 는 독립적이며 
상태공유없이 돌아가기때문에 여러가지 일들을 하기위해  여러 TSD 들에게 일거리를 던져주는데 아무 문제없다.

각각의 TSD 는 HBase 오픈소스 데이타베이스를 사용하며 타임시리즈데이터를 가져와서 저정한다. HBase 스키마는 저장공간을 줄이기위해 비슷한 타임시리즈를 빠르게 집약하는것에 대해 최적화 되어있다. TSD 유져들은 HBase 에 직접적으로 접근할 필요가 없다. 간단한 텔넷 스타일 프로토콜/HTTP API/ 간단한 빌트인 GUI 등을 경유해서 TSD 와 커뮤니케이션할수있다. 모든 커뮤니케이션들은 동일한 포트상에서 발생한다. (TSD 는 처음 몇바이트를 읽어서 클라이언트의 프로토콜을 이해한다.)




쓰기


OpenTSDB 를 사용하는 첫번째 단계는 TSDs 에 타임시리즈 데이터를 보내는것이다.   여러가지 툴(tools )들이  다양한 소스로부터 데이터를 꺼내서 OpenTSDB 에 넣기위해  존재한다. 만약 당신이 필요한 툴을 찾지 못한다면 직접 스크립트를 짤 필요가 있다.  (e.g. by reading interesting metrics from /proc on Linux, collecting counters from your network gear via SNMP, or other interesting data from your applications, via JMX for instance for Java applications) 그리고 TSDs 중 하나에 데이터 포인트들을 주기적으로 푸시하면 된다.

StumbleUpon 는  tcollector  라 불리는 파이썬 프레임워크를 썼는데(wrote) , Linux 2.6, Apache's HTTPd, MySQL, HBase, memcached, Varnish 등으로 부터 수천가지의 계측데이터를 모으기위해 사용되었다. 
이런 적은 영향(
low-impact)을 주는 프레임워크는 몇가지 쓸만한 컬렉터들을 포함하고, 그 커뮤니티는 꾸준히 그 이상의 기능을  제공한다. OpenTSDB 와 상호작용하는 프레임워크들은  Collectd /  Statsd  / the Coda Hale metrics emitter 를 지원하며 포함한다. OpenTSDB 에서 , 타임시리즈 데이타 포인트는 다음과 같이 구성된다:


  • 계측(Metric) 이름.
  • UNIX 타임스탬프 (seconds or millisecinds since Epoch).
  • 값 (64 bit integer or single-precision floating point value).
  • 태그들의 셋  (key-value 쌍 )  포인트에 해당하는 타임시리즈를  나타낸다.

태그들은 다른 소스들 또한 연계된 엔터티들로 부터 유사한 데이터 포인터들을 구분하기위해 사용된다.  그래서 당신은 쉽게 그들을 개별적으로 또는 그룹으로 나타낼수 있다. 태그는 머신의 이름을 가진 주석된 데이터 포인트들로 구성된다. (머신이 포함된 pool 또는 클러스터의 이름도~) 이것은 당신이  서버의 논리적 풀의 집약상태를 보여주는 데쉬보드 뿐만아니라 추가적으로 서버당 당신의 서비스의 상태를  나타내는 데쉬보드를 쉽게 만들수있게한다.

mysql.bytes_received           1287333217 327810227706             schema=foo host=db1
mysql.bytes_sent                  1287333217 6604859181710           schema=foo host=db1
mysql.bytes_received           1287333232 327812421706             schema=foo host=db1
mysql.bytes_sent                  1287333232 6604901075387           schema=foo host=db1
mysql.bytes_received           1287333321 340899533915             schema=foo host=db2
mysql.bytes_sent                  1287333321 5506469130707           schema=foo host=db2

이 예는 4개의 다른 타임 시리즈에 속한 6개의 데이터포인트를 보여준다. 각각의  계측과 태그의 컴비네이션들은 다른 타임 시리즈를 만들어낸다.  
4개의 타임시리즈 모두는 2개의 계측(
metrics) 은mysql.bytes_received or mysql.bytes_sent중 하나이다.

 데이터 포인트는 최소한 하나의 태그를 가져야하고  계측에 대한 매 타임 시리즈들은 동일한 숫자의 태그(역주: 위의 예는 2개) 를 가져야한다.  데이터 포인트당 6~7개 이상의 태그를 갖는건 추천하지 않는다. 새로운 데이터 포인트와 연계된 비용이 포인트 넘어 태그의 숫자에 지배되기 때문이다.

위의 예의 태그를 가지고서  쉽게 호스트 또는 스키마당 MySQL 의 네트워크 액티비티를 보여주는 그래프나 데쉬보드를 생성할수있을것이다. OpenTSDB 2.0 은 계측의 질과 메타데이터를 추적하는  데이터 포인트들과 함께 non-numeric 주석을 저장할수있게됬다. 


읽기

타임시리즈 데이터는 라인 그래프로 보통 그려질수있다. 그래서 OpenTSDB  는 그래프를 생성기위해  하나 혹은 그 이상의 계측과 태그를 선택하는 빌트인 심플 유저인터페이스를 제공한다.

 HTTP API 는  monitoring frameworks /  dashboards / statistics packages or automation tools 같은 외부  시스템들과  묶여서  OpenTSDB 에서 활용된다. 관련된 툴들을 보기위해  resources 페이지로 가자.  



저는 최근에 사물인터넷 플랫폼에 대해 살펴보는 중에 OSGi 에 대해서 좀 더 관심을 갖게되었습니다. (예전에 이클립스 플러그인 책에서도 쳐음 접하고..) OSGi 는 얼핏 보기에 JNDI 가 제공하는 리소스투명성 및 컴포넌트 베이스 기반 방법론을 합쳐놓은 느낌입니다. 당연하지만 예전부터 많은 컴포넌트 조립 기술(CORBA, COM+) 들이 난립해 왔기 때문에 각각 기술들의 테두리가 분명할리는 없겠지요.  2008년에 쓰여진글이라 좀 됬지만 OSGi 가 궁금하신분은 아래 번역글을 통해서 첫인사를 해보시길 바랍니다. 딱히 OSGi 가 궁금하지 않더라도 옛날얘기 들려주듯이 작성된 IT 선배의 개발 모델 이야기는 충분히 재미있을것입니다. ( 2020년 현재 업데이트:  참고로 자바 9버전의 모듈리티를 이용하면 좀 더 편하게 모듈화를 할 수 있습니다. 그렇다고 OSGi를 대체하진 못합니다. 가장 큰 부분이 자바9 모듈리티는 컴파일 타임에 적용되며, OSGi는 런타임에 설치/업그레이드/제거 까지 할 수 있습니다. 쓰임새에 따라서 달리 사용되거나, 혼용해서 사용 될 수 있을 것 입니다. )



원글 링크 : https://queue.acm.org/detail.cfm?id=1348594

* 번역에 심각한 오역이 있거나, OSGi 에 대한 정보를 공유해주시면 더욱 이 글을 번역한 보람이 있을것입니다. 감사합니다. 

OSGi 가 어떻게 내 삶을 바꾸어 놓았나  

1980년 초반 나는 OOP (object-oriented programming)  를 알게되었으며  홀딱  빠져서 사랑하게 되었다.보통 이런 종류의 사랑은 이 새로운 기술에 투자하기 위해 경영진을 설득시킨다는걸 의미한다. 그리고 무엇보다 중요한것은 쩌는 컨퍼런스에 가볼수있게 된다는 것이다. ㅎㅎ 그래서 나는 상관에게 이 기술의 장미빛 미래에 대한 썰을 풀었다. 어떻게 하루만에 이미 존재하는 클래스들로부터 어플리케이션을 만들수있는지~ 클래스들을 저장소(repository) 로부터 가져와서 그것들을 조합하고 뚝딱똑딱 거리면 새로운 어플리케이션이 쑴풍쑴풍 생겨난다고...

오늘날 우리는  당연히 객체들을 사용한다. 그러나 솔직히 말하자면 1985년에 내가 상관에게 했던 장미빛 이야기는 실제로 구체화 되지 않은거 같다. 객체의 재사용은 결코 사람들이 예견한 수준을 넘지 못했고 여전히 레고 이론은 추구해야 할 경배의 대상이며 다다를수없는 성배와 같다. (역주: 2020년 현재도 요원하다. 다행이 JSON-HTTP가 대세가 됬는데 역시 쉬운게 먹힌다는 걸 방증한다. COM+, 웹서비스,SOA 다 대중성과는 멀다.) 

우리가 필요한것

늦은 90년대, 에릭슨연구소에서 일하는 동안, 나는 레고이론을 탐구할 기회가 생겼다. 홈 오토매이션에 대한 소프트웨어 표준화 작업에 참여하게되었는데 이 작업은 IBM, 에릭슨, 노텔, 사이베이스, 썬, 프랑스 텔레콤, 모토롤라, 필립스등 여러 회사들의 참여하에 시작되었고 그 회사들은 나중에 OSGi 얼라이언스 (오픈 동적 컴포넌트 플랫폼을 진행하기위한) 가 되었다. 우리가 1999년에 직면한 핵심 문제점은 어떻게 여러 임베디드 컴퓨터들 사이에 여러 밴더들의 어플리케이션들이 신뢰성 있게 리소스를 공유하며 함께 작동 할 수 있는지 였다. 간단한 말처럼 들리지만 , 집에는 여러 디바이스들이 연결된 다양한 종류의 네트워크로 이루어져있다. 고로 어플리케이션이 각각 다른 리소스와 기능을 재사용할수있는 모델이 필요하다는것은 처음부터 자명한 일이었다. 

여러 어플리케이션들이 각각 그것의 드라이버들과 라이브러리를 포함하게 강제하는 모델은 알맞지 않다. (예컨데, 오늘날 자바 폰 소프트웨어가 작동하는 방식)  또한 패쇄적인 API 셋도 마찬가지인데 , 타겟 마켓(역자: 스위치,계량기,수많은 센서들) 의 다양성이 너무 크기 때문이다. 더 중요한점은 우리는 이런 어플리케이션들이 서로에 대한 선행지식 없이 어울려지길 바랬던 것이다. 추가적으로 간편한 플러그인 방식이길 바랬다. 새로운 기능 추가를 위해 홈 서버를 내려야만 하는것은 그닥 매력적이지 않다. 1999년에 OSGi 얼라이언스가 출범한것을 상기시켜보면 윈도우95가 주류였는데 기술그룹에서 우리들은 약간의 설정만 바꿔도 PC 가 재부팅되는것에 질려있었다. "No reboot" 는 일찍부터 우리의 경구(mantra)가 되었다.또 다른 경구는 OSGi 얼라이언스 멤버회사들이 크고 작은 범위에서 그들 자신의 방법대로 스펙을 구현 할 수 있다는 것이다. 즉  여러 공급자들로 부터 온 각각의 부분들이 콜라보레이션이 될 수 있어야 한다는 것이다. 

그런 환경에서 보안은 옵션이 아니다. 시작부터 명확해야한다. 보안은 아키텍쳐안에서 구축되어져야한다. 다른 신뢰레벨을 가진 여러 리소스로 부터 어플리케이션을 실행하는 능력은 중요한 요구항목이다. 우리는  퍠쇄 시스템, 벽으로 둘러쌓인 정원, 완전하게 개방적인 시스템 등을 충분히 지원해야한다.

홈서버를 위한 환경선택은 우리가 해야할 첫번째 결정 사항이었다. 이것은 그렇게 힘들지 않았는데 자바는 경쟁자가 없었으며 선 마이크로시스템즈( Object-Oriented 언어로 유명한 ) 는 OSGi 멤버였다. 그래서 자바는 다른 참가자들의 어떤 반대없이 무난히 선택되었다. 자바의 중요한 특징은 VM (가상머신) 아키텍쳐라는것인데 이것은 여러 다른 디바이스들의 스펙에 대한 지원을 쉽게 해주었다. 오늘날  VM 은  다양한언어 (PHP, Scala, Groovy, Ruby, Python, etc.) 를 선택할수있게 해주며 심지어 다양한 하드웨어에서 실행된다. 

객체 얽김 (Entanglement)

저 시기에 객체들은 사용할 만 은 했었지만 그것들의 재사용성은 객체 얽김 문제 때문에 한계가 있었다. 많은 소프트웨어 개발자들은 절망적인 느낌을 받았는데 어떤 경우냐 하면 class A 를 사용할때 , 그것이 라이브러리 B 를 끌어오고, 그것은 라이브러리C 를 필요로하고..괴롭게도 계속된다. 최근 OOP 에서 우리는 커플링에 대한 주의력 없이 캡슐화에 대해 열광하였다. 흥미롭게도 OO 의  전임자는 구조적 프로그래밍이었는데 , 그것의 경구는 "낮은 커플링" "높은 응집력" 이었다. 내가 예상하길 우리는 상속성, 폴리모피즘, 기타 객체지향 신상품들 때문에 매우 바빠질것이라고 봤다.그러나 1998 년에 홈오토매이션 어플리케이션을 위한 자바프레임워크는 클래스들 특성 보다는 커다란 응집도/조밀도 (granularity) 의 크기를 가진 무언가를 요구했었다. 

우리에게 필요한것은 컴포넌트 프레임워크였다. 강건하고 신뢰성있으며 동적으로 컴포넌트들을 관리할수있는 그런 프레임워크 말이다. 우리는 새로운 컴포넌트를 완전히 동적으로 리부팅없이 인스톨 / 시작,멈추기 /  언인스톨 할수있기를 원했다. 만약 컴포넌트 A 가 컴포넌트 B 를 사용한다면 이런 의존성은 관리되야하며 , 컴포넌트가 시작되었을때 예외와 함께 발견되면 안된다. 컴포넌트간에는 서로를 발견할 필요가 있다. 또한 우리는 리부트를 허용하지 않기때문에 그 컴포넌트들은 의존성이 사라질때 탐지를 해야한다. 이런 동적 작동을 하기위해서 우리는 서비스 모델이란 것을 개발했었다. 하나의 컴포넌트가 서비스 객체를 등록할 수 있게하는 것은 또 다른 컴포넌트가 그 서비스를 발견하고 바인딩 할 수 있다는것을 말한다. 만약 서비스가 사라지면 언바인딩도 되면서 말이다. 각각의 서비스는 반드시 그것의 행위를 기술하는 계약서(contract)를 가져야하며 이 아키텍처는 SOA  (service-oriented architecture) 라 불릴수있을것이다. - 이 용어가 인기를 얻기 전 이야기지만 -  오늘날의 대부분 유명한 SOA 와는 대조적으로 OSGi 모델은 웹서비스나 커뮤니케이션 층의 어떤 다른것을 요구하지 않는다. 

OSGi 서비스는 단지  POJO 이다.     

OSGi 스펙들 

썬은 환경을 제공할뿐만아니라, 우리에게 JES (Java Embeded Server) 라고 불리는 구현품을 제공한다. JES 는 자바 가상머신 실행시에 번들 (ZIP/JAR files)의 인스톨/언인스톨을 허용한다. 저것은 VM 은 여러 다른 어플리케이션들 사이에서 공유된다는 것을 말하며  번들은 좀 그저그렇지만 우리는 찾고있던 컴포넌라고 볼수있다. 그리고 개발자로서 품위를 지키기위해 그것을 발전시켜야 한다는 것을 느꼈고 그렇게 했다. - 광범위하게.  우리는 8년을 해왔으며 시계는 여전히 돌아간다. OSGi 스펙은 , 지금 현재 릴리즈 4,  꽤 성숙해있다. 2000년에 인터넷 광풍을 따라서 홈 오토매이션 마켓이 붕괴되었을때에도 (단지 릴리즈1이 나왔을때) ,OSGi 스펙은 전화,자동차,산업자동화등에 채택되었으며, 최근에는 OSGi 기술이 확대시키거나또는 무거운 J2EE 컨테이너 그리고 다른 어플리케이션 서버를 대체할수있는 엔터프라이즈 컴퓨팅 세계에서 꽤 유명하게 되었다. 

시스템 예시 : Idefix 

산업자동화는 내가 OSGi 테크놀러지에서 좋아하는 분야이다. 나는 자바와 임베디드 프로그래밍을 좋아한다. 운수없게도, 소비자 전자회사들은 BOM(원료구입서,재료사양서) 상에서 극단적인 시각을 가지고있으며, C,C++ 같은 언어들에서 더 높게 나오는 소프트웨어 개발 비용을 무시하는 경향이 있다. 이것은 종종 JAVA 꺼져를 의미하며 VM 라이센스는 비용을 지불해야하며 추가적인 CPU , 메모리 요구사항이 있다는것으로 말을 일삼는다.

소량 제작은 소프트웨어 비용을 더 심각하게 만들기 때문에 산업 자동화 마켓에서는 좀 문제이다. 예를 들어서 한 회사가 50십만 유로로 팔리는  Idéfix  라는 산업용 측정 디바이스를 생산한다고 말해보자.  (그것은 가상의 디바이스이지만 정보는 실제 제품/상황 으로부터 수집됬다. 비공개를 원했을뿐..)

Idéfix 는 많은 하드웨어 익스텐션을 가지고있는데, 그것들은 수송라인의 샘플을 위한것이다. 샘플들의 정확한 위치, 특별한 액체 투입, 정밀한 값이 필요한 복잡한 측정등이 필요하다. 명백히 그런 장치는 많은 수량이 팔리지않는다.  고객은 그들의 환경에 딱 맞추기 위해서 확장 커스터마이징을 요구한다.  소프트웨어 아키텍처는 유연성 및 그런 유지비용, 적응성 비용을 낮추기위해 포커싱을 맞추게 된다. 적응성(adaptations ) 이 이런 종류의 시장에 매우 중요한며 또 다른 중요한 요소는 원격관리 이다.

세계 무역시장은 점점 커지고있으며 Idéfix  같은 디바이스는 세계 어디에서나 필요하다. 이런 작은 규모의 판매량은 기술자가 고객 근처에서 원할한 서비스를 해주는것을 어렵게한다. 만약 어떤 문제가 생겼을때 이런 문제는 신뢰성에 큰 타격을 입히는데. 원격 진단 및 소프트웨어 업데이트는 그래서 매우 중요해진다.

Idéfix  는 과거 수년동안 OSGi 스펙을 가진 자바 기반의 방법론에 대한 아이디어를 가진 컨설턴트들과 협동 작업을 해왔다. OSGi 스펙들은 Idéfix 같은 장치들에 대한 요구사항과 굉장히 매치가 잘되는데. 동적 컴포넌트 모델을 제공함으로써 표준 고객 적응성,  하드웨어 아키텍처 확장, 원격관리, 복잡한 측정알고리즘같은 복잡한문제들을 단순화해준다. 플러그향 형태의 시스템이 필요할때 누구한테나 필요하지 않겠는가? 자바가 실시간형태의 디바이스에 사용될수있지만 Idéfix  아케텍처는 하드 리얼타임 코드를 메인 어플리케이션 코드로 부터 분리시켰다. 이 하드 리얼타임 형태는 보조 프로세서에의해 제공되게 하며 , 하드웨어 확장에 그 스스로 임베디드되던가 혹은 플러그인 카드와 함께 제공되게 했다. 하드 리얼타임 부분을 분리시키는것은 복잡하고 치명적인 문제들을 단순화시킬수있었다.

디바이스 드라이버 로딩 

Idéfix 의 디자이너는 1-wire 디바이스를 익스텐션을 구분하기위해 사용했다. 이 간단한 프로토콜은 파워라인같은 동일한 와이어상에서 작동할수있으며, 매우 쌌고 , 간단한 1-wire 디바이스의 네트워크는 지선(ground wire) 과 파워/프로토콜 와이어와 연결되었다. 각각의 1-wire 디바이스는 유니크한 64비트 주소를 가지고있으며 그 주소는 1-wire 프로토콜을 통해 발견되어질수있었다. 일단 익스텐션이 적절히 연결되면 , 1-wire 디바이스 안의 유니크 코드는 안착된 익스텐션의 타입을 감별하기위해 사용 될 수 있었다. 이런것들은 사실 OSGi  디바이스 엑세스 스펙 디자인에 대한 예인데, 이 스펙은 OSGi 동적 서비스 모델을 명쾌히 설명해준다. 

자 더 자세히 살펴보자.

1-wire 버스는 컨트롤러를 요구한다. 그 컨트롤러는 1-wire 디바이스가 네트워크상에 있는지 감지하는데 OSGi 시스템에서 이런 컨트롤러는 프로그램되었으며 그 자체로 번들인 베이스(base) 드라이버라는 것을 통해 관리된다. 베이스 라이버가 새로운 1-wire 디바이스를 감지하면 그것을 OSGi 서비스 레지스터리와 함께 1-wire 디바이스를 나타내는 서비스로 등록한다.OSGi 서비스는 단지 POJO 이며, 서비스 정보에 대한 속성셋을 가지고 있다. 이 경우 하나의 속성은 1-wire (USB,Firewire,RFID,Ethernet, Zigbee, Z-Wave 같은것도 마찬가지) 인 디바이스 카테고리를 나타내는데 또 다른 속성으로는 unique ID 가 있다. 이 경우 1-wire unique code 는 모든 1-wire 칩안에 임베디드되있다. 디바이스 엑세스 서브시스템은 특별한 디바이스 속성을 가지고있는 서비스가 등록되는것을 감지하며 OSGi 프레임워크로 부터 서비스가 등록되면 바로 고지를 받을것이다.

하나 또는 그 이상의 드라이버 위치 서비스들을 통해 번들들의 데이타베이스를 참고하기 위해 속성들을 사용한다. 그 드라이버 위치 서비스는 매칭된 드라이버 로케이션(URLs) 를 리턴하며, 디바이스 엑세스 서브 시스템은 프레임워크 안의 이런 번들들을 로딩할것이다. 물론 그들이 이미 존재한다면 말이다. 이런 드라이버 번들 각각은 드라이버 서비스를 시작할때 등록된다. 이런 드라이버 서비스는 드라이버의 적합성을 따지기위해 사용된다. 가장 적합한것은 드라이버 셀렉터 서비스에 의해 선택되며 그 드라이

버는 그 후에 디바이스 서비스에 붙여서 사용된다.  그 드라이버는 그리고나서 연결된 디바이스의 실질적인 기능을 반영한 새로운 서비스를 등록하는것을 통해 디바이스 서비스를 재구성(refine) 할것이다.

원형은 번들이고 삼각형은 서비스들 인 아래 그림은 각각의 진행사항을 나타낸다. 숫자는 액션의 순서이다.



 역주: 

  0. 어떤 장치(device)가 장착되면 베이스 드라이버가 관리하는 컨트롤러가 그것을 감지한다. 
  1. 그것을  장치 서비스로  등록하면 
  2. 장치 엑세스 번들에서 감지해서
  3. 드라이버 로케이터 서비스를 이용해서 드라이버 db 에서  드라이버 위치를 얻고 
  4. 그 위치를 토대로 드라이버(들)를 인스톨하고 
  5. 드라이버(들)를 찾아서 
  6. 드라이버 셀렉터 서비스를 이용해 통해서 가장 적절한것으로 매칭하고
  7. 드라이버를 장치 서비스에  붙혀서  녀석으로 재구성한다.  


예에서 , 다음 1-wire ID 를 갖는 디바이스는 : 

  67.4B.A7.CD.90.AA.1A.01 

5 센티미터 직경을 가진 샘플 트레이로 정재될수있다. 만약 1-wire 베이스 드라이버가 장착되지 않은 디바이스를 검침하면 적합한 디바이스 서비스는 즉시 등록해제 될것이다. 디바이스 엑세스 번들은 등록해제되었다고 고지받을것이며 , 셈플 트레이 서비스가 등록해제되게 할것이다. 이 예제는 어떻게 이런 번들을 실제 디커플(decoupled) 시키는지 보여주며, 1-wire 리시버 베이스 드라이버는 표준화된 디바이스 엑세스 번들을 인지하지 않거나 어떤 셈플 트레이 서비스에 대한 지식도 가지고있지 않는다.

디바이스 엑세스 번들은 단지 디바이스 속성(properties )에 대해서만 알고있으며 1-wire 컨트롤러의  베이스드라이버에 대한 어떠한 단서도 없으며 . 샘플 트레이에 대한 어떠한 특징도 알수없다.  이런 세가지 컴포넌트가 알고있는 모든것은  단지 서비스들 이다. 샘플 트레이를 위해 다르게 만들지 않았다. 만약 1-wire 컨트롤러 베이스 드라이버 번들이 소프트웨어 업데이터나 샘플 트레이가 제거되었다고 해도 멈추지 않는다.

양쪽 이벤트는 동등하게 다루어지며 이러한 서비스레지스트리를 통한 디커플링 패턴은 OSGi 디자인패턴의 핵심이다.디바이스 드라이버번들을 인스톨링하는것은 꽤나 직설화법처럼 들리는데, 실제적으로 OSGi의 많은 부분에서 모듈레이어에 의해 구성된다.  그것은 VM 안에서 번들을 관리하는 책임이 있다. 중요한 문제는 이러한 번들들이 클래스들과 리소스를 공유한다는것이다. 즉 하나의 번들은 다른 번들로부터 클래스들을 임포트 할수있다는것이다. 컴퓨팅 세상에서 공유는 어렵다..

자바 모듈화 

번들 사이에서 클래스들을 공유하는것은 번들의 ZIP 파일의 일부인 메니페스트에 포함된 OSGi 메타데이터를 통해서 핸들링된다.메니페스트는 헤더네임과 연관된 값들의 리스트이다. 어떻게 공유작업이 이루어지는지 이해하기위해서, 먼저 자바패키지를 이해해야하는데 자바 패키지는 그저 클래스들과 리소스들을 가진 디렉토리이다. 클래스들은 다른 패키지들 끼리 동일한 이름을 각각 가질수있다. OSGi 시스템에서 패키지는 다른 번들로 익스포트되거나 다른 번들로부터 임포트되는거나 완전히 감추어지는데 각 익스포트된 패키지는 버전을 가지며 , 임포트는 일정한 버전들을 가지고 올수있다. 다른 번들로 부터 패키지들을 감출수있는것은 장점이 있는데 ,그  패키지들안의 클래스들이 나중에 새 버전으로 릴리즈할때 그것을 사용하는  클라이언트에게 영향을 미치지 않고 수정될수있다는것이다.  이것은 no import, no export , no hiding of classes 인 곳의  Plain Java 와는 근본적으로  다른점이다. OSGi 시스템에서 각각의 번들은 자신의 클래스 공간을 가지는데, 그 공간은 클래스들의 일관적인(consistent) 셋으로 구성된다.  일관성(Consistency) 의 의미는 같은 이름을 가진 클래스들은 항등적이며 (identical) 일관적이지 않은 클래스들에 닿을수없다는것이다. (classes with the same name are identical and cannot reach classes that are not consistent. ) 

다른 번들들은 다른 클래스 공간에 속할수있다. 그러나 동시적으로 같은 VM 안의 존재하기위해  같은 어플리케이션이나 라이브러리의  다른 버전을 따른다 (허용한다) . OSGi 프레임워크는 자동적으로 다른 클래스 공간들안의 번들들을 분리한다. 그래서 그들은 충돌하지 않게된다. 클래스 공간을 관리하는 동안에 익스포트들을 위해 임포트들을 풀어내는것(Resolving) 은 매우 어려운 문제인데 각 가능한 케이스에서 해결책을 보장할수가 없다. 이 리졸빙 알고리즘은 OSGi 스펙에서  구현자들이  혁신적인 해결책을 찾기위해 자유롭게 연구중인 아주 자그마한 영역중에  하나이다.    운좋게도 번들 개발자들은 완전히 이런 어려운 문제로부터 보호받고있다. 이런 모든 복잡성은 쉽게 사용가능한 API 로부터 감춰져있으며 , 우리의 예제에서는 드라이버 번들은 오직  OSGi 프레임워크이 적합한 번들을 찾을수있게하는  URL 을 제공할뿐이다. 그 번들은 파일 시스템, 웹 서버, 데이타베이스 및 Java URL 을 가진 어떤 위치에나 거주지를 마련할수있게된다. 번들은 ZIP 파일들이고 , 그러므로 자바코드 이상의 것을  포함할수있다. 내포적 (introspective 역주: 스스로를 설명할수있는 )이고 중요한 시간에 이벤트를 발생시키는  잘 정의된 라이프싸이클와 함께 그것을 사용하라너는 단지 디바이스를 위한 자바 코드가 아니라 컨텐트를 가져다주기위한 시스템을 가지고있다.  Idéfix 에서 보조프로세서위에서 돌아가기위해 필요한 코드를 예로들어서 갖는다. 이런 코드를 인스톨링하는 일은 어쩌면 디바이스 드라이버의 몫이 될수있는데 그러나 모든 다른 디바이스에게 매우 유사한 코드가 될수있다. 또한 신뢰성의 이유로서 , 또 다른 번들이 모든 보조프로세서들을 위해 이 코드를 관리한다면 더 나을것이다.

그러므로 Idéfix  장치는 인스톨이 필요할때  특별한 디렉토리에서 찾을수있는 번들을 가진다.(고지는 라이프 사이클 이벤트 동안 보내어진다)  만약 이 디렉토리가 보조프로세서를 위해  코드 이미지를 포함한다면, 이 번들은 자동적으로 그것을 인스톨할것이다. 만약 번들이 업데이트되었다면, 그 보조프로세서상의 이미지는 따라서 업데이트 될것이다.  만약 번들이 언인스톨되면, 그 코드는 보조프로세서(auxiliary processor) 로부터 제거될것이다. 또 다른것에 번들의 (관리되는) 라이프 사이클을 매칭하는것은 매우 유명한데 extenders 이라는 이름을 가지고있다. Extenders  는  help resources, install database tables, provide Web services 이런것들을 등록하기위해 사용된다. 

디폴트 JAR 매니페스트파일 (역자추가: 오라클참조)

JAR file 을 만들때, 자동적으로 디폴트 매니패스트 파일을 만들어지는데 . 오직 하나가 존재할수있다.

META-INF/MANIFEST.MF

디폴트 매니패스트 파일은 간단하며 다음과 같다.

Manifest-Version: 1.0

Created-By: 1.7.0_06 (Oracle Corporation)

매니페스트는  "header: value" 와 같이 헤더의 이름과 값은  콜론으로 분리되며 추가적으로 다양한 정보가 들어갈수있다.

리플렉션과 인트로스펙션 (역자추가: 위키참조)

컴퓨터 과학에서, 반영(Reflection)은 컴퓨터 프로그램에서 런타임 시점에 사용되는 자신의 구조와 행위를 관리(type introspection)하고 수정할 수 있는 프로세스를 의미한다. “type introspection”은 객체 지향 프로그램언어에서 런타임에 객체의 형(type)을 결정할 수 있는 능력을 의미한다.

많은 컴퓨터 아키텍처에서, 프로그램 명령은 데이터와 같이 메모리에 적재되므로, 명령과 데이터 사이의 구분은 단지 컴퓨터와 프로그램 언어에 의하여 어떻게 정보가 처리되느냐의 문제이다. 일반적으로, 명령은 실행되고, 데이터는 (명령의 자료로서) 처리된다. 그렇지만, 어떤 언어에서는, 프로그램은 명령 역시 데이터와 같은 방식으로 처리 할 수 있기 때문에, Reflective 수정이 가능하게 된다. 가장 일반적으로 반영은 스몰토크, 스크립트 언어와 같이 높은 수준의 가상 머신프로그램 언어에서 주로 많이 사용되고, 자바, C 언어와 같이 선언적이거나 정적 형식의 프로그램 언어에서는 드물게 사용된다.

서비스 지향 비지니스 모델 

산업에서 복잡한 제품(products) 을 만들기위한 분명한 트랜드는 제품(products)을 파는것으로 부터 멀어지고 대신해서 서비스를 판매하는데 촛점을 맞추라는것이다. 예를들어서 GE 는 비행기를 위한 엔진 (products) 을 파는것을 멈추고 대신 오늘날에는 그들에게 서비스로서 추력 (thrust) 를 판매한다.  또다른 예는 하이델베르그(Heidelberg) 로서 프린팅 프레스 제조업인 이 회사는 지금 복사 프린트로 돈을 벌고있다. 이런 비지니스 서비스 모델은 그렇게 다양하지 않은 스킬들을 요구하기때문에  고객을 더 기밀(agile)하게 만든다. 그리고 제조업의 손에는 더욱 큰  책임감과  여러 전문기술들을 던저 버린다.Idéfix  제조품은 서비스 베이스 비지니스 환경에서 사용되길 의도했었다. 분명히 , 원격 관리와 함께한 번들 모델은 좋은 매칭을 가진다.  그 장치들은 결국 세상 어디에나 있을것이기 때문이다. 성공을 위한 이런 비지니스 서비스 모델에 대한 강한 요구사항이 있지만 고객의  공장(토지)에 설치된 그 장치들은 보안(고정)되있고 쉽게 조작할수없다. (secure and tamper proof. )

만약 고객이 counters  를 리셋할수있거나 , 비 인가된  방식으로 장치를 사용할수있다면 , 그 제조회사는 돈을 읽게되겠지..결국 보안 모델은 매우 중요하다. OSGi 보안모델은 번들과 함께 시작한다. 번들은 X.509 증명서를  사용한 인증을 위해 공용키/개인키를 사용하여 서명될수있다. 우리가 작은 별도의 룰을 세팅해야할지라도 , 이것은 자바에 의해 제공되는 기본적인 모델이다. 자바 보안 모델의 중요한 문제는 모델이 높은 복잡도(fine granularity)를 가지고있기때문에 만들어지는 설정관리 문제이다. 

( 역주: Granularity에는 Coarse-Grained와 Fine-Grained라는 개념이 있다. 이는 서로 반대되는 개념으로써 전자는 보다 더 뭉쳐져있는 정도를 말하고 후자는 보다 잘게 잘게 쪼개져있음을 의미한다.자바 시큐리티를 관리하기 시도하는것은 매우 어렵다.  

많은 시스템들이 끝내 2가지 정적 레벨을 가지게되었는데 "보안하지 않거나, 모두 허용  ㅡ.ㅡ;; "OSGi 는  보안 매니지먼트를 번들기반의 깔쌈한 모델을 제공하여 간소화한다. 각 번들은 승인(permission) 셋을 가지고있고 그것은 컨디셔널 승인 관리자 서비스가 사뿐사뿐 돌아다니며 바꿀수있다. 게다가 각 번들은 허가설정(permission) 파일을 포함하며 번들이 환경으로부터 얻은 승인설정을 더욱더 제한할수있다. 그 아이디어는 서명자는 그들이 사인하기전에 번들의 보안스코프를 확인할수있게하는것이다. 이 모델은 보안 퍼미션들의 관리가 복잡한 문제일지라도 그것을  다루는것을 꽤 단순화해준다. 

OSGi and Open Source

Another advantage that made Idéfix easy to sell to the software developers is Eclipse, a free open source development environment. The developers at Eclipse had originally created their own plug-in model, but in 2003 they were looking for a more dynamic model. After evaluating several modularity systems, OSGi technology came out on top (OK, it might have helped that I was part of the team). The Eclipse team then did an amazing job of open-heart surgery by removing the old plug-in engine, replacing it with a brand new framework compatible with OSGi, and creating a compatibility layer that made all existing plug-ins compatible with the new system. To top it off, Eclipse provided an excellent environment in which to develop bundles. Though it is not a key requirement, there is definitely synergy if bundles for a device can be developed and tested in the same environment as your desktop. This is a key advantage of OSGi and why we sometimes call it universal middleware. Properly designed bundles run almost anywhere.

Idéfix’s architecture allowed for a lot of use of open source projects. For the OSGi framework, Idéfix chose Apache Felix, one of the key open source OSGi implementations. It also used bundles from Knopflerfish (an open source project with commercial backing) and Equinox (the Eclipse OSGi implementation). These projects implement most of the service specifications of OSGi release 4. Idéfix could also have chosen from one of the commercial implementations available from companies such as Makewave, ProSyst, IBM, and others.

Unfortunately, not all Java-based open source projects provide the right metadata for OSGi frameworks, even though the necessary headers are quite easy to add when a project is built with make, ant, maven, or the bnd tool. These headers do not cause any overhead or problems when the JARs (Java archive files) are used without OSGi. We hope that the increasing adoption rate of OSGi in our industry will help improve this situation dramatically in the next year. In the meantime, there are two projects, one in Eclipse and one in Apache Felix, that provide bundle-ized JARs for many open source software projects.


Application Programming Models

One of the great software insights of the past decade is the concept of a POJO. POJO-style programming means that we write Java code that is coupled to the Java environment but not to a specific container. We have learned the hard way that coupling our application logic to a framework is a bad idea because it locks us in. We always need some code that bridges our container with the POJO, however. This code injects any dependencies into the POJO so it can remain oblivious to where those dependencies come from. Though the OSGi framework is lightweight, it is also some kind of container and the same rules therefore apply.

Several application frameworks based on dependency injection have been developed to allow POJO programming in an OSGi environment. These frameworks hide the complexity of the dynamic dependencies, add extra layers such as transactions and remoting transparently, and simplify programming of the application logic.

The OSGi Alliance specified the declarative services application model for the release 4 service platform. The declarative services model is a small but effective dependency injection model based on the OSGi service model. Apache Felix took an interesting approach with iPOJO. This model reduces many programming chores by analyzing the bytecodes and inferring the intentions for many common tasks.

The best-known application programming model for OSGi is Spring. SpringSource, the Spring guardian, extended the Spring bean configuration model to connect to the dynamic OSGi services. This turned out to work extremely well because Spring and OSGi had little overlap and were extremely complementary. Spring-OSGi is highly popular in the enterprise software market at the moment. In the near future, the SCA (Service Component Architecture), an effort from OASIS with all the major players in the enterprise software market, will map SCA to OSGi, a promising combination.

Five different programming models, and counting, is quite a lot for a technology such as OSGi, because the collaboration among these models could be severely impaired. All these application models, however, use the OSGi service registry at the base. Through the registry, a Spring-OSGi application works seamlessly with an iPOJO application or a declarative services application. Developers can therefore choose which model provides the best solution for them but still reuse components written in other application models.

Reflecting

The future of the OSGi technology looks pretty rosy. It is a mature standard, proven in many markets, has many implementations, and has shown to scale well. It provides the foundation for a true universal middleware standard that could have a huge impact in our industry, if we can explain the technology to a wider audience.

We have done the groundwork, but we are far from finished. We need more companies that are willing to take the standard in different directions so we can get closer to fulfilling the promises of the Lego hypothesis: a model where components are wired together to create advanced applications. On that day, I can finally say that my original pitch to my manager has come true.

PETER KRIENS is the OSGi director of technology and CEO of aQute. He has worked as consultant for a large number of international companies introducing object-oriented techniques. In 1994 he moved to Sweden to work for Ericsson. In 2001, he was hired part-time by OSGi to act as its technical director. His responsibilities include editing the specifications and serving as the OSGi evangelist.



JNDI 는 자바 네이밍 / 디렉토리 인터페이스인데 J2EE 의 가장 중요한 스펙중하나이다.

많은 전문가들은 JNDI 의 역할과 중요성을 이해하지 못하고서는 진정한 J2EE EJB 를 알고있다고 말할수없다고 한다.

과연 JNDI 의 역할은 멀까?

JNDI 의 역할을 이해하기위해  "JNDI 가 없다면 어떻게 해야하는지"  를 먼저 보고  JNDI 를 사용하는것에 대해 살펴보자. 

마지막으로 JNDI 의 실행모습과 환경설정등에 대해 알아보자.


* 구체적인 사용방법은 다른 블로그를  참고하도록하자. 




1. JNDI 왜  사용하나? 


JNDI 의 역할을 이해하기위해  "JNDI 가 없다면 어떻게 해야하는지"  를 먼저 보고  JNDI 를 사용하는것에 대해 살펴보자. 


JNDI 없이 


MySQL 데이타베이스에 접근하기위한 어플리케이션을 개발할때,  MySQL JDBC 드라이버 클래스를  참조하기위해 

해당되는 JDBC URL 를 사용하는데 대략 다음과 같다.


Java code 


Connection conn = null; 
try { 
    Class.forName ("com.mysql.jdbc.Driver" , true, Thread.currentThread (). getContextClassLoader ()); 
    conn = DriverManager.getConnection ("jdbc: mysql :/ / MyDBServer? user = qingfeng & password = mingyue"); 

    ...... 
    conn.close (); 
} 
.....


이것은 전통적인 접근방법이며 , 다른 언어개발자들에게도 일반적인 방법이다. 이 접근법은 일반적으로 작은규모의 개발

 프로세스에 적합하며  자바언어에 익숙하기만하면 어플리케이션을 금방 만들수있는 장점이 있다. 


 

JNDI 식 접근 


1. 데이타베이스 서버이름 MYDBSERVER/사용자이름,비밀번호/ 바꿀필요가 있을때라든지 JDBC URL 을 수정할필요가 있을때

2. 데이타베이스가 다른것(DB2, Oracle등) 으로 바뀔수있을때

3. JDBC 설정이 바뀔필요가 있을때 (커넥션 풀 파라미터등등) 


해결책 : 

프로그래머는 데이타베이스 백그라운드에서의 특별한 세팅에 대해 신경쓰게 하고 싶지 않다. 데이타베이스 관리자가 

진두지휘하고 프로그래머는 그냥 가져다 쓰게하고싶다.


그럴때 JNDI 가 있다.


우선 J2EE 컨테이너에 JNDI 파라미터를 설정하고, 데이타소스등을 정의한다. JBoss 에서의 예를 보자


<? Xml version = "1.0" encoding = "UTF-8"?> 
<datasources> 
<local-tx-datasource> 
<jndi-name> MySqlDS </ jndi-name> 
<connection-url> jdbc: mysql :/ / localhost: 3306/lw </ connection-url> 
<driver-class> com.mysql.jdbc.Driver </ driver-class> 
<user-name> root </ user-name> 
<password> rootpassword </ password> 
<exception-sorter-class-name> org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter </ exception-sorter-class-name> 
<metadata> 
<type-mapping> mySQL </ type-mapping> 
</ Metadata> 
</ Local-tx-datasource> 
</ Datasources>


2 . 소스에서 사용하기 


Java code 
Connection conn = null; 
try { 
    Context ctx = new InitialContext (); 
    Object datasourceRef = ctx.lookup ("java: MySqlDS"); / / reference data source 
    DataSource ds = (Datasource) datasourceRef; 
    conn = ds.getConnection (); 

...... 
c.close (); 
} 
.....




시스템에 대해 배포후에 , 만약 데이타베이스 관련된 파라미터가 바뀔때 오직 mysql-ds.xml 설정만 바꿔주면 된다.

소스코드를 바꿀필요없이  아마 그것만 하는 관리(개발)자를 두면 그사람이 알아서 회사(제품)방침에 따라서 조작 할것이다.

JNDI 는 프로그램과 데이타베이스간에 타이트하게 묶여있는 커플링을 피하게 해주며, 쉽게 설정,배포하게해준다.


3. 관련 이미지 




위의 예는 DB 에 접근하기위한 방법에 대한 예이지만, 모든 리소스들에 대해서도 투명화하기위하면 사용할만하겠다. 

예를 들어서  밴더별 컴포넌트, 디바이스 드라이버, 환경설정등등..

근데 요즘 OSGi 도 살펴보는중인데 OSGi 는 JNDI 의 특성(위치투명성)과 기존 컴포넌트베이스개발방법론이 합쳐진거

같은 느낌을 받았다.



2. JNDI 모습들과 환경설정에 관하여




환경 설정에 관한 이야기들 


웹로직/톰캣 서버가 부팅시에 JNDI 객체를 등록합니다.

JNDI 서버의 실제 구현 기능은 각 Application Server의 Vendor (톰캣, 웹로직같은) 가 제공함

JNDI 서버 단독실행 가능함 : http://meri-stuff.blogspot.kr/2012/01/running-jndi-and-jpa-without-j2ee.html

간단한 JNDI 서버 : https://code.google.com/p/osjava/wiki/SimpleJNDI

어떻게 원격 JNDI 서버에 접속하나? : http://stackoverflow.com/questions/15272467/how-to-lookup-remote-jndi







레퍼런스:

http://www.databaseskill.com/216815/





https://thrift.apache.org/


아파치 쓰리프트 프레임워크는 다양한 언어로 서비스되며 , 효율적인 코드생성엔진을 갖고 소프트웨어 스택을 묶으며 다음과 같은 다양한 언어들을 지원한다  C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and 기타등등.


시작하기 

  • Apache Thrift 다운로드 

    To get started, download a copy of Thrift.

  • Apache Thrift compiler 빌드/인스톨

    You will then need to build the Apache Thrift compiler and install it. See the installing Thrift guide for any help with this step.

  •  .thrift 파일 작성 

    After the Thrift compiler is installed you will need to create a thrift file. This file is an interface definitionmade up of thrift types and Services. The services you define in this file are implemented by the server and are called by any clients. The Thrift compiler is used to generate your Thrift File into source code which is used by the different client libraries and the server you write. To generate the source from a thrift file run

                thrift --gen <language> <Thrift filename>
              

    The sample tutorial.thrift file used for all the client and server tutorials can be found here.


To learn more about Apache Thrift Read the Whitepaper



예제 


아파치 쓰리프트는 데이타타입 및 서비스 인터페이스를  간단한 정의파일안에 제공한다.파일을 통해 입력하면 

컴파일러는 교차언어간에 자연스럽게 통신할수있는  RPC 클라이언트/서버로  쉽게 사용되는 코드를 생성해준다. 

당신이 만든 객체를 이동하거나 직렬화 하기위해 행사코드를 쓰는 수고를 덜어주며, 원격메소드를 호출하여 당신이 

비지니스로직에만 집중할수있게한다.

다음 예제는 웹프런트엔드에 대해  유저객체를 저장하기위한 간단한 서비스를 보여준다.


쓰리프트 정의 파일 

service Calculator extends shared.SharedService { /** * 메소드 정의는 C 코드같다. 리턴타입 과 매개변수 , 예외를 가지고있다. * Note that argument * lists and exception lists are specified using the exact same syntax as * field lists in struct or exception definitions. */ void ping(), i32 add(1:i32 num1, 2:i32 num2), i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), /** * 단방향 콜로써 요청한후에 리턴받는걸 무시한다. */ oneway void zip()


파이썬 클라이언트 

 # Make socket
  transport = TSocket.TSocket('localhost', 9090)

  # Buffering is critical. Raw sockets are very slow
  transport = TTransport.TBufferedTransport(transport)

  # Wrap in a protocol
  protocol = TBinaryProtocol.TBinaryProtocol(transport)

  # Create a client to use the protocol encoder
  client = Calculator.Client(protocol)

  # Connect!
  transport.open()

  client.ping()
  print 'ping()'

  sum = client.add(1,1)
  print '1+1=%d' % (sum)



자바 서버 


Initialize the Server:

    try {
      TServerTransport serverTransport = new TServerSocket(9090);
      TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));

      // Use this for a multithreaded server
      // TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor));

      System.out.println("Starting the simple server...");
      server.serve();
    } catch (Exception e) {
      e.printStackTrace();
    }


The CalculatorHandler:

public class CalculatorHandler implements Calculator.Iface {

  private HashMap<Integer,SharedStruct> log;

  public CalculatorHandler() {
    log = new HashMap<Integer, SharedStruct>();
  }

  public void ping() {
    System.out.println("ping()");
  }

  public int add(int n1, int n2) {
    System.out.println("add(" + n1 + "," + n2 + ")");
    return n1 + n2;
  }

  public int calculate(int logid, Work work) throws InvalidOperation {
    System.out.println("calculate(" + logid + ", {" + work.op + "," + work.num1 + "," + work.num2 + "})");
    int val = 0;
    switch (work.op) {
    case ADD:
      val = work.num1 + work.num2;
      break;
    case SUBTRACT:
      val = work.num1 - work.num2;
      break;
    case MULTIPLY:
      val = work.num1 * work.num2;
      break;
    case DIVIDE:
      if (work.num2 == 0) {
        InvalidOperation io = new InvalidOperation();
        io.what = work.op.getValue();
        io.why = "Cannot divide by 0";
        throw io;
      }
      val = work.num1 / work.num2;
      break;
    default:
      InvalidOperation io = new InvalidOperation();
      io.what = work.op.getValue();
      io.why = "Unknown operation";
      throw io;
    }

    SharedStruct entry = new SharedStruct();
    entry.key = logid;
    entry.value = Integer.toString(val);
    log.put(logid, entry);

    return val;
  }

  public SharedStruct getStruct(int key) {
    System.out.println("getStruct(" + key + ")");
    return log.get(key);
  }

  public void zip() {
    System.out.println("zip()");
  }

}

<장점>

- 버전닝 지원
- 여러 언어에서 사용 가능하며 언어에 맞도록 소스가 생성되고, 언어간의 Serialization 가능
- Sync, Async Server API 제공
- XML 설정이 필요 없음
- Layer에 맞는 Interface를 사용 및 Customizing 구축 가능
- RPC 기능 제공 (Google Protocol Buffer에는 없는 기능)
- 서버 기능 좋음
   -- 서블릿 제공(org.apache.thrift.server.TServlet)
   -- 멀티쓰레드 지원 (org.apache.thrift.server.ThreadPoolServer : worker thread 지정)
   -- Async 지원 (org.apache.thrift.server. TNonblockingServer : single threaded)
   -- Multi-thread Half-Sync/Half-Async지원 : org.apache.thrift.server. THsHaServer
   -- Exception을 제공 (Google Protocol Buffer에는 없는 기능)
   -- Set, Map 지원 (Google Protocol Buffer에는 없는 기능)

 


 <단점>

- 자바로 코드가 생성될 때, Slf4j를 기본적으로 가지고 가며, 내부 코드는 모두 thrift lib가 필요함
- C++의 Server threading part는 Boost에 의존을 가짐
- 자바 쪽 이클립스 플러그인 없음
- Thrift lib의 api가 자주 바뀌어서, 버전 업마다 소스를 좀 보고 코딩해야 함. (인터넷 예제가 거의 없음)
   인터넷 예제랑 달라서, 컴파일 에러 안나게 하는게 귀찮음...
- XML Serialization/Deserialization 기능 없음
- 문서가 확실히 적음 (허허~)
- 생성된 코드가 Google Protocol Buffer에 비해서 보기는 편하지는 않음 (특히 C++)


http://knight76.tistory.com/1426  펌 



+ Recent posts