Elasticsearch node 종류와 기본 설정 옵션

Elasticsearch의 노드 

Elasticsearch의 인스턴스를 시작하는 동시에 노드도 같이 시작된다. 노드들을 연결해놓은 것을 클러스터라고 한다.

만약 하나의 엘라스틱 서치 노드만을 실행시킨 경우도 하나의 노드를 가진 클러스터라고 한다. 

클러스터안에서 모든 노드는 HTTP와 Transport 트래픽을 기본적으로 다룬다. Transport 레이어는 오로지 노드들과 Java TransportClient와의 통신에만 사용된다. Http 레이어는 오직 외부 Rest Cliente들과 통신할 때 사용된다.

모든 노드는 클러스터 안에서 서로 다른 노드들에 대하여 알고 있고 client에 요청을 적적한 노드로 향하게 조절해준다. 기본적으로 노드는 master-eligible, data, ingest, machine learning이 존대한다.

 

Elasticsearch의 노드 종류

Master-eligible 노드

- node.master를 true로 지정하며 클러스터의 컨트롤을 통해 마스터 노드로 선택될 자격을 가지게 된다.

- 마스터 노드는 클러스터에서 인덱스를 만들고 지우는 행위, 클러스터에서 노드들을 트래킹하고 각각의 노드를 샤드를 할당할건지 결정한다.

- Masger Eligible Node등에서 마스터 노드는 마스터 설출 프로세스를 통해 선출된다.

(https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-discovery.html)

- 마스터 노드는 데이터 노드처럼 데이터와 폴더에 접근 권한이 있어야 한다. 노드가 재시작 하는 사이에도 클러스터 상태가 유지되어야 하기 때문에 접근이 가능해야 한다.

- 데이터를 인덱싱하고 찾고 하는 작업은 CPU, Memory, I/O 자원을 많이 사용하기 때문에 큰 규모에서는 data node와 master node를 구별한다.

- 마스터 노드도 Coordinating Node 처럼 데이터를 routing하고 모으고 하는 작업이 가능하지만 이는 마스터 노드가 하는 주 목적이 아니다. 안정적인 마스터 노드를 운영하기 위해서는 자기 일만 딱 하게 해주는 것이 좋다.

- 마스터 노드로 노드를 지정하기 위한 기본 설정 값은 다음과 같다.

node.master: true 
node.data: false 
node.ingest: false 
node.ml: false 
xpack.ml.enabled: true 
cluster.remote.connect: false

 

Data 노드

- node.data가 true로 지정된 노드는 데이터를 가지고 있을 수 있고 CRUD, 검색, aggregation 등의 데이터와 관련된 작업이 가능하다.

- 데이터 노드는 인덱싱 된 Document를 포함하고 있는 샤드를 관리한다.

- 데이터 노드는 데이터를 직접적으로 다루기 때문에 리소스 자원이 많이 필요하다.

- 데이터 노드로 노드를 지정하기 위한 기본 설정 값은 다음과 같다.

node.master: false 
node.data: true 
node.ingest: false 
node.ml: false 
cluster.remote.connect: false

 

Ingest 노드 

- node.ingest가 true로 지정된 노드가 Document가 인덱싱 되기 전에 변형되고 풍성하게 하기 위해서 Document를 ingest pipeline으로 적용할 수 있다.

- ingetst node는 pre processing 파이프라인을 실행하고 하나 또는 하나 이상의 ingest processor들을 모으는 작업을 한다.

- ingest를 로드하는건 무겁기 때문에 데이터나 마스터 노드에서는 node.ingest를 false로 지정하는 것이 좋다.

- 많은 리소스를 잡아먹기 때문에 ingest node는 별도로 지정하는 것이 좋다.

- ingest 노드로 노드를 지정하기 위한 기본 설정 값은 다음과 같다.

node.master: false 
node.data: false 
node.ingest: true 
node.ml: false 
cluster.remote.connect: false

 

Machine Learning 노드

- xpack.ml이 true로 지정되어 있고 node.ml이 true로 설정되어 있는 노드는 기본적으로 엘라스틱서치에서 분배하는 행위를 한다.

- 만약 머신러닝 특징을 사용하고 싶으면 적어도 클러스터 내에 하나의 머신러닝 노드가 있어야 한다.

 

Coordinating 노드

- 검색 요청과 bulk indexing과 같은 요청들은 다른 노드들의 있는 데이터를 많이 다룬다.

- 데이터가 흩어져 있는 경우 데이터가 있는 노드로 향하게 조정해준다. 각각의 데이터 노드는 요청을 자체적으로 처리하고 그것의 값을 Coordinating 노드에 전달해준다. 그럼 Coordinating 노드는 이를 모아서 하나의 데이터 형태로 정제하여 반환한다.

- 각각의 노드는 Coordinating node가 될 수 있다. 대신 node.master, node.data, node.integer가 false로 되어 있어야 한다.

- 또한 데이터를 모으고 조작하고 하는 작업이 많기 때문에 Coordinating 노드는 메모리랑 CPU에 대한 자원이 많아야 한다. 그렇기 때문에 오직 요청을 라우팅하고 검색 구절을 조절하고, bulk indexing 분배작업을 하는 노드로만 사용하는 게 좋다.

- Coordinating node는 본질적으로 로드 밸런싱 같은 역할을 한다.

- Coordinating node로 지정하기 위한 설정은 다음과 같다.

node.master: false 
node.data: false 
node.ingest: false 
node.ml: false 
cluster.remote.connect: false

 

Node Data Path Setting

path.data

- 모든 데이터와 master-eligible 노드는 샤드 그리고 인덱스, 클러스터 메타데이터가 저장되어 있는 데이터 디렉토리를 접근한다.

- path.data는 기본적으로 $ES_HOME/data로 지정되어 있지만 elasticsearch.yml을 통해서 바꿀 수 있다.

댓글()

Mybatis에서 쿼리 작성 시 부등호 사용하면 발생하는 Error 수정

web/Spring|2018. 6. 12. 13:36

Mybatis에서 사용하는 쿼리중에 < > 와 같은 부등호가 들어가게 되면 에러가 발생한다.


[에러내용]

"The content of elements must consist of well-formed character data or markup."


이를 해결하기 위해서는 부등호를 사용하는 쿼리는 

<![CDATA[ ]]>을 감싸주어야 한다.


1
2
3
4
5
6
7
8
9
10
<select id="test resulttype="dto">
<![CDATA[
SELECT
    jumin
FROM
    member
WHERE 
    id > 1
]]>
</select>
cs


댓글()

Stack을 이용한 문장 완성도 판별 프로그램

IT 지식/자료구조|2018. 5. 27. 21:05

개발을 진행하다보면 기본에 대해 잊어갈때가 있다.

잊지 않기위해 오늘 부터 매주 하나씩 자료구조를 이용한 문제를 풀어봐야겠다.

오늘은 Stack 첫번째 시간으로 문장의 완성도를 확인하는 프로그램을 작성하여 보자.

[제약사항]
- {[(에 대한 괄호들이 정상적으로 닫혀있어야 한다.
- 주석 //, /* 안에 포함된 내용은 무시한다.
- "" double quote에 들어있는 내용을 무시한다.

간단한 프로그램이라 설명은 생략한다.



- Text를 읽고 판별을 진행하는 Main 클래스



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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package practice1;
 
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
 
public class Main {
    
    public static void main(String[] args) {
        List<String> fileList = Arrays.asList("practice1_file/paren1.txt""practice1_file/paren2.txt""practice1_file/paren3.txt");
        List<String> readText = new ArrayList<>();
        
        for (String file : fileList) {
            readText(file, readText);
            System.out.println(file + " : " + checkSentence(readText));
            readText.clear();
        }
        
    }
    
    /**
     * @param readText
     * @return
     */
    public static boolean checkSentence(List<String> readText) {
        Stack<BracketType> brackets = new Stack<>();
        boolean isMultiComment = false;
        boolean isDoubleQuote = false;
        
        for (String str : readText) {
            int oneLineCommentIndex = str.indexOf("//");
            
            // line 주석 체크
            if (oneLineCommentIndex > 0) {
                str = str.substring(0, oneLineCommentIndex);
            } else if (oneLineCommentIndex == 0) {
                continue;
            }
            
            for (int i = 0; i < str.length(); i++) {
                char c = str.charAt(i);
                
                // 멀티 라인 주석일 경우
                if (isMultiComment) {
                    if ( c == '*' && i + 1 < str.length() && str.charAt(i + 1== '/' ) {
                        isMultiComment = false;
                        i += 1;
                    } else {
                        continue;
                    }
                }
                
                // " 시작인 경우
                if (isDoubleQuote) {
                    if ( c == '"' ) {
                        isDoubleQuote = false;
                        continue;
                    } else {
                        continue;
                    }
                }
                
                // ", /*
                if (c == '"') {
                    isDoubleQuote = true;
                    continue;
                } else if ( c == '/' && i + 1 < str.length() && str.charAt(i + 1== '*' ) {
                    isMultiComment = true;
                    continue;
                }
                 
                // 괄호 체크
                BracketType type = BracketType.getType(c);
                
                if (type != null) {
                    if (!brackets.isEmpty() && brackets.peek().checkBracket(type)) {
                        brackets.pop();
                    } else {
                        brackets.push(type);
                    }
                }
            }
        }
        
        return brackets.isEmpty();
    }
    
    /**
     * 텍스트 읽기
     * 
     * @param fileName
     * @param list
     * @throws IOException
     */
    public static void readText(String fileName, List<String> list) {
        try (FileChannel fileChannel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ)) {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            
            Charset charset = Charset.defaultCharset();
            int byteCount;
            
            while (true) {
                byteCount = fileChannel.read(buffer);
                
                if (byteCount == -1)
                    break;
                
                buffer.flip();
                String line = charset.decode(buffer).toString().trim();
                
                if (null == line || line.length() == 0) {
                    continue;
                }
                
                list.add(line);
                buffer.clear();
            }
            fileChannel.close();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
    
}
cs





- 괄호에 대한 종류를 담고 있는 Enum 클래스
- 각 괄호를 나타내는 Enum 객체마다 괄호가 정상적으로 닫히는지 여부를 체크하는 메소드가 재정의 되어있음



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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package practice1;
 
/**
 * 문장의 괄호 종류와 체크로직
 * 
 * @author wedul
 *
 */
public enum BracketType implements CheckBracketI {
    BIG_RIGHT_BRACKET('}') {
        @Override
        public boolean checkBracket(BracketType type) {
            return false;
        }
    },
    SMALL_RIGHT_BRACKET(')') {
        @Override
        public boolean checkBracket(BracketType type) {
            return false;
        }
    },
    SMALL_LEFT_BRACKET('(') {
        @Override
        public boolean checkBracket(BracketType type) {
            return type.equals(SMALL_RIGHT_BRACKET);
        }
    },
    BIG_LEFT_BRACKET('{') {
        @Override
        public boolean checkBracket(BracketType type) {
            return type.equals(BIG_RIGHT_BRACKET);
        }
    },
    MIDDLE_LEFT_BRACKET('[') {
        @Override
        public boolean checkBracket(BracketType type) {
            return type.equals(MIDDLE_RIGHT_BRACKET);
        }
    },
    MIDDLE_RIGHT_BRACKET(']') {
        @Override
        public boolean checkBracket(BracketType type) {
            return false;
        }
    };;
    ;
    
    private char data;
    
    private BracketType(char data) {
        this.data = data;
    }
    
    public char getData() {
        return this.data;
    }
    
    /**
     * getType
     * 
     * @param input
     * @return
     */
    public static BracketType getType(char input) {
        for (BracketType type : values()) {
            if (type.getData() == input) {
                return type;
            }
        }
        
        return null;
    }
}
cs




- enum에서 사용된 인터페이스


1
2
3
4
5
6
7
8
9
10
11
12
13
package practice1;
 
/**
 * 괄호의 종류별로 체크하는 메소드를 포함한 인터페이스
 * 
 * @author wedul
 *
 */
public interface CheckBracketI {
    
    boolean checkBracket(BracketType type);
 
}
cs



결과




테스트 파일


paren1.txt

paren2.txt

paren3.txt



댓글()

Stack - 후위 표기법으로 된 식 계산

IT 지식/자료구조|2018. 5. 27. 21:01

1 3 + 4 * 와 같이 후위 표기되어있는 식을 계산하는 프로그램을 stack을 이용해서 만들어라

주의사항
- 피연산자가 너무 많으면 오류를 발생시켜라.
- 피연산자가 적어도 오류를 발생시켜라
- 연산자가 사칙연산 이외의 것이 나오면 예외를 발생시켜라
- 결과는 소수점 둘째까지 반올림해서 표현하라.
- 예외는 이 프로그램을 위한 예외를 새로 만들어라

구성
- 파일을 읽는 메서드가 담긴 util 클래스
- 동작이 진행되는 Main 클래스
- 이 프로그램의 예외 OperatorException 클래스



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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package practice2;
 
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.List;
 
/**
 * 유틸 클래
 * 
 * @author jeongcheol
 *
 */
public class UtilClass {
    
    /**
     * 텍스트 파일을 읽어서 List에 삽입 
     * 
     * @param fileName
     * @param list
     */
    public static void readText(String fileName, List<String> list) {
        try (FileChannel fileChannel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ)) {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            
            Charset charset = Charset.defaultCharset();
            int byteCount;
            
            while (true) {
                byteCount = fileChannel.read(buffer);
                
                if (byteCount == -1)
                    break;
                
                buffer.flip();
                String line = charset.decode(buffer).toString().trim();
                
                if (null == line || line.length() == 0) {
                    continue;
                }
                
                list.addAll(Arrays.asList(line.split("\n")));
                buffer.clear();
            }
            fileChannel.close();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
 
}
 
 
package practice2;
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
 
import org.apache.commons.lang3.StringUtils;
 
public class Main {
 
    private static final List<String> fileList = Arrays.asList("file/practice1/postfix.txt"  , "file/practice1/postfix1.txt");
    private static final List<String> operator = Arrays.asList("+""-""/""*");
    private static final List<String> readText = new ArrayList<>();
    private static final Stack<String> operand = new Stack<>();
 
    public static void main(String args[]) {
        for (String file : fileList) {
            UtilClass.readText(file, readText);
            readText.stream().forEach(x -> {
                try {
                    process(x);
                } catch (OperatorException e) {
                    System.out.println(e.getMessage());
                }
            });
            readText.clear();
        }
    }
 
    /**
     * 서식 처리 
     * 
     * @param str
     * @throws OperatorException
     */
    private static void process(String str) throws OperatorException {
        // 초기
        operand.clear();
 
        // 빈 문자열 체크
        if (StringUtils.isBlank(str)) {
            return;
        }
 
        for (String ch : str.replaceAll("\\r\\n|\\r|\\n|\\n\\r""").split(" ")) {
            if (StringUtils.isNumeric(ch)) {
                operand.push(ch);
            } else if (operator.contains(ch)) {
                checkOperand();
                
                double operand2 = Double.valueOf(operand.pop());
                double operand1 = Double.valueOf(operand.pop());
                
                switch (ch) {
                case "+":
                    operand.push(String.valueOf(operand1 + operand2));
                    break;
 
                case "-":
                    operand.push(String.valueOf(operand1 - operand2));
                    break;
 
                case "*":
                    operand.push(String.valueOf(operand1 * operand2));
                    break;
 
                case "/":
                    operand.push(String.valueOf(operand1 / operand2));
                    break;
                    
                default:
                    throw new OperatorException("An unsupported operator.\n");
                }
            } else {
                throw new OperatorException(ch + " operator is unsupported operator.\n");
            }
        } 
        
        // 결과 확인
        checkResult();
        
        System.out.printf(" = %.2f\n" ,Double.valueOf(operand.peek()));
        System.out.println();
    }
    
    /**
     * 계산 전 피연산자 개수 체크 
     * 
     * @throws OperatorException
     */
    private static void checkOperand() throws OperatorException {
        if (operand.isEmpty() || operand.size() < 2) {
            throw new OperatorException("Not enough operand.\n");
        }
    }
    
    /**
     * 계산 후 피연산자 개수 체크 
     * 
     * @throws OperatorException
     */
    private static void checkResult() throws OperatorException {
        if (operand.size() != 1) {
            throw new OperatorException("Too many operand.\n");
        }
    }
    
 
}
 
 
package practice2;
 
/**
 * 연산 입센션 추가 
 * 
 * @author jeongcheol
 *
 */
public class OperatorException extends Exception {
 
    private static final long serialVersionUID = 1L;
    
    public OperatorException(String errMsg) {
        super(errMsg);
    }
 
}
cs



결과




postfix.txt

postfix1.txt




댓글()