달력

92021  이전 다음

  •  
  •  
  •  
  • 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
  •  
  •  

[펌] Sorting Algorithm

JAVA/JSE 2005. 1. 15. 17:16

Sorting algorithm

From Wikipedia, the free encyclopedia.

In computer science and mathematics, a sorting algorithm is an algorithm that puts elements of a list in a certain order. The most used orders are numerical order and lexicographical order. Efficient sorting is important to optimizing the use of other algorithms (such as search and merge algorithms) that require sorted lists to work correctly; it is also often useful for canonicalizing data and for producing human-readable output.

Contents [hide]


 

Classification

Sorting algorithms used in computer science are often classified by:

  • computational complexity (worst, average and best behaviour) in terms of the size of the list (n). Typically, good behaviour is O(n log n) and bad behaviour is O(n2). Sort algorithms which only use an abstract key comparison operation always need at least O(n log n) comparisons on average; sort algorithms which exploit the structure of the key space cannot sort faster than O(n log k) where k is the size of the keyspace.
  • memory usage (and use of other computer resources)
  • stability: stable sorting algorithms maintain the relative order of records with equal keys. That is, a sorting algorithm is stable if whenever there are two records R and S with the same key and with R appearing before S in the original list, R will appear before S in the sorted list.

When equal elements are indistinguishable, such as with integers, stability is not an issue. However, say we were sorting these pairs of numbers by their first coordinate:

(4, 1) (3, 1) (3, 7) (5, 6) 

In this case, two different results are possible, one which maintains the relative order records with equal keys, and one which doesn't:

(3, 1) (3, 7) (4, 1) (5, 6) (order maintained) (3, 7) (3, 1) (4, 1) (5, 6) (order changed) 

Unstable sorting algorithms may change the relative order of records with equal keys, stable sorting algorithms never so. Unstable sorting algorithms can be specially implemented to be stable. One way of doing this is to artificially extend the key comparison, so that comparisons between two objects with otherwise equal keys are decided using the order of the entries in the original data order as a tie-breaker. Remembering this order, however, often involves an additional space penalty.

Table of sorting algorithms

In this table, n is the number of records to be sorted, k is the number of distinct keys, and u is the number of unique records.

Stable

Unstable

Questionable sort algorithms not intended for production use:

Summaries of the popular sorting algorithms

Bubble sort

Bubble sort is the most straightforward and simplistic method of sorting data that could actually be considered for real world use. The algorithm starts at the beginning of the data set. It compares the first two elements, and if the first is greater than the second, it swaps them, then repeats until no swaps have occurred on the last pass. The algorithm does this for each pair of adjacent elements until there are no more pairs to compare. This algorithm, however, is vastly inefficient, and is rarely used except in education (i.e., beginning programming classes). A slightly better variant is generally called shuttle sort, and works by inverting the ordering criteria, and the pass direction on alternating passes.

Insertion sort

Insertion sort is similar to bubble sort, but is more efficient as it reduces element comparisons somewhat with each pass. An element is compared to all the prior elements until a lesser element is found. In other words, if an element contains a value less than all the previous elements, it compares the element to all the previous elements before going on to the next comparison. Although this algorithm is more efficient than the Bubble sort, it is still inefficient compared to many other sort algorithms since it, and bubble sort, move elements only one position at a time. However, insertion sort is a good choice for small lists (about 30 elements or fewer), and for nearly-sorted lists. These observations can be combined to create a variant of insertion sort which works efficiently for larger lists. This variant is called shell sort (see below).

Shell sort

Shell sort was invented by Donald Shell in 1959. It improves upon bubble sort and insertion sort by moving out of order elements more than one position at a time. One implementation can be described as arranging the data sequence in a two-dimensional array (in reality, the array is an appropriately indexed one dimensional array) and then sorting the columns of the array using the Insertion sort method. Although this method is inefficient for large data sets, it is one of the fastest algorithms for sorting small numbers of elements (sets with less than 10 or so elements). Another advantage of this algorithm is that it requires relatively small amounts of memory.

See work-in-place article for the list of sorting algorithms that can be written as work-in-place.

Merge sort

Merge sort takes advantage of the ease of merging already sorted lists into a new sorted list. It starts by comparing every two elements (i.e. 1 with 2, then 3 with 4...) and swapping them if the first should come after the second. It then merges each of the resulting lists of two into lists of four, then merges those lists of four, and so on; until at last two lists are merged into the final sorted list.

Heapsort

Heapsort is a member of the family of selection sorts. This family of algorithms works by determining the largest (or smallest) element of the list, placing that at the end (or beginning) of the list, then continuing with the rest of the list. Straight selection sort runs in O(n2) time, but Heapsort accomplishes its task efficiently by using a data structure called a heap, which is a binary tree where each parent is larger than either of its children. Once the data list has been made into a heap, the root node is guaranteed to be the largest element. It is removed and placed at the end of the list, then the remaining list is "heapified" again.

Radix sort

Some radix sort algorithms are counterintuitive, but they can be surprisingly efficient. If we take the list to be sorted as a list of binary strings, we can sort them on the least significant bit, preserving their relative order. This "bitwise" sort must be stable, otherwise the algorithm will not work. Then we sort them on the next bit, and so on from right to left, and the list will end up sorted. This is most efficient on a binary computer (which nearly all computers are). If we had a ternary computer, we would regard the list as a list of base 3 strings and proceed in the same way. Most often, the bucket sort algorithm is used to accomplish the bitwise sorting.

Radix sort can also be accomplished from left to right, but this makes the algorithm recursive. On a binary (radix 2) computer, we would have to sort on the leftmost bit, and then sort the sublist with 0 as the leftmost bit, and then sort the sublist with 1 as the leftmost bit, and so on.

Graphical representations

Microsoft's "Quick" programming languages (such as QuickBASIC and QuickPascal) have a file named "sortdemo" (with extension BAS and PAS for QB and QP, respectively) in the examples folder that provides a graphical representation of several of the various sort procedures described here, as well as performance ratings of each.

Also, a program by Robb Cutler called The Sorter (http://faculty.harker.org/robbc/Pages/Software/TheSorter/TheSorter.htm) for classic Mac OS performs a similar function. It illustrates Quick Sort, Merge Sort, Heap Sort, Shell Sort, Insertion Sort, Bubble Sort, Shaker Sort, Bin Sort, and Selection Sort.

See also

External links and references

'JAVA > JSE' 카테고리의 다른 글

FileFilter... 까먹기 싫어~~~  (0) 2005.02.12
[nio] Channels 클래스  (0) 2005.01.17
[펌] Sorting Algorithm  (0) 2005.01.15
[link] 자바 검색 봇~  (0) 2005.01.11
[펌] [Collection Framework ] List, Set and Map  (0) 2004.12.29
소스포지.. 디컴파일해두 소스 안보여주는  (0) 2004.11.23
Posted by Tornado tornado

댓글을 달아 주세요

[link] 자바 검색 봇~

JAVA/JSE 2005. 1. 11. 15:44

http://www.nutch.org/docs/en/

 

lucene 도 봐야 허고.. 이거도 봐야하고..

간단한 게시판에 역인덱스 구조도 만들어 봐야 하고

할꺼 디지게 많은데.. 와우가 나를 부른다.. ㅡㅡ

'JAVA > JSE' 카테고리의 다른 글

[nio] Channels 클래스  (0) 2005.01.17
[펌] Sorting Algorithm  (0) 2005.01.15
[link] 자바 검색 봇~  (0) 2005.01.11
[펌] [Collection Framework ] List, Set and Map  (0) 2004.12.29
소스포지.. 디컴파일해두 소스 안보여주는  (0) 2004.11.23
[허가없는 링크^^] 패턴  (0) 2004.10.25
Posted by Tornado tornado

댓글을 달아 주세요

Collection(List, Set) 과 Map.. 기억하자 기억하자 다짐하면서 번번히 차이점을 잊어버리곤 한다.

 

이번엔 절대로!! 잊지 않겠다는 신념으로  "Head First 자바" 부록을 참고해서 확실하게 정리해 보았다. -_-+

 

 

1. Collection

Collection 은 여러개의 객체를 하나의 유닛으로 다루기 위한 최상위 인터페이스이다.

 

객체 집합을 하나의 객체로 다루는 방법에 따라서 두가지로 나뉘는데, List 는 객체들이 들어온 순서대로 참조를 유지하기 위한 목적을 가지고 있고 Set 은 중복된 참조를 허용하지 않는 목적을 가진다.

 

 

2. List

Collection 인터페이스를 상속한 List는 객체들이 들어온 순서대로 참조를 관리한다.

 

들어온 순서가 중요하기 때문에 객체들에게 index(색인)을 부여하고 이를 통해서 각각의 객체에 접근한다.

 

List 에서 중요한 것은 객체들의 순서를 관리하는 것이다. 즉, List 는 index 로 순서를 추적하는데에 관심이 있을 뿐, 같은 객체의 참조가 여러번 들어오거나 null 참조가 들어오는 것은 조사하지 않는다.

 

만일 List에 참조가 여러개 존재하지 않아야 하는 상황이라면 List 보다는 Set 계열의 클래스를 이용하는 것이 좋다.

 

 

a. Vector

 

자바 1.0 부터 수많은 개발자들로부터 사랑받아오던 원년 멤버이지만 Collection 프레임워크가 등장하고 나서 List 인터페이스를 구현하면서 Collection 프레임워크로 편입됐다. Vector는 멀티 쓰레드 환경에서도 사용될 수 있도록 객체의 삽입, 삭제 시에 동기화를 보장하도록 되어있다.

 

하지만 Multi Thread 환경이 아니라면 ArrayList 보다 성능이 떨어지므로 Single Thread 에서 접근한다면 ArrayList 를 대신 사용하는 것이 효율적이다.

 

b. ArrayList

 

Collection 을 상속한 클래스들 중에서 add 메소드의 실행이 가장 빠르고 배열의 크기를 자유자재로 늘릴 수 있다. 하지만 Vector 처럼 동기화 과정은 제공하지 않는다. Collection 계열 클래스들은 (Vector를 제외하고) 여러개의 쓰레드가 동시에 접근하는 상황에 대한 대비책은 없기 때문에 주의할 필요가 있다. (이에 관한 추가 사항은 6.Collections 에서 다룬다.)

 

c. LinkedList

 

List 인터페이스의 기본적인 구현 외에도 추가적으로 몇개의 메소드를 넣어서 사용의 편리성을 도모했다. 이 몇개의 메소드란 addFirst(), addLast(), removeFirst(), removeLast() 등이다. LinkedList는 자체로서 사용되기 위해서라기 보다는 스택, 큐 등 사용자가 ADT를 구축할 때 내부에서 사용되기 위한 측면이 강하다.

 

따라서 단순히 객체에 대한 참조를 넣고 빼기 위해서라면 LinkedList 를 쓰기보다는 Vector나 ArrayList 를 사용하는 것이 바람직하다.(쓰더라도 문제될 건 없다.)

 

 

3. Set

List 가 항목의 순서를 관리하는데 비해 Set 는 중복된 항목을 방지하는데 관심이 있다. 이를 위해서 Set 에 의해서 관리되는 객체는 equals() 메소드를 구현해야 한다.

 

자바에서 == 는 단순히 객체의 주소에 근거해서 비교 결과를 반환하기 때문에 equals() 메소드에서 객체의 "내용"을 비교하는 과정을 적어넣아야 Set 에서 equals() 메소드를 통해서 이미 존재하는 항목인지 아닌지를 확인할 수 있다.

 

a. HashSet

 

HashSet 은 가장 빠른 접근을 보장한다. HashSet은 내부적으로 HashMap 을 이용한다. HashSet에 추가되는 항목은 HashMap의 키값으로 저장이 되기 때문에 HashSet이 하는 일이란 HashMap과 사용자 사이의 중계 역할만을 할 뿐이다. 

 

HashSet에서는 항목의 순서를 확인할 수 없다.새로운 객체가 HashSet 에 들어오게 되면 내부에서 객체의 참조 위치가 바뀔 수도 있는데, 이는 HashSet 내부에서 이용하는 HashMap의 특성때문이다.

 

b. LinkedHashSet

 

Set 에 순서를 부여하기 위해서 java 1.4에서 LinkedHashSet 클래스가 등장했다. 이 클래스는 내부에서 double-link 를 이용해서 linked list 를 구현함으로써 원소가 추가된 순서를 유지한다.  LinkedHashSet도 HashSet과 마찬가지로 내부에서 LinkedHashMap 인스턴스를 사용하고 있다.

 

TreeSet 은 Set의 항목들을 정렬된 순서대로 보관한다. 항목을 정렬하기 위해서 TreeSet이 하는 일이란 SortedMap 인스턴스에 작업을 위임하는 것 뿐이다. TreeSet 에 추가되는 항목은 SortedMap 인스턴스의 키값으로 등록이 된다. (키값의 정렬은 Map 인터페이스의 역할이다.)

 

위에서 살펴본대로 Set 계열의 클래스들은 자신의 작업을 Map 계열의 클래스들에게 전적으로 위임하고 있다. Set 에서 중복된 원소를 허용하지 않는 정책은 Map에서 중복된 키값이 존재해서는 안되는 정책이므로, Set에서 삽입되는 원소는 모두 Map 인스턴스에서 키값으로 추가가 된다.

 

이러한 이유 때문에 Set 계열의 클래스들과 Map 계열의 클래스들의 이름이 비슷하게 된 것이 아닌가 싶다.

 

 

 

4. Map

 

 

구조적으로 볼 때 Map 인터페이스는 Collection 인터페이스와 피한방울 섞이지 않은 남남이다. Map 인터페이스는 키와 값을 대응시키기 위해서 사용된다. 여기서 키(key)라 함은 하나의 Map 에 담기는 객체들을 유일하게 식별할 수 있는 객체를 의미하는데, 이는 하나의 Map 내에서 같은 값을 가지는 key 는 존재할 수 없음을 뜻한다.

 

주어진 키에 대응 하는 값을 빠르게 찾기 위한 탐색의 측면에서 Map 계열 클래스들의 의미가 있다고 하겠다.

 

*Collection 은 객체들을 넣고 빼는데 있어서 어떻게 이 객체들을 관리할 것인가를 다루고 있고 Map 은 키를 통해서 실제 객체에 접근한다.*

 

 

5. Collections

 

Collections 클래스는 Collection 인터페이스를 구현한 하위 클래스들에게 다양한 오퍼레이션을 제공할 목적으로 모든 메소드가 static 메소드이다. 따라서 모든 Collection 계열의 인스턴스에 대해서 필요에 따라 다양한 작업을 할 수 있다.

 

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html

 

a. 동기화 지원

 

위에서 언급한 ArrayList 뿐만이 아니라, Collection 을 구현하는 클래스들은 모두 ArrayList 처럼 동기화에 대한 대비책이 없다. 따라서 Vector와 Hashtable 을 제외한 모든 Collection 객체들이 Multi Thread 환경에서 사용되기 위해서는 별도의 기능을 갖춰야 하는데, 이를 위한 메소드가 Collections 클래스에 존재한다.

 

static CollectionsynchronizedCollection(Collection c)
          Returns a synchronized (thread-safe) collection backed by the specified collection.
static ListsynchronizedList(List list)
          Returns a synchronized (thread-safe) list backed by the specified list.
static MapsynchronizedMap(Map m)
          Returns a synchronized (thread-safe) map backed by the specified map.
static SetsynchronizedSet(Set s)
          Returns a synchronized (thread-safe) set backed by the specified set.
static SortedMapsynchronizedSortedMap(SortedMap m)
          Returns a synchronized (thread-safe) sorted map backed by the specified sorted map.
static SortedSetsynchronizedSortedSet(SortedSet s)
          Returns a synchronized (thread-safe) sorted set backed by the specified sorted set.

 

다음과 모든 Collection 계열의 객체에 대해서 synchronized...(..) 메소드로 Multi Thread 환경에서 이용가능하도록 전환할 수 있다. 

 

List list = Collections.synchronizedList(new ArrayList(...));

List list = Collections.synchronizedList(new LinkedList(...));

 

SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));

Set s = Collections.synchronizedSet(new HashSet(...));

Set s = Collections.synchronizedSet(new LinkedHashSet(...));

 

 

Map m = Collections.synchronizedMap(new HashMap(...));

Map m = Collections.synchronizedMap(new TreeMap(...));
Map m = Collections.synchronizedMap(new LinkedHashMap(...));

 

'JAVA > JSE' 카테고리의 다른 글

[펌] Sorting Algorithm  (0) 2005.01.15
[link] 자바 검색 봇~  (0) 2005.01.11
[펌] [Collection Framework ] List, Set and Map  (0) 2004.12.29
소스포지.. 디컴파일해두 소스 안보여주는  (0) 2004.11.23
[허가없는 링크^^] 패턴  (0) 2004.10.25
[펌] JAVA application 성능향상..  (0) 2004.10.07
Posted by Tornado tornado

댓글을 달아 주세요

http://proguard.sourceforge.net/
Posted by Tornado tornado

댓글을 달아 주세요

http://zeropage.org/wiki/_c6_d0_c5_cf_ba_d0_b7_f9
Posted by Tornado tornado

댓글을 달아 주세요

URL 남겨놓고 시간날때 좀 자세히 봐둬야 것다...

 

http://kr.sun.com/developers/tech_docs/wireless_web06/wireless02.html

Posted by Tornado tornado

댓글을 달아 주세요

Applet Technology



  [2004년 4월 19일] 자바 기술을 이용하여 사인드 애플릿 만들기!!!!

              -. 아직도 사인드 애플릿을 만들때 마이크로소프트에서 제공하는 방법을 사용하시나요?
                 이제 더 이상 그렇게 불편하게 하지 않으셔도 됩니다.
                 더 이상 지원되지 않는 Microsoft SDK for Java 4.0을 설치하실 필요도 없습니다.
                 자, 이제 자바 기술을 사용하여 사인드 애플릿을 만들어 보세요.
                 정말이지 제가 게으른 탓에 이제서야 드디어 정리를 했습니다.
                 제가 보기엔 이 방법이 훨씬 더 나은것 같습니다.
                 질문이나 문의사항은 게시판을 이용해 주세요..^^;
            
  Internet Explorer에서 실행되는 Signed Applet을 dubuild를 사용하여 만들기~!!!!

              -. cabarc를 이용하여 Signed Applet을 만들었더니, 브라우저가 실행될때마다 인증을 요구하나요?
                 하하~!!!! 이제 버전이 업그레이드 되기 전에는 인증을 요구하지 않게 할 수 있습니다.
                 cabarc대신 dubuild를 사용해 보세요...
                 어떻게 하냐고요? 그냥 이 문서를 따라하면 됩니다..^^*
                 미루고 미루었는데 드뎌 정리를 했습니다...^^;
                 마니 마니 도움이 되었으면 좋겠습니다...
                 질문이나 이상한 점은 게시판을 이용해 주세요..^^;
            
  Internet Explorer에서 실행되는 Signed Applet을 만드는 방법을 정리한 문서입니다.

              -. Microsoft SDK for Java를 이용하여 Applet에 Sign을 하여 Signed Applet을 만들 수 있습니다.
                 아쉽게도 Signed Applet에 대한 개념을 원하신다면 이 문서에는 없습니다..-.-
                 이 문서는 다만 Signed Applet을 만드는 방법만을 설명합니다..
                 그냥 순서에 따라 만드시면, 쉽게 Signed Applet을 만드실 수 있습니다...
                 그리고, 이 문서는 cabarc라는 명령어(Microsoft SDK for Java에 포함되어 있음.)사용합니다.
                 요즘에는 dubuild라는 명령어(Microsoft SDK for Java에 포함되어 있음.)를 사용합니다...
                 dubuild를 사용하는 방법도 거의 비슷한데...제가 게을러서 정리를 아직 못했습니다..*^^*
                 조만간 정리를 해서 올리도록 하겠습니다...기대하세요~~~~
            

'JAVA > JSE' 카테고리의 다른 글

[허가없는 링크^^] 패턴  (0) 2004.10.25
[펌] JAVA application 성능향상..  (0) 2004.10.07
[펌 http://raytrust.pe.kr/] signed applet  (0) 2004.09.06
[펌] javadoc 유틸리티  (0) 2004.09.01
[nio] 기초 정리 잘된곳  (0) 2004.08.09
[펌] 나만의 자바 컴포넌트를 만들자  (0) 2004.04.01
Posted by Tornado tornado

댓글을 달아 주세요

Appendix II

 

javadoc 유틸리티

javadoc 유틸리티는 클래스들, 메소드들과 /** . . . */주석을 위한 소스파일을 분석한다.또한, API 문서와 같은 형태의 HTML 파일을 생성해낸다. 사실, API 문서는 자바 소스 파일에 대한 javadoc 의 결과이다.

만일 여러분의 소스 코드에 특별한 구별자인 /**로 시작하는 주석을 추가하면 여러분은 간단히 전문적으로 보이는 문서를 얻을 수 있다. 이 방법은 한 군데에 여러분의 코드와 문서를 저장하게 해주기 때문에 아주 좋은 방법이다. 전통적인 문서는 코드와 주석들이 분리되어 있는문제로 인해 고생하고 있다. 주석이 소스 파일로서 같은 파일 안에 존재하기 때문에 손쉽게내용을 갱신한 후 다시 javadoc 을 수행하기만 하면 된다.

우리는 corejava 패키지내의 파일들에 대해 /** 주석과 javadoc 을 사용했다. 여러분의 웹브라우저를 \CoreJavaBook\corejava\api\tree.html 에 위치시키면 친숙한 형태의corejava 문서를 볼 수 있을 것이다.

 

주석을 삽입하는 방법

javadoc 유틸리티는 다음의 기능에 대한 정보를 추출한다.

l  package

l  public 클래스

l  public interface

l  public 또는 protected 메소드

l  public 또는 protected 변수와 상수

여러분은 이러한 기능들 각각에 대한 주석을 제공할 수 있다.

각각의 주석은 설명하고자 하는 기능의 바로 위에 위치시킨다. 주석은 /**로 시작하여 */

끝을 낸다.

/* * . . . */ 문서화 된 주석은 태그를 따르는 자유 형태의 텍스트를 따른다. 태그

@author 또는 @param 와 같이 @로 시작한다.

자유 형태의 텍스트의 첫 문장은 요약문이다. Javadoc 유틸리티는 자동으로 이러한 문장을 가지는 요약 페이지를 생성한다.

자유 형태 텍스트에서 여러분은 이탤릭체를 위한 <i> . . . </i> , 타자체 폰트를 위한 <tt> . . . </tt> , 볼드체를 위한 <b> . . . </b> , 이미지를 포함하는 <img. . .>처럼 HTML 수식어를 사용할 수 있다. 그러나 여러분은 <h1>이나 <hr> 헤딩을 사용해서는 안 된다. 왜냐하면 이것들은 문서의 포맷팅과 충돌을 일으키기 때문이다.

----------------------------------------------------------------------

노트 : 만약 주석이 이미지(예를 들어, 사용자 인터페이스 구성요소의 다이어그램이나 이미

)와 같은 다른 파일과의 링크를 포함한다면, 이러한 파일은 doc-파일로 이름 지위진 서브

디렉토리에 위치한다. javadoc 유틸리티는 이러한 모든 파일을 소스 디렉토리에서 문서 디

렉토리로 복사한다.

----------------------------------------------------------------------

 

일반적인 주석

다음의 태그들이 모든 문서화 주석에 지원된다.

@ since 텍스트

이 태그는 “since” 엔트리를 만든다. text 는 기능을 설명하는 버전을 기술하는 것이다.

@ deprecated 텍스트

이 태그는 더 이상 사용되지 않는 클래스, 메소드, 변수에 대하여 설명을 한다. text 는 제자리로 되돌린다(replacement). 예를 들어, @deprecated Use <tt> setVisible(true) </tt>@see @link tags 를 사용하여 javadoc 문서의 연관된 일부분 또는 외부의 문서로 하이퍼링크되어 진다.

@see link

이 태그는 “See also” 섹션에서 하이퍼링크를 추가한다. 클래스와 메소드 두 가지를 모두사용할 수 있다. 이기서 link 는 아래의 하나이다.

l  package.class#feature label

l  <a href=”. . .”>label</a>

l  “text”

첫 번째 경우가 가장 유용한 경우이다. 클래스와 메소드, 변수의 이름을 주면 javadoc 은 문서에 하이퍼링크를 추가한다. 예를 들어, @see corejava.Console#readInt

(java.lang.String)corejava.Console 클래스의 readInt (String) 메소드에 링크를 추가한다. 패키지의 이름 혹은 패키지와 클래스의 이름을 모두 생략할 수 있다. 그러면,기능은 현재의 패키지나 클래스의 중심부에 있다.

메소드나 변수의 이름과 구분을 하기 위하여 #을 사용해야 함에 주의하여야 한다. 자바 컴파일러는 그 자체로, 패키지와 서브패키지, 클래스, 내부클래스, 메소드, 변수 사이의 구분자로서, 구간 문장의 다양한 의미를 추정하는 고도의 기술을 가지고 있다. 하지만 javadoc 틸리티는 그렇게 똑똑하지 못하여 항상 도와 주어야 한다.

만약 < 문자 뒤에 @see 태그가 온다면 하이퍼링크를 명시하여야 한다. 여러분은 원하는 어떤URL 과도 링크를 할 수 있다. 예를 들어, @see <a href =

www.horstmann.com/corejava.html>The Core Java home page</a> 이러한 각 경우에, 링크를 고정시켜 보이게 하는 선택적인 label 을 지정할 수 있다. 레벨을잊었다면 사용자는 타겟 코드 이름이나 URL 을 볼 것이다.

문자 다음에 @see 태그가 온다면 “see also” 절에 텍스트가 표시된다. 예를 들면, @see“Core Java 1.2 volume 2” 이다.하나의 기능에 대하여 다중 @see 태그를 추가 할 수도 있다. 하지만 이 모두는 반드시 함께있어야 한다.

원한다면 주석의 어디에라도 다른 클래스나 메소드에 하이퍼링크를 위치 시킬 수 있다. 주석의 어디에라도 {@link package.class#feature label} 형태의 특수형 태그를 추가 할 수 있다. 기능의 묘사는 @see tag 와 같은 룰을 따른다.

 

클래스와 인터페이스 주석

클래스 주석은 class 정의 바로 앞이면 어떠한 import 문 뒤에라도 올 수 있다.

태그에는 다음의 것들이 있다.

@author 이름

이 태그는 “author” 엔트리를 만든다. 여기에는 여러 명의 저자를 위한 복수개의 author태그를 사용할 수 있다. 그러나 그들은 모두 함께 선언돼야 한다.

@version

Posted by Tornado tornado

댓글을 달아 주세요

http://my.dreamwiz.com/conbox/deepjava/nio/nio_home.htm

 

기초 정리 깔끔~!

Posted by Tornado tornado

댓글을 달아 주세요

나만의 자바 컴포넌트를 만들자
eapoeash (2004-03-22 17:40:14)

저자: 김영익 / (주)콘텔라


자바 프로그래머라면 당연히 AWT나 Swing 컴포넌트에 대해서 알고 있고 GUI를 위해서 여러 형태의 컴포넌트들을 조합해서 원하는 화면을 만들어 보았을 것이다. 그러나 때로는 JDK 에서 지원하는 표준 컴포넌트들만으로는 무엇인가 부족함을 느껴 본적은 없는가? 자신의 입맛에 딱 맞는 컴포넌트가 없어서 오랜 시간을 허비하거나 고생해본 경험이 있을 수도 있다. 이번 기사에서는 자신만의 간단한 컴포넌트를 작성해보기로 하자.


1. 이렇게 만들어 주세요~~~

필자가 작년에 수행했던 프로젝트 중에 이런 기능을 넣어 달라는 요구 사항이 있었다.
“유닉스 시스템의 CPU, 메모리, 파일 시스템의 상태를 감시하는 기능을 챠트를 이용해서 보기 좋게 넣어달라” 요구 사항 자체는 간단했지만 챠트를 만들기 위해서는 상당한 노력이 필요하기 때문에 다른 라이브러리를 사용하기로 결정했다. 비용 절감을 위해 “JFreeChart” 라는 오픈 소스 프로젝트를 사용해서 챠트 문제를 해결했지만 한가지 남은 문제가 있었다.
CPU의 상태를 윈도우의 작업 관리자에서 보이는 형태처럼 만들어 달라는 것이었다.

null


JProgressBar를 사용하면 비슷한 형태가 나오기는 하지만 아무래도 많이 다르다는 느낌이 들어서 직접 만들어서 사용하기로 결정했다. 최종적으로 구현된 결과는 아래 화면을 참고하자.



원래 이 컴포넌트만 단독으로 보여 주는 것은 아니었고 다른 그래프들과 함께 프레임에 포함된 것이었다. JFreeChart로 그려진 그래프도 구경할 겸해서 아래 그림도 첨가한다.




2. 주요 구현 설명

일반적으로 자바 컴포넌트를 만들기 위해서 Sun 에서는 자바 빈즈 컴포넌트 명세를 따르기를 권고한다. 그러나 지침대로 모든 사항을 맞추기에는 시간과 노력이 너무 많이 들기 때문에 최대한 간단하게 원하는 기능만을 수행하도록 작성 해보도록 하자.

소스의 양도 그리 길지 않고 어려운 부분도 없으므로 소스에 삽입된 주석만을 주의 깊게 살펴보면 된다.

import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
import java.awt.event.*;

public class PmTickChartPanel extends JPanel {
  BorderLayout borderLayout1 = new BorderLayout();
  JPanel centerPanel = new JPanel();
  JPanel southPanel = new JPanel();
  JPanel northPanel = new JPanel();
  JLabel dataLabel = new JLabel();
  GridLayout gridLayout1 = new GridLayout();
  BorderLayout borderLayout2 = new BorderLayout();
  JLabel titleLabel = new JLabel();
  BorderLayout borderLayout3 = new BorderLayout();
  JPanel westPanel = new JPanel();
  JPanel eastPanel = new JPanel();

  // 편의상 눈금은 10개만 보이고 색상 변경도 10 단위로만
  int tickCount = 10;

  Border centerPanelBorder;
  private Border border1;

  public PmTickChartPanel() {
    try {
      jbInit();
    } catch (Exception e) {
      e.printStackTrace();
   }
  }

  private void jbInit() throws Exception {
    centerPanelBorder = BorderFactory.createLineBorder(Color.green, 1);
    border1 = BorderFactory.createBevelBorder(BevelBorder.LOWERED, new Color(4, 4, 4), new Color(3, 3, 3), Color.black, Color.black);
    this.setBackground(Color.black);
    this.setForeground(Color.green);
    this.setBorder(border1);
    this.setLayout(borderLayout1);
    centerPanel.setBackground(Color.black);
    centerPanel.setFont(new java.awt.Font("Dialog", 0, 12));
    centerPanel.setForeground(Color.green);
    centerPanel.setBorder(centerPanelBorder);
    centerPanel.setLayout(gridLayout1);
    southPanel.setBackground(Color.black);
    southPanel.setForeground(Color.green);
    southPanel.setLayout(borderLayout2);
    northPanel.setBackground(Color.black);
    northPanel.setForeground(Color.green);
    northPanel.setLayout(borderLayout3);
    dataLabel.setBackground(Color.black);
    dataLabel.setFont(new java.awt.Font("Dialog", 1, 12));
    dataLabel.setForeground(Color.green);
    dataLabel.setHorizontalAlignment(SwingConstants.CENTER);
    dataLabel.setHorizontalTextPosition(SwingConstants.CENTER);
    dataLabel.setText("");
    titleLabel.setBackground(Color.black);
    titleLabel.setFont(new java.awt.Font("Dialog", 1, 12));
    titleLabel.setForeground(Color.green);
    titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
    titleLabel.setHorizontalTextPosition(SwingConstants.CENTER);
    this.titleLabel.setText("CPU");
    gridLayout1.setColumns(1);
    gridLayout1.setRows(tickCount);
    gridLayout1.setHgap(1);
    gridLayout1.setVgap(1);
    eastPanel.setBackground(Color.black);
    eastPanel.setForeground(Color.green);
    westPanel.setBackground(Color.black);
    westPanel.setForeground(Color.green);
    this.add(centerPanel, BorderLayout.CENTER);
    this.add(southPanel, BorderLayout.SOUTH);
    southPanel.add(dataLabel, BorderLayout.CENTER);
    this.add(northPanel, BorderLayout.NORTH);
    northPanel.add(titleLabel, BorderLayout.CENTER);
    this.add(westPanel, BorderLayout.WEST);
    this.add(eastPanel, BorderLayout.EAST);
    setPreferredSize(new Dimension(90, 180));

    for (int i = 0; i < tickCount; i++) {
      Tick tick = new Tick(); // 눈금(tick)을 10개 생성하여 추가
      this.centerPanel.add(tick);
    }
  }

  /* 실제 컴포넌트에 값을 설정하면 눈금에 색상을 변경한다
  *  값의 범위는 0~100 으로 하자
  */
  public void setValue(int value) {
    if (value > 100) { // 100을 넘어가면 100으로
      value = 100;
    }
    else if (value < 0) { // 0보다 작으면 0으로
      value = 0;
    }

    // 일단 전체 tick 을 검정색으로 칠하고
    for (int j = 0; j < tickCount; j++) {
      Tick tick = (Tick)this.centerPanel.getComponent(j);
      tick.setBackground(Color.black);
      tick.repaint();
    }

    // 입력된 value 값에 해당하는 tick들만 다시 녹색으로 칠한다
    for (int i = 0; i < tickCount; i++) {
      Tick tick = (Tick)this.centerPanel.getComponent(i);
      if (tickCount - i > value / 10) {
        // nothing to do
      } else {
        tick.setColor(Color.green);
        tick.repaint();
      }
    }

    // 하단에 숫자로 값을 표시
    this.dataLabel.setText(value + " %");
  }

  public static void main(String args[]) {
    JFrame frame = new JFrame(); // 테스트용 프레임을 생성하자
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    PmTickChartPanel tickPanel = new PmTickChartPanel();
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(tickPanel, BorderLayout.CENTER);

    frame.setSize(300, 300);
    frame.setVisible(true);
    
    for (int i = 0 ; i < 100 ; i++) { // 테스트를 위해 값을 설정하는 부분
      try {
        Thread.sleep(100); // 잠시 쉬었다가
        tickPanel.setValue(i); // 1씩 증가되는 값을 설정, 10 단위로 눈금 색상 변경
      }
      catch (InterruptedException ie) {
        ie.printStackTrace();
      }
    }
  }
}

/* 10 단위의 눈금 하나에 해당하는 컴포넌트
* 같은 값을 갖는 것이 좌우 하나씩 쌍으로 구성된다
*/
class Tick extends JPanel {
  JPanel lPanel = new JPanel();
  JPanel rPanel = new JPanel();
  GridLayout layout = new GridLayout(1, 2);

  public Tick() {
    this.setBackground(Color.black);
    this.setForeground(Color.black);
    lPanel.setBackground(Color.black);
    lPanel.setForeground(Color.green);
    rPanel.setBackground(Color.black);
    rPanel.setForeground(Color.green);
    layout.setHgap(1);
    setLayout(layout);
    add(lPanel);
    add(rPanel);
  }

  protected void setColor(Color color) {
    lPanel.setBackground(color);
    rPanel.setBackground(color);
  }
}

3. 나만의 컴포넌트 작성 소감

위의 소스를 작성하고 컴파일까지 이상 없이 진행되었다면 실행해보자. 앞에서 보여진 그림처럼 값이 증가됨에 따라 눈금이 올라가는 것을 볼 수 있다. 대단한 것은 아니지만 예상보다 예쁘게 보이는 컴포넌트가 대견하기만 하다. 여러분은 용도에 따라 별도의 구현만 추가한다면 입맛에 바꿔 사용할 수 도 있고, 이 예제를 기반으로 다른 컴포넌트를 작성할 준비가 된 것이다. 언제까지 남이 만든 것만 사용할 것인가? 머리 속에 무엇인가 떠오르는 것이 있다면 지금 당장 준비하자 !!!
Posted by Tornado tornado

댓글을 달아 주세요

출처 : http://www-903.ibm.com/developerworks/kr/java/library/j-jmx3.html

JMX Agent를 네트워크 관리 시스템에 연결하기

Level: Intermediate

Sing Li
작가, Wrox Press
2002년 12월 17일

실제 Network Management System (NMS)를 사용하여 JMX로 만들어진 자바 애플리케이션을 모니터링한다. NMS/JMX 통합에 사용된 일반적인 기술은 물론 JMX를 전개할 때 발생하는 일반적인 어려움들을 설명한다.

JMX는 자바 플랫폼의 새로운 표준 확장으로서 현대적 Network Management Systems (NMS)를 통해 장치, 애플리케이션, 서비스들을 관리 및 제어, 감시할 수 있다. JMX가 소프트웨어 애플리케이션/서비스를 어떻게 활용하는지를 확실히 알고 싶다면 실제 오픈 소스 NMS(OpenNMS)를 사용하여 ClickMeter 애플리케이션을 모니터링한다. 광범위한 가용성과 단순한 디자인 때문에 OpenNMS를 선택했다. 여러분들도 다른 NMS 제품에 설명된 통합 기술을 적용할 수 있다. OpenNMS 스팩으로 작업하기 전에 일반적인 디자인 엘리먼트와 대부분의 NMS 제품이 공유하는 작동 모델을 보도록 하자.

네트워크 관리 시스템- 그 근본적인 복잡성
네트워크 관리 사용자 인구가 다양해진 덕택에 지금의 NMS 제품은 가장 광범위하고 복잡한 소프트웨어 시스템이 되었다. 예를 들어 분산 작동 센터를 통해 통신 네트워크 장비를 관리 및 감시하는 다국적 조직은 가상 프라이빗 네트워크(VPN), PC 자산, 데이터 통신 자산, 애플리케이션 서버 관리에 필요한 지역 비지니스의 다양한 요구를 안게 될 것이다.

전형적인 NMS는 수천, 수만, 심지어 수백만 엔드포인트(노드)를 관리해야 한다. NMS의 목표 고객들은 중간 규모 이상의 조직들이다. 이러한 고객들은 다양한 비지니스를 하기 때문에 NMS는 채택성이 높은 설정 메커니즘과 고객의 다양한 요구를 만족시킬 사용자 인터페이스를 갖춰야 한다. 전형적인 NMS 솔루션의 고비용을 정당화 할 수 있어야 한다.

관련 기술자료

Part 1, "Management, JMX 1.1 style" (2002년 9월)

Part 2, "Beans, JMX 1.1 style" (2002년 10월)

OpenNMS: 오픈 소스 NMS
OpenNMS는 오픈 소스 분야에서는 하나의 소프트웨어 시스템이다. 이것은 개발 커뮤니티에 복잡하지만 채택가능한 NMS 솔루션의 실행파일과 소스 코드를 무료로 제공하려는 시도이다.

OpenNMS는 레거시 없이 탄생했기 때문에 보다 새로운 접근방식이 필요했다. OpenNMS는 사용자 중심의 NMS이며 전형적인 네트워크 관리자를 싱글 포인트 포커스로 두어 필요한 기능을 결정하게한다. 몇몇 안되는 구성원으로 이루어진 초기 팀은 네트워크 관리 컨설턴트이며 그들의 지식을 총동원하여 객체, 태스크, 워크플로우 관련 작동 모델을 규명했다. 이것은 상용 NMS 제품에 대비되며 디바이스 중심, 네트워크 중심, 소프트웨어 서비스 중심 성격이된다.

NMS 분석
많은 NMS 제품들은 애플리케이션의 특정 도메인, 코드 유산, 벤더와 상관 없이 유사한 개념적 구성을 갖고있다. 그림 1은 이러한 일반적 구성을 설명하고 있다.

그림 1. NMS의 개념적 구성
Figure 1. Conceptual composition of an NMS

구성은 일반적으로 3-TIER 이다. 프론트(front) 티어는 관리되고 있는 디바이스와 서비스의 네트워크, 시스템 사용자, 외부 시스템과 인터페이싱한다. 미들 (middle) 티어에는 NMS의 기능 세트를 제공하는 많은 로직이 포함되어 있다. 백엔드(back-end) 티어는 데이터를 유지하고 조작한다.

광범위한 정보와 동적이지만 강력한 기반에서 트래킹되어야 할 복잡한 상호관계 때문에 NMS는 상용 관계형 데이터베이스 관리 시스템(RDBMS)을 백엔드 티어에 전개했다.

첫 번째 티어에서 모니터링, 관리, 제어 컴포넌트는 NMS 작동을 실행해야 하는 많은 동시 태스크들로 구성되어 있다. 액티브 네트워크 발견, 디바이스 정지 및 서비스 등록하기, 디바이스, 서비스, 고급 분산 에이전트에서 비동기식 이벤트 개입 및 프로세싱을 맡고 있다. 이 컴포넌트는 설정 로직, 제공 로직, 워크플로우 실행자, 미들 티어의 커스텀 로직에서 온 작동들 역시 수행한다.

OpenNMS의 역사
2002년 봄, OpenNMS 1.0이 탄생했다. 오픈 소스로 사용할 수 있는 최초의 엔터프리이즈급 네트워크 관리 플랫폼이 탄생한 것이다. 2002년 5월, 프로젝트의 담당자들은 OpenNMS에 지원과 컨설팅 서비스를 제공하는 Sortova Consulting Group으로 옮겼지만 개발 진화는 계속되고 있다.

1999년, 시스템 프로그래머들과 네트워크 관리 컨설턴트들은 관리 제품의 현황에 실망하고 해결책을 모색할 것을 결정했다. 상용 NMS 제품의 천문학적 비용을 감지한 팀은 오픈 소스 개발 모델을 사용하여 보다 나은 것을 개발하기로 결정했다.

또한, 프론트 티어는 사용자 인터페이스 컴포넌트이다. NMS는 "fat client GUI" 인터페이스는 물론 쉽게 커스터마이징 할 수 있는 웹 기반 사용자 인터페이스도 가지고 있다. 리포팅 장치가 이 레이어에 있으며 UI와 인터랙팅하여 실시간 소프트 카피 리포트는 물론 배치 하드 카피 리포트도 제공한다.

첫 번째 티어의 외부 인터페이싱 컴포넌트는 사용자와 외부 시스템에 공지 프로세스를 할 수 있다. 페이저호출, 이메일, 전호 호출, 특정 이벤트를 외부 관리 시스템에 전한다. API와 확장 플러그인 기반구조로 인해 NMS는 커스터마이징 될 수 있고 다른 시스템과 인터페이싱 및 통합될 수 있다.

미들 티어는 NMS의 로직이 존재하고 있는 곳이다. NMS에 구별된 기능과 특성을 부여한다. 재고 또는 자산 관리, 데이터 수집과 분석, 사용자 또는 역할 관리, 워크 플로우 관리/실행 등이 알려진 기능들이다.

재고(또는 자산) 관리는 대부분의 NMS 제품의 주요 기능이다. 트래킹되는 아이템들은 NMS에서 장비, 서킷, 서버, 설치된 소프트웨어 서비스와 애플리케이션에 이르기까지 다양하다. 이 컴포넌트의 사용자 인터페이스와 애플리케이션 로직은 관리되는 다른 아이템들에게도 유연하게 적용될 수 있다.

데이터 수집과 분석 기능은 관리되고 있는 디바이스와 서비스에 대한 현재와 기존의 통계를 제공한다. 네트워크와 서브 네트워크, 디바이스/서비스 가용성을 드러내는 통계적 분석을 제공한다. 이 컴포넌트는 커스텀 워크플로우를 핸들하기 위해 워크플로우 실행 로직과 인터랙팅 할 수 있다.

사용자와 역할 관리 컴포넌트는 NMS에 다양한 레벨의 접근을 제공한다. 가장 넓은 네트워크는 하나 이상의 팀이 관리한다. 사용자들에게 할당된 역할은 디자인과 커스텀 보안 정책의 구현 뿐만 아니라 커스텀 워크플로우와 이벤트 증대 플로우에 사용될 수 있다.

워크플로우 관리 및 실행은 장단기 관리 태스크의 관리 및 자동 실행을 제공한다. 자동화된 커스텀 워크플로우는 다양한 조직의 다양한 비지니스 요구사항에 NMS가 채택되는데 필수적인 요소이다.

NMS 모든 NMS가 이 모든 컴포넌트들을 갖고 있는 것은 아니고 어떤 것은 보다 구체화된 변이를 갖고 있을 수도 있다. 이 글에서 검토되는 것들은 NMS를 구성하고 있는 것들에 대한 일반적 개요라 할 수 있다.

OpenNMS 아키텍쳐
그림 1을 레퍼런스로 사용하여 레퍼런스 구성과 OpenNMS의 아키텍쳐 사이의 구체적 구성도를 그릴 수 있다. 그림 2는 OpenNMS를 구성하고 있는 컴포넌트이다.

그림 2. OpenNMS의 컴포넌트
Figure 2. Components of OpenNMS

백엔드 티어에서 OpenNMS는 RDBMS로서 PostgreSQL (참고자료)을 사용한다. 프론트 티어에서 Apache Jakarta Tomcat (참고자료)의 JSP와 서블릿 기술을 사용하여 유연하게 커스터마이징 할 수 있는 사용자 인터페이스를 제공한다. 기존 Perl 기반의 사용자 인터페이스 역시 사용할 수 있다. 여러 관리 유틸리티들은 UNIX 쉘 스크립트와 Perl로 작성된다. OpenNMS는 그림 1의 모니터링, 관리, 제어 컴포넌트에 상응하는 컨커런트 자바 태스크를 사용하여 이 기능을 제공한다. 이러한 동시 태스크들은 그림 2에 원으로 표현되었다.

OpenNMS 데몬: 컨커런트(concurrent) 관리 태스크
OpenNMS의 모니터링, 제어, 데이터 수집 기능들은 데몬(daemon) 이라고 하는 컨커런트 태스크에 의해 핸들된다. (BSD UNIX 규약). 표 1은 컨커런트 관리 태스크들 이다.

표 1. OpenNMS의 컨커런트 관리 태스크

Concurrent Taskdaemon 이름 Description
Action daemonactiond자동 액션 실행 장치. 인커밍 이벤트에 근거한 자동화된 액션.
Collection daemoncollectd관리되는 노드에서 데이터 수집.
Capability daemoncapsd발견된 노드 상에서 기능 검사 수행. 알려진 서비스 프로토콜 지원을 위한 인터페이스 포트 점검.
DHCP daemondhcpdOpenNMS에 DHCP 클라이언트 기능 제공.
Discovery daemondiscovery관리되는 네트워크 노드의 초기 및 지속적인 발견.
Events manager daemoneventd다른 컨커런트 태스크에서 나온 이벤트의 관리 및 (RDBMS에) 저장
Notification daemonnotifd외부 공지 수행.
Outage manager daemonoutaged이벤트를 결합하여 각 관리되는 노드/서비스에 outage 뷰 제공.
Poller daemonpollerd관리되는 노드/서비스를 정기적으로 등록하여 작동 상태 결정.
RTC manager daemonrtcd실시간으로 데이터를 수집하여 관리되는 노드/서비스의 사용자 정의 카테코리에 가용성 정보 제공.
SNMP trap daemontrapdSNMP 트랩(이벤트) 핸들.
Threshold service daemonthreshd특정 임계값에 도달한 애트리뷰트 값에 근거하여 노드/서비스 감시.

OpenNMS 확장하기
OpenNMS의 프론트 티어에서 특정 수직 애플리케이션 도메인에 시스템을 적용하는 것은 매우 단순하다. JSP 기술의 유연성 덕택에 OpenNMS의 사용자 인터페이스는 자바 개발자들이 쉽게 커스터마이징할 수 있다. 새로운 NMS 애플리케이션 로직은 JSP 파일과 서블릿 코딩의 결합을 통해 빠르게 추가될 수 있다.

OpenNMS는 관리되는 디바이스/서비스용 SNMP 지원이 됨으로서 표준이 되었다. SNMP는 관리가 편리한 디바이스/서비스용 산업 표준이다. 이 표준은 OpenNMS가 TCP/IP 네트워크 상에서 다양하고 광범위한 기존 디바이스를 관리 할 수 있도록 한다.

SNMP 밖에서, OpenNMS는 대중적인 소프트웨어 서비스(FTP, 파일 서버, 데이터베이스 서버)를 탐지하고 관리할 수 있다. 서비스 스팩의 플러그인을 제공하고 이를 수행하는지를 감시한다. 새로운 플러그인과 모니터를 만듦으로서 OpenNMS는 새로운 디바이스 또는 서비스를 탐지하고 감시할 정도로 확장될 수 있다.

커스텀 기능의 플러그인 만들기
OpenNMS의 디스커버리 데몬(discovery)은 관리되는 네트워크의 초기 및 지속적인 발견을 맡고있다. 일단 discovery가 노드를 발견하면 기능 데몬에게 노드가 지원하는 서비스가 무엇인지를 요청한다. 기능 데몬은 특정 프로토콜 플러그인을 통해 반복하여 서비스가 지원하는 것을 검사한다. 커스텀 프로토콜 플러그인을 작성하는 것은 단순하다. 단계는 다음과 같다:

  1. org.opennms.netmgt.capsd.Plugin 인터페이스를 구현하는 클래스를 만든다. 특히 이 인터페이스는 플러그인이 구현해야 하는 세 개의 메소드를 갖고있다. (표 2):

    표 2. org.opennms.netmgt.capsd.Plugin 인터페이스의 메소드

    메소드 이름과 사인Description
    String getProtocolName();이 플러그인의 프로토콜 이름을 리턴한다.
    Boolean isProtocolSupported(java.nnet.InetAddress address);
    boolean isProtocolSupported(java.nnet.InetAddress address, java.util.Map properties);
    필요할 경우 인커밍 매개변수용 프로퍼티 맵을 사용하여 이 프로토콜이 구체적인 InetAddress의 지원을 받는지를 결정한다.



  2. /etc/capsd-configuration.xml 파일에 프로토콜-플러그인 정의를 만든다. 이것은 capsd가 시작하는 동안 사용할 프로토콜 플러그인을 결정하기 위해 읽게된다.

커스텀 폴러(poller) 모니터 만들기
OpenNMS가 관리 노드상의 서비스를 결정한 후에 폴러 데몬(pollerd)을 사용하여 관리되는 디바이스/서비스를 정기적으로 등록한다. 그들이 작동하고 있다는 것을 확인하기 위해서이다. pollerd는 지정된 폴러 모니터 "플러그인"을 통해 반복하면서 개별 서비스 폴들을 수행한다:

  1. org.opennms.netmgt.poller.ServiceMonitor 인터페이스를 구현하는 클래스를 만든다. 특히 이 인터페이스는 모니터가 구현해야 하는 다섯 개의 메소드를 갖고있다. (표 3):

    표 3. org.opennms.netmgt.poller.ServiceMonitor 인터페이스의 메소드

    메소드 이름과 사인Description
    void initialize(java.util.Map parameters);
    void initialize(org.opennms.netmgt.poller.NetworkInterface iface);
    첫 번째 형식은 시작하는 동안 호출되어 플러그인이 초기화 중에 실행할 수 없도록 할 기회를 제공한다. 두 번째 형식은 새로운 노드가 발견될 때마다 서비스를 지원하기 위해, 그리고 첫 번째 poll()이 호출되기 전에 호출된다.
    void release();
    void release(java.net.NetworkInterface iface);
    첫 번째 형식은 OpenNMS 정지 시 호출된다. 두 번째 형식은 서비스를 지원하기 위해 발견된 노드가 더이상의 폴링 스케쥴에서 제거될 때 마다 호출된다.
    int poll(java.net.NetworkInterface iface, org.opennms.netmgt.utils.EventProxy eproxy, java.util.Map parameters);감시되고 있는 서비스를 여전히 사용할 수 있는지를 결정할 때 사용되는 메소드이다. 서비스가 실행 중일 경우에는 ServiceMonitor. SERVICE_AVAILABLE을그렇지 않으면 ServiceMonitor. SERVICE_UNAVAILABLE을 리턴해야 한다.

  2. /etc/poller-configuration.xml 파일에 서비스 정의와 모니터 정의를 만든다.

OpenNMS 다운로드 및 설치
리눅스 배포판과 OpenNMS의 시스템 요구사항을 숙지해야 한다. 자세한 설치 및 업데이트 절차는 이 글에서 다루지는 않는다. 참고자료 섹션에서 OpenNMS의 최신 버전 다운로드 정보를 검색할 수 있다.

OpenNMS의 최신 안정 버전은 1.0.2이다. 이 글의 모든 코드는 이 안정 버전으로 테스트를 한 것이다. OpenNMS1.0.2는 세 가지 리눅스 스팩(Red Hat Linux 7 & 8, Mandrake 8)에서 테스트되었다. 복잡한 시스템으로 초기 실험 시 이 세 배포판 중 하나를 사용하기 바란다.

OpenNMS를 사용하여 JMX 가능한 ClickMeter 감시하기
capsd 플러그인과 pollerd 모니터를 만듦으로서 OpenNMS와 JMX 구동의 ClickMeter를 통합할 수 있다는 것을 알고 있다. 하지만 한가지 질문이 남아있다. OpenNMS는 JMX를 지원하지 않는가?

심지어 유명한 상용 NMS 오퍼링에서도 같은 경향을 엿볼 수 있다. JMX가 기본적으로 지원되지 않는다. JMX 구동의 디바이스와 서비스는 진행중에 있기 때문이기도하고 SNMP 호환이 제 3의 디바이스와 서비스의 관리에 제공되었기 때문이기도 하다.

JMX의 통합 과정이 NMS 벤더들 사이에서 비교적 느리게 진행되는 중요한 이유가 있다. JMX 사용 레벨과 에이전트 레벨이 1.1 스팩에는 적절히 정의되어있더라도 네트워크를 통해 JMX 에이전트에 액세스 하는 방법은 아직까지는 모호하다.

JMX Remoting 딜레마
JMX 에이전트가 네트워크 관리 애플리케이션이나 분산 서비스에 의해 네트워크를 통해 액세스되는 방법은 JMX Remoting이라고 알려져있고 이것이 JSR 160의 핵심 사안이다.(참고자료).

JSR 160은 JMX 에이전트의 발견이 네트워크를 통해서나 에이전트의 기능에 원격으로 액세스하는 구체적인 방법을 통해 어떻게 수행되는지를 정한다. 여기에는 사용될 프로토콜 어댑터 관련 스팩들이 포함될 것이다. JMX Remoting 1.2 스팩이 마감될 때까지 OpenNMS와 ClickMeter MBean을 관리하는 JMX 에이전트 사이의 통신 대안을 찾아야 한다.

JMX remoting 솔루션
물론, JMX 에이전트의 주요 목적은 이것이 관리하는 JMX MBeans로의 원격 액세스를 제공하는 것이다. 에이전트들은 커넥터와 프로토콜 어댑터를 사용하여 NMS 애플리케이션 또는 분산 서비스들과 통신한다.

ClickMeter의 경우 JMX 레퍼런스 구현의 간단한 에이전트를 사용했다. 여기에는 HTTP 프로토콜 어댑터가 포함되어 있다. 이 간단한 에이전트는 HTTP 프로토콜 어댑터를 통해 모든 MBeans의 애트리뷰트와 작동을 노출한다.

HTTP 어댑터를 사용하여 작업을 최소화하기
OpenNMS와 ClickMeter MBean 사이의 통신을 위해 JMX 레퍼런스 구현에서 간단한 에이전트와 HTTP 프로토콜을 쉽게 사용할 수 있다. 그림 3은 통신 방식을 제안한 것이다. 작동중에 OpenNMS의 capsd는 탐지된 노드를 검사하여 "CLICKMETER" 서비스가 지원되는지의 여부를 본다. pollerd는 탐지된 서비스를 정기적으로 등록하여 이들이 작동중임을 확인한다. 이러한 탐침들을 수용하기 위해서 incPanelValue 호출 작동을 사용할 수 있다. 탐침 메커니즘으로서 incPanelValue 작동을 사용하는 것의 이점은 OpenNMS의 탐지 및 등록 액션을 시각적으로 볼 수 있다는 것이다. ClickMeter의 값은 탐침 때마다 증가한다.

그림 3. HTTP 어댑터로 ClickMeter에 액세스하기
Figure 3. Accessing ClickMeter with the HTTP adapter

이제 남은 일은 ClickMeter MBean 에서 incPanelValue 작동에 액세스 하기 위해 HTTP 프로토콜 어댑터를 사용하는 방법을 결정하는 일이다. 브라우저를 사용하여 다음 URL에서 JMX 에이전트에 액세스할 수 있다:

http://<host of agent>:8082/

물론 이를 수행하기 전에 에이전트가 실행되는지 확인해야 한다. 그런 다음 버튼을 클릭하여 노출된 incPanelValue 작동을 실행한다. (그림 4).

그림 4. 탐침 URL 결정하기
Figure 4. Determining the probe URL

그림 4 에서, 이 작동에 액세스하기 위해 사용된 URL은 다음과 같다:

http://<host of agent>:8082/InvokeAction//MBean:name=ClickMeter/action=incPanelValue?action=incPanelValue

ClickMeter 애플리케이션이 올바르게 기능을 발휘하고 있다면 결과페이지에는 incPanelValue Successful 이라는 문장이 뜬다. 이 정보를 사용하여 OpenNMS에서 원격으로 MBean에 액세스하겠다.

OpenNMS 통합
이제 새로운 "CLICKMETER" 서비스를 OpenNMS에 통합할 준비가 되었다. 이를 위해 capability 데몬(capsd)용 플러그인과 poller 데몬(pollerd)용 모니터를 만들것이다.

OpenNMS 디스커버리용 ClickMeterPlugin
capability 데몬 플러그인 코드는 org.opennms.netmgt.capsd.ClickMeterPlugin 클래스에 있다. 이 플러그인은 org.opennms.netmgt.capsd.Plugin 인터페이스를 구현해야 한다는 것을 알고있다. Listing 1은 AbstractPlugin 의 클래스이다. OpenNMS가 제공되는 클래스는 두 개의 매개변수 추출 메소드(getKeyedInteger() & getKeyedString())를 제공한다.

Listing 1. ClickMeterPlugin 관리 클래스

public final class ClickMeterPlugin extends AbstractPlugin {    private static final String   PROTOCOL_NAME = "CLICKMETER";    private static final int  DEFAULT_PORT  = 8082;    private final static int  DEFAULT_RETRY = 0;    private final static int  DEFAULT_TIMEOUT = 5000; // in milliseconds

getProtocolName() 메소드는 Listing 2의 코드로 간단히 구현된다:

Listing 2. getProtocolName() 메소드

public String getProtocolName() {     return PROTOCOL_NAME;     }

Listing 3은 isProtocolSupported() 메소드가 구현되는 방법이다:

Listing 3. isProtocolSupported() 메소드

public boolean isProtocolSupported(InetAddress address) {  return isClickMeter(address, DEFAULT_PORT, DEFAULT_RETRY, DEFAULT_TIMEOUT);  }

보다 긴 버전의 isProtocolSupported() 메소드에서는, 원격 JMX 에이전트에 액세스하는 URL을 만드는데 사용되는 인커밍 매개변수를 처리한다. 일단, IP와 포트가 매개변수에서 얻어지면, isProtocolSupported()isClickMeter() 메소드를 호출하여 ClickMeter가 이 노드에서 활성인지를 결정한다. Listing 4는 isClickMeter()에 대한 코드이다. URL용으로 정의된 두 개의 상수가 ClickMeter의 incPanelValue 작동을 위한 HTTP 프로토콜 어댑터 액세스 URL과 상응한다는 것에 주목하라.

Listing 4. isClickMeter() 메소드

private final static String CLICK_METER_BEAN_LOCATOR_URL = "/InvokeAction//MBean:name=ClickMeter/action=incPanelValue?   action=incPanelValue";      private final static String CLICK_METER_ID = "incPanelValue Successful";      private boolean isClickMeter(InetAddress host, int port,         int retries, int timeout) {          Category log = ThreadCategory.getInstance(getClass());          boolean foundClickMeter = false;          for (int attempts=0; attempts <= retries && !foundClickMeter;             attempts++)          {                                    URL jmxLink = null;                  InputStream iStream = null;               try               {                      String hostIP = host.getHostAddress();                      jmxLink = new URL("http", hostIP, port,                         CLICK_METER_BEAN_LOCATOR_URL);                      if (scanURL(jmxLink, CLICK_METER_ID, log)) {                            foundClickMeter = true;                            break;   // get out of the for loop                           }                     }          catch(IOException e) {                    log.info("ClickMeterPlugin: Error communicating                        with host " + host.getHostAddress(), e);                    foundClickMeter = false;              }          }          return foundClickMeter;  }

scanURL() 메소드(Listing 5)는 인자로서 URL과 스트링을 취하는 헬퍼 메소드이다. 이것은 URL에 액세스하고 결과 페이지에서 지정된 스트링을 찾는다. 스트링이 발견되면 true를 리턴한다. 그렇지 않을 경우 false를 리턴한다. 이 경우, ClickMeter의 incPanelValue 작동용 URL에 액세스한 후에 incPanelValue Successful 스트링을 찾고있다.

Listing 5. scanURL() 메소드

private boolean scanURL(URL inURL, String toSearch, Category log)    {                  InputStream iStream = null;           try {                                            iStream = inURL.openStream();                     BufferedReader urlReader =                        new BufferedReader(new InputStreamReader(iStream));                          String curLine = urlReader.readLine();                        do  {                                if (curLine.indexOf(toSearch) != -1) {                                       return true;                                      }                           curLine = urlReader.readLine();                         } while (curLine != null);                        }                 catch  (IOException e) {                              e.fillInStackTrace();                      log.debug("ClickMeterMonitor.poll:                         Error reading from URL:"                         + inURL, e);                      }               finally  {                   try  {                       if(iStream != null)                             iStream.close();                    }                    catch(IOException e) {                        e.fillInStackTrace();                        log.debug("ClickMeterMonitor.poll:                           Error closing stream to URL.", e);                    }               }      return false;   }}

플러그인 통합에 필요한 두 번째 단계는 <OpenNMS installation directory>/etc/capsd-configuration.xml 파일을 편집하고 프로토콜-플러그인 정의를 추가하는 것이다.(Listing 6):

Listing 6. 프로토콜-플러그인 정의

  <protocol-plugin     protocol="CLICKMETER"      class-name="org.opennms.netmgt.capsd.ClickMeterPlugin"     scan="on" >    <property key="port" value="8082"/>    <property key="timeout" value="2000"/>    <property key="retry" value="1"/>  </protocol-plugin>

OpenNMS가 관리되는 노드를 검사해야할 IP 범위를 제한하기 위해 discovery-configuration.xml 파일을 편집하고 싶을 것이다. Listing 7에서는 두 개의 IP로 제한하여 ClickMeter 애플리케이션이 빨리 위치할 수 있도록 한다:

Listing 7. 디스커버리 범위 제한

  <include-range retries="2" timeout="3000">    <begin>192.168.23.75</begin>    <end>192.168.23.76</end>  </include-range>

OpenNMS용 ClickMeterMonitor
다음에는, poller 데몬(pollerd) 모니터 플러그인, org.opennms.netmgt.poller.ClickMeterMonitor 클래스를 만든다: 이 클래스는 org.opennms.netmgt.poller.ServiceMonitor 인터페이스를 구현해야 한다. OpenNMS는 이 인터페이스의 모든 메소드용 디폴트 구현을 갖고있는 기본 클래스(org.opennms.netmgt.poller.IPv4Monitor)를 제공한다. 특별한 초기화나 릴리스가 필요없기 때문에 poll() 메소드를 오버라이딩 하면된다.(Listing 8):

Listing 8. poll() 메소드

public int poll(NetworkInterface iface, Map parameters) {       if(iface.getType() != NetworkInterface.TYPE_IPV4)              throw new NetworkInterfaceNotSupportedException("Unsupported                     interface type, only TYPE_IPV4 currently supported");    Category log = ThreadCategory.getInstance(getClass());    int retry   =       getKeyedInteger(parameters, "retry", DEFAULT_RETRY);    int port    =       getKeyedInteger(parameters, "port", DEFAULT_PORT);    int timeout =       getKeyedInteger(parameters, "timeout", DEFAULT_TIMEOUT);    InetAddress ipv4Addr = (InetAddress)iface.getAddress();            String hostIP = ipv4Addr.getHostAddress();    if (log.isDebugEnabled())               log.debug("ClickMeterMonitor.poll: Polling interface: "                      + hostIP + " timeout: " + timeout + " retry: " + retry);        int serviceStatus = ServiceMonitor.SERVICE_UNAVAILABLE;    for (int attempts=0; attempts <= retry && serviceStatus !=               ServiceMonitor.SERVICE_AVAILABLE; attempts++) {                  URL jmxLink = null;                  InputStream iStream = null;        try {                          jmxLink = new URL("http", hostIP, port,                                     CLICK_METER_BEAN_LOCATOR_URL);                        if (scanURL(jmxLink, CLICK_METER_ID, log)) {                            serviceStatus = ServiceMonitor.SERVICE_AVAILABLE;                            break;                             }                     }          catch(IOException e) {        e.fillInStackTrace();        log.debug("ClickMeterMonitor.poll:                IOException while polling address: "                + ipv4Addr, e);      }    }  // of for       return serviceStatus;  }

scanURL() 헬퍼 메소드(Listing 8)를 사용하여 ClickMeter MBean에 액세스한다는 것에 주목하라.

<OpenNMS installation directory>/etc/poller-configuration.xml 파일에서, 서비스 정의 엔트리를 추가해야 한다. Listing 9에서 폴링 간격을 10,000 밀리초로 정했다:

Listing 9. poller 데몬 서비스 정의

  <service name="CLICKMETER" interval="10000"     user-defined="false" status="on">      <parameter key="timeout" value="3000"/>      <parameter key="port" value="8082"/>  </service>

같은 poller-configuration.xml 파일에 모니터 정의를 삽입해야 한다. (Listing 10):

Listing 10. poller 데몬 모니터 정의

<monitor service="CLICKMETER"    class-name="org.opennms.netmgt.poller.ClickMeterMonitor" />

ClickMeter 서비스로 OpenNMS 테스트하기
소스에서 두 개의 플러그인을 구현하려면 compile.bat 파일을 사용한다. 몇몇 OpenNMS 라이브러리 파일을 <article code distribution>/lib 디렉토리에 복사해야 할 것이다. compile.bat 파일은 dwClickMeterJMX.jar를 만든다. 이 결과 JAR 파일을 <OpenNMS installation directory>/lib 디렉토리에 놓으면 OpenNMS는 시작할 때 자동적으로 새로운 플러그인을 로딩하게 된다.

반드시 OpenNMS의 웹 기반 GUI에 액세스하여 시스템을 시작하라. 일반적인 URL은 다음과 같다:

http://<host of OpenNMS>:8080/opennms/

프롬프트되면 userid에는 admin을 패스워드에는 admin을 사용한다. (그림 5):

그림 5. OpenNMS 시작 스크린
Figure 5. OpenNMS startup screen

OpenNMS가 시작하는 동안 두번이나 빠르게 증가하는 ClickMeter 카운트를 보게된다. ClickMeter는 pollerd가 작동할 때 보통 10초 간격으로 증가한다.

일단 capsd가 ClickMeter 애플리케이션을 탐지하면 이를 관리 서비스로서 RDBMS에 추가 할 것이다. 제품의 경우 OpenNMS의 자산 관리 기능들은 이 서비스를 보다 자세히 범주화 해 놓을 수 있다. 우리 실험에서는 OpenNMS GUI를 사용하여 ClickMeter 서비스를 연구하고 이에 개입된 자세한 이벤트를 볼 수 있다.(그림 6):

그림 6. ClickMeter 서비스를 관리하는 OpenNMS
Figure 6. OpenNMS managing ClickMeter service

참고자료

Posted by Tornado tornado

댓글을 달아 주세요