# Http 상태 코드

 

내가 자주 보았던 Http 응답 코드는 404, 500, 200, 등등이었는데 앞자리에 따라서 의미가 다르다. 잘 몰랐지만 이번에 정리를 해보자

 

http 응답 상태는 3자리 숫자로 나타낸다.

 

첫번째 숫자는 응답의 클래스(분류)로 구분된다.

마지막 두 자리는 클래스나 분류 역할을 하지는 않지만 분류에 따라 다양하다.



| 앞 번호 | 의미 |

|-|-|

|1 (조건부 응답)| 요청을 받았으며, 프로세스를 계속 한다.|

|2 (성공)| 요청을 성공적으로 받았으며, 인식했고 수용하였다. |

|3 (리다이렉션 완료)| 요청완료를 위해 추가 작업 조치가 필요함|

|4 (요청 오류)| 요청의 문법이 잘못됬거나 요청을 처리 할 수 없다.|

|5 (서버 오류)| 서버가 명백히 유효한 요청에 대해 충족을 실패 했다.|

 

**예시**

100 : 요청자는 요청을 계속 한다. 서버는 이 코드를 제공하여 요청의 첫번째 부분을 받았으며 나머지를 기다리고 있음을 나타냄.

101 : 요청자가 서버에 프로토콜을 전환을 요청했고, 서버는 이를 승인하는 중.

 

200 : 서버가 요청을 제대로 처리 했다.

201 : 성공적으로 요청되었으며 서버가 새로운 리소스를 작성함

202 : 서버가 요청을 접수는 했는데, 아직 처리가 되지 않음

204 : 콘텐츠 없음, 서버가 요청을 성공적으로 처리 했지만 콘텐츠를 제공하지 않음

205 : 서버가 요청을 성공적으로 처리 했지만, 콘텐츠를 표시하지 않는다.

206 : 서버가 get 요청의 일부만 성공적으로 처리함

 

301 : 요청한 페이지를 새 위치로 영구적으로 이동( GET Head 요청에 대한 응답으로 이 응답을 표시하면 요청자가 자동으로 새 위치로 전달됨)

302 : 현채 서버가 다른 위치의 페이지로 요청을 응답하고 있지만, 요청자는 향후 요청시 원래 위치를 계속 사용함.

 

400 : 서버가 요청 구문을 인식하지 못할때

401 : 인증이 필요한 요청이지만, 권한이 없음, 또는 인증안됨을 뜻함

403 : forbidden 에러 : 서버가 요청을 거부!!

404 : 서버가 요청한 페이지를 찾을 수 없을 때

408 : 서버의 요청 대기가 시간을 초과 하였다.

 

500 : 서버에 오류가 발생하여 요청을 수행 할 수 없다.

501 : 서버에 요청을 수행할 수 있는 기능이 없다

502 : 서버가 게이트웨이나 프록시 역할을 하고 있거나 또는 업스트림 서버에 잘못된 응답을 받았다.

504 : 서버가 게이트웨이나 프록시 역할을 하고 있거나, 업스트림 서버에서 제때 요청을 받지 못함

...이외에도 다양한 응답 상태가 존재한다.





참고 : [Http 상태 코드 /위키백과](https://ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C)

'BackEnd > ETC' 카테고리의 다른 글

[gradle] CreateProcess error=206  (0) 2020.04.25
Git remote: Permission to  (0) 2020.03.08
CQRS란 ?  (1) 2020.01.19
STORM 정리  (0) 2017.12.18

CQRS

*Command Query Responsibility Segregation : *
명령과 쿼리의 역할을 구분한다는 의미

Command란? CURD(Create-Insert-Update, Delete)를 나타낸다.
Query란 ? Select(데이터 조회)의 책임을 분리한다는것이다.
버란트 마이어의 CQS가 CQRS의 출발이고, CQRS를 처음 소개 한 분은 Greg Young이다.

탄생
전통적인 CURD 아키텍처 기반에서 Application을 개발 및 운영 하다 보면 자연스럽게 Domain Model의 복잡도가 증가된다.
이때 유지보수에 대한 Cost는 증가되고, Domain Model은 점점 설계시 의도한 방향과는다르게 변질된다. Application Business 정책이나 제약은 거의 대 부분 데이터 변경작업에서 처리되고 Read는 단순 조회가 대부분이기 때문에, 이 두 업무를 동일한 도메인 모델로 처리하게 되면 도메인의 속성들의 복잡도가 증가하고, 설계와는 다르게 다른 방향으로 변질이 된다.

그래서 나온것이 '명령을 처리하는 책임!', '조회를 처리하는 책임!' 을 분리 구현하자! 라는 개념이 CQRS의 핵심이다.

참고 : 나만 모르고 있던 CQRS & EventSourcing
추가 자료 최신-기술-cqrs-처음-도입하기

'BackEnd > ETC' 카테고리의 다른 글

[gradle] CreateProcess error=206  (0) 2020.04.25
Git remote: Permission to  (0) 2020.03.08
http 상태 코드  (0) 2020.01.19
STORM 정리  (0) 2017.12.18

드디어 solid에 대한 개념을 정리 하게 되었다.

객체 지향의설계의 5원칙 집대성

로버트 C. 마틴이 2000년대 초반 객체 지향 프로그래밍 및 설계의 다섯가지 기본원칙으로 제시함 .

응집도(high Cohesion)는 높이고, 결합도 (Loose Coupling)는 낮추라는 고전 원칙을 객체 지향의 관점에서 재정립한 것.

결합도와 응집도
결합도는 모듈간의 상호 의존 정도로서 결합도가 낮으면 모듈간의 상호 의존성이 줄어들어 객체의 재사용이나 수정, 유지 보수가 용이하다.
응집도는 하나의 모듈내부에 존재하는 구성요소들으 ㅣ기능적 관련성으로 응집도가 높은 모듈은 하나의 책임에 집중하고 독립성이 높아져 재사용이나 기능의 수정, 유지보수가 용이하다.

객체지향 SW 설계의 원칙 ① 개방-폐쇄 원칙

객체지향 SW 설계의 원칙 ② 사례연구, 단일 책임 원칙

객체지향 SW 설계의 원칙 ③ 인터페이스 분리의 원칙

객체지향 SW 설계의 원칙 ④ 리스코프 치환 원칙

SRP (Single Responsibility Principle) 단일 책임 원칙

어떤 클래스를 변경해야하는 이유는 오직 하나 뿐이어야 한다. - 로버트 C 마틴

책에서는 여자친구, 어머니, 직장상사, 소대장 등 다양한 사람들이 의존하는 남자친구로 설명을한다.

여러 사람들이 의존하는 남자친구는 피곤할수 밖에 없다.

여자친구- 남자친구, 어머니 - 아들, 직장상사 - 사원, 소대장 - 소대원

이렇게 역할을 분리하라는 것이 단일 책임 원칙이다.

장점 :

  • 이전에는 남자친구라는 이름으로 의존되고있는 것을 관리 하였는데, 역할을 분할하니 클래스 이름도 이해하기가 좋다.
  • 여자친구와 이별을 하더라도 어머니-아들, 직장상사- 사원, 소대장 - 소대원 에게는 영향을 받지 않는다.
  • 단일 책임 원칙은 속성, 메서드, 패키지, 모듈, 컴포넌트, 프레임워크 등에도 적요할 수 있는 개념이다.

잘못된 예

예시1) 남자와 여자를 사람으로 나타내는 클래스가 있다. 남자는 군대를 가야해서 사람이라는 클래스에 군번이라는 필드를 넣게 된다면? 여자는 군대를 가지 않지만 군번이라는 필드 에 값은 할당되지 않아도 계속 가지고 있어야하는 찜찜함이 있다.

이럴때는 남자, 여자가 공통적인 부분들을 사람이라는 클래스에 두고 남자, 여자 클래스에서 상속을 받아, 차이점을 구현하면 해결할수 있다.

OCP(Open Closed Principle) 개방 폐쇄 원칙

소프트 웨어 인티티(클래스, 모듈, 함수) 등 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야한다 - 로버트 c 마틴

자신의 확장에는 열려있고, 주변의 변화에 대해서는 닫혀 있어야한다

예제

한 운전자가 수동의 마티즈를 운전할때 창문 수동 개방, 기어 수동 조작에 대한 메서드를 사용 했는데, 나중에 쏘나타로 차를 변경하게 되면서 창문 수동 개방, 기어 자동 조작 에 대한 메서드를 사용하게 된다면 ?

운전자가 운전에 영향을 받아야하는가?를 물어보면서 상위 클래스 또는 인터페이스를 중간에 둠으로써, 다양한 자동차가 생긴다고 해도 객체 지향 세계의 운전습관에는 영향을 받지 않게 된다.

자동차가 생긴다고 하는것은 자동차 입장에서는 자신의 확장에 개방이 되어있고, 운전자입장에서는 주변의 변화에 폐쇄 되어있는 것이다.

또 다른 예를 들면, JDBC를 사용하는 클라이언트는 데이터베이스가 오라클에서 MySQL 로 바뀌더라도 Connection을 설정 하는 부분외에는 따로 수정하는 부분이 없다. 데이터베이스는 교체가 가능하므로 확장에 개방이 되어있고, 자바 애플리케이션은 데이터베이스라고 하는 주변의 변화에 닫혀 있다는 말이다.

LSP (Liskov Substitution Principle) 리스코프 치환 원칙

서브 타입은 언제나 자신의 기반 타입(base type) 으로 교체 할 수 있어야한다. - 로버트 c 마틴

상속은 조직도나 계층도가 아닌 분류도가 되어야한다!

  • 하위 클래스 is a kind of 상위 클래스 - 하위 분류는 상위 분류의 한 종류이다.

  • 구현 클래스 is able to 인터페이스 - 구현분류는 인터페이스 할 수 있어야 한다.

    인터페이스 할수 있어야한다라는 표현은 각 인터페이스 명에 따라 쉽게 이해할 수 있다.
    AutoCloseable - 자동으로 닫힐 수 있어야한다.
    Appendable - 덧붙일 수 있어야한다.
    Cloneable - 복제할 수 있어야한다.
    Runnable - 실행 할 수 있어야한다.

상위 클래스의 객체 참조 변수에는 하위 클래스의 인스턴스를 할당할 수 있다.

부모 자식관계의 잘못된 예를 보면

아버지 춘향이 = new 딸();

춘향이는 아버지형의 객체 참조변수 이기에 아버지객체가 가진 행위를 할 수 있어야하는데, 딸인 춘향이는 아버지의 역할을 할수가 없다.

아래와 같은 경우에는 동물 - 펭귄 구조(분류도)는 리스코프 치환 원칙을 만족 한다라고 할 수 있다.

동물 뽀로로 = new 펭귄();

정리하면 하위 클래스의 인스턴스는 상위형 객체 참조 변수에 대입해 상위 클래스의 인스턴스 역할을 하는데 문제가 없어야한다.

계층도/조직도 경우가 아니라, 분류도인 경우 하위에 존재하는 것들은 상위에 있는 것들의 역할을 하는데 전혀문제가 없다.

ISP (Interface Segregation Principle) 인터페이스 분리 원칙

클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다. - 로버트 C. 마틴

이전의 SRP를 설명할때 남자친구는 여자친구, 어머니, 직장상사, 소대장이 의존하고있는 남자친구에 대해 역할을 분리하는것이 좋다고 이야기를 했는데, 다른 방법으로는 ISP를 사용하여 나타낼 수 있다.

여자친구, 어머니, 직장상사, 소대장이 의존하고있는 남자친구의 역할의 메서드를 포함하는 인터페이스를 생성하고, 남자친구를 implements 해서 각 역할에 맞는 클래스를 생성하는것이 인터페이스 분할 원칙의 핵심이다.

인터페이스에 메서드를 정의하고,정의된 메서드들을 각 개별의 객체의 클래스에스 구현하는 것 이 핵심이라고 생각함

결론적으로 SRP, ISP는 같은 문제에 대한 두가지 다른 해결책이라고 볼수 있다.

프로젝트의 요구사항과 설계자의 취향에 따라 단일 책임 원칙이나 인터페이스분할 원칙중 하나를 선택해서 설계할 수 있다.

상위 클래스는 풍성할 수록 좋고, 인터페이스는 작을 수록 좋다.

DIP (Dependency Inversion Principle) 의존 역전 원칙

"고차원 모듈은 저차원 모듈에 의존하면 안된다. 이 두 모듈 모두 다른 추상화 된 것에 의존해야 한다.","추상화된 것은 구체적인 것에 의존하면 안된다. 구체적인 것이 추상화된 것에 의존해야한다."," 자주 변경되는 구체(Concrete) 클래스에 의존하지 마라" - 로버트 마틴

자동차 타이어에는 여러 종류가 있다. 스노우 타이어, 일반 타이어, 광폭타이어

자동차 타이어가 교체 될때마다 타이어클래스들을 변경 해야하지만, 상위에 인터페이스로 타이어라는 추상 객체를 만들어 상속하여 사용한다면, 타이어가 변경되도

자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어번 하기쉬운 것의 변화에 영향 받지 않게 하는것이 의존 역전의 원칙

상위 클래스일 수록 인터페이스일수록, 추상클래스일수록 변하지 않는 가능성이 높기에 하위 클래스나 구체 클래스가 아닌 상위 클래스, 인터페이스, 추상클래스를 통해 의존하라는것이 바로 의존 역전의 원칙

'ProgramLanguage > Java' 카테고리의 다른 글

JVM 튜닝  (0) 2020.02.10
Lambda_Expression(2)  (0) 2020.01.25
Java 와 객체 지향  (0) 2019.12.03
Java jar파일 만들기  (0) 2019.08.04
인터페이스와 추상클래스  (0) 2019.06.10

yum Repository 만들기

  1. 이전 (1) 에서 미리 R설치에 대한 rpm 파일을 모두 다운 받았뒀다. 기본의 yum들을 백업 함

    $cd /etc/yum.repos.d
    //root 계정 로그인
    #su
    //백업 폴더 생성
    #mkdir bak
    // /etc/yum.repos.d/ 하위 repository, bak 폴더로 이동
    #mv . bak
    #ls
    bak

  2. 다운받았던 rpm 디렉토리(/home/morriskim/data/rpm)를 repository파일로 등록

vi /etc/yum.repos.d/morris.repo

[rpm]
name=morrisRepository
baseurl=file:///home/pduser/data/rpm
enabled=1
gpgcheck=0
  1. createRepository

    #createrepo /home/pduser/data/rpm

  2. yum repo 리스트 확인

이전의 PuzzleRepository 가 있는 지 확인

# yum repolist
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
rpm                                                                                           | 2.9 kB  00:00:00
rpm/primary_db                                                                                | 247 kB  00:00:00
repo id                                            repo name                                                   status
rpm                                                morrisRepository                                            268
  1. yum 을 통한 설치

    $sudo yum install R

참고

local repository 만들기

'BackEnd > Linux' 카테고리의 다른 글

awk 사용하기  (0) 2020.03.02
Yum Repository 만들기 (1)  (0) 2019.12.23
[Linux]NoLogin  (0) 2019.10.08
Swap 메모리 늘리기  (0) 2019.09.17
cache 삭제하기  (0) 2019.08.27

내부 인터넷을 사용하는 곳에서는 다양한 yum install 에 있어서 설치가 불가능 할경우가 많다. 그래서 offline 으로 미리 다운을 받아가야한다. 그래서 local yum repository를 생성해 가기로 했다.

curl 이나 wget 으로 rpm 을 다운받아서할수 있지만 패키지 의 의존성을 각자 개별적으로 다운을 받아야한다 이럴때 함께 다운받으려면 ?

rpm 다운로드 하기

쉽게 다운로드 하려면 다음과 두 가지 메서드를 이용하면 패키지를 동시에 다운받을 수 있다.

  1. downloadonly

    $sudo yum install yum-plugin-downloadonly

    $sudo yum install --downloadonly

위의 명령어를 사용하면 default location 으로 /var/cache/yum/ rhel-{arch}-channel/packages 에 다운로드된다.

지정된 위치를 사용하려면

$sudo yum install --downloadonly --downloaddir=<directory> <package-name>
  1. yumdownloader

    $sudo yum install yum-utils

    // 단일 패키지만 다운로드
    $sudo yumdownloader

    // 의존성 rpm 들이 한꺼번에 다운로드됨
    $sudo yumdownloader --resolve

    //위치 지정해서 패키지 다운로드
    $sudo yumdownloader --resolve --destdir=
    $sudo yumdownloader --resolve --destdir

참고

How to Download A RPM Package with All Dependencies In CentOS

'BackEnd > Linux' 카테고리의 다른 글

awk 사용하기  (0) 2020.03.02
Yum Repository 만들기 (2)  (0) 2019.12.24
[Linux]NoLogin  (0) 2019.10.08
Swap 메모리 늘리기  (0) 2019.09.17
cache 삭제하기  (0) 2019.08.27

개인적인 테스트를 진행한 결과를 정리한 개인의 생각이므로, 제가 잘못알고 있는 것이면 댓글 달아주세요.

index segments _max count = 1 ?

인덱스를 고정하기 전에 먼저 force_merge를 실행하는 것이 좋습니다. 그러면 샤드별로 디스크에 하나의 세그먼트만 있게 됩니다. 또한, 압축률이 훨씬 향상되고, 고정 인덱스에 대해 집계 또는 정렬된 검색 요청을 실행할 때 필요한 데이터 구조가 간소화됩니다. 여러 세그먼트가 있는 고정 인덱스에 대한 검색을 실행하면 최대 수백 배의 성능 오버헤드가 발생할 수 있습니다.

POST /sampledata/_forcemerge?max_num_segments=1

https://www.elastic.co/kr/blog/creating-frozen-indices-with-the-elasticsearch-freeze-index-api

실습

기존 인덱스의 segments 의 수를 보자

아래를 보면 하나의 샤드당 segments 카운트는 8개로 나뉘어져있다.

이것을 하나의 세그먼트로 force merge를 해보자

$car_wash/_forcemerge?max_num_segments=1

해보기전

$curl -X GET "localhost:9200/car_wash/_segments?verbose=true&pretty" > car_wash_segments_default

Max_segments 크기 변경

$curl -X POST "localhost:9200/car_wash/_forcemerge/?max_num_segments=1&pretty"

{
  "_shards" : {
    "total" : 10,
    "successful" : 5,
    "failed" : 0
  }
}

변경 후 force merge

$curl -X GET "localhost:9200/car_wash/_segments?verbose=true&pretty" > car_wash_segments_forcemerge

car_wash_segments_default 와 car_was_segments_forcemenrge 두개의 파일을 비교 해보자

car_wash_segments_default는 한 샤드당 9개의 세그먼트로 각 세그먼트당 "memory_in_bytes" 의 값을 더해보았다.

값을 다 더해보면 61158 의 값이 나왔고,

"_shards" : {
    3     "total" : 10,
    4     "successful" : 5,
    5     "failed" : 0
    6   },
    7   "indices" : {
    8     "car_wash" : {
    9       "shards" : {
   10         "0" : [
   11           {
   12             "routing" : {
   13               "state" : "STARTED",
   14               "primary" : true,
   15               "node" : "uCyuJNg-TVu3E7g7nzRAZw"
   16             },
   17             "num_committed_segments" : 9,
   18             "num_search_segments" : 9,
   19             "segments" : {
   20               "_0" : {
   21                 "generation" : 0,
   22                 "num_docs" : 25,
   23                 "deleted_docs" : 0,
   24                 "size_in_bytes" : 23400,
   25                 "memory_in_bytes" : 6033,
   26                 "committed" : true,
   27                 "search" : true,
   28                 "version" : "7.5.0",
   29                 "compound" : true,
   30                 "ram_tree" : [
   31                   {
   32                     "description" : "postings [PerFieldPostings(segment=_0 formats=1)]",
   33                     "size_in_bytes" : 4794,
   34                     "children" : [
   35                       {
   36                         "description" : "format 'Lucene50_0' [BlockTreeTermsReader(fields=21,delegate=Lucene50Po      stingsReader(positions=true,payloads=false))]",
   37                         "size_in_bytes" : 4594,
   ....

car_was_segments_forcemenrge 의 segments의 갯수는 하나이고,

memory_in_bytes 의 값은 12268로 메모리가 줄어든 것을 확인할 수 있었다.

7   "indices" : {
   8     "car_wash" : {
   9       "shards" : {
  10         "0" : [
  11           {
  12             "routing" : {
  13               "state" : "STARTED",
  14               "primary" : true,
  15               "node" : "uCyuJNg-TVu3E7g7nzRAZw"
  16             },
  17             "num_committed_segments" : 1,
  18             "num_search_segments" : 1,
  19             "segments" : {
  20               "_9" : {
  21                 "generation" : 9,
  22                 "num_docs" : 2774,
  23                 "deleted_docs" : 0,
  24                 "size_in_bytes" : 1128655,
  25                 "memory_in_bytes" : 12268,
  26                 "committed" : true,
  27                 "search" : true,
  28                 "version" : "7.5.0",
  29                 "compound" : false,
  30                 "ram_tree" : [
  31                   {
  32                     "description" : "postings [PerFieldPostings(segment=_9 formats=1)]",
  33                     "size_in_bytes" : 11073,
  34                     "children" : [
  35                       {
  36                         "description" : "format 'Lucene50_0' [BlockTreeTermsReader(fields=21,delegate=Lucene50Pos     tingsReader(positions=true,payloads=false))]",
  37                         "size_in_bytes" : 10873,

일반적인 샤드의 segments의 크기는 61158

forcemerge 한 세그먼트의 메모리 byte 크기12268

Force merge 의 세그먼트의 메모리가 확 줄어든것을 볼수 있다.

세그먼트의 verbose로 살펴본 결과 segments.compound 의 값이 변경된것을 알수 있다. 무엇을 의미 하는것일까 ?

compound
    (Boolean) If true, Lucene merged all files from the segment into a single file to save file descriptors.

왜 그런것일까 ??

https://discuss.elastic.co/t/what-is-in-segments-memory/61651

indices.segments.terms_memory_in_bytes ??

역인덱싱 으로 되어있어서, segments로 나뉘어있어서, 하나로 합쳐지니까 메모리가 줄여지는거 아닐까??

아래의 내용들은 답을 이해 하기 위해 찾다가 참고가 된 문서인데 확실하지는 않지만, segments 에서 Terms 이 동일한것이 많아서 줄어들거나,

참고

Lucene Merge 설명

https://juanggrande.wordpress.com/2011/02/07/merge-policy-internals/

Maybe in your case some segments shares same terms or something else that duplicates in memory but belongs to different segments. After segment reduction same terms merged and so you have a little gain in memory. But it just my guess.

https://discuss.elastic.co/t/segments-memory-in-bytes-goes-down-after-reduction-of-segments-restart/41258/7

In my case, after merging segments into 1 segment using force merge 46, segments.terms_memory was decreased by 30%. (note that this percentage depends on your index characteristics)

I hope segment merging help you prevent adding more nodes (or resources, or money).

https://discuss.elastic.co/t/reducing-heap-usage-dedicated-to-indices-segments-terms-memory-in-bytes/68899

생각과 추측이 맞는지 테스트 해보기segments의 크기를 1로 테스트 해보기

조건 : 같은 데이터를 사용해서 segments가 여러개일때와 segments를 하나로 합쳤을때의 결과를 비교해봤다.

아래는 테스트 내용이다.

##인덱스 생성
PUT segments_test
##세그먼트 확인
GET segments_test/_segments



##데이터 삽입 X 3번 
POST segments_test/_doc
{
  "name":"cup",
  "text" : "the bowllike part of a goblet or the like."
}

3번의 데이터를 삽입한 결과 1번 샤드에 두개의 도큐먼트가 삽입된것을 알수 있다. 같은 도큐먼트 이지만, 메모리는 각 세그먼트 마다 가지고 있다.

{
  "_shards" : {
    "total" : 10,
    "successful" : 5,
    "failed" : 0
  },
  "indices" : {
    "segments_test" : {
      "shards" : {
        "0" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 0,
            "num_search_segments" : 0,
            "segments" : { }
          }
        ],
        "1" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 0,
            "num_search_segments" : 2,
            "segments" : {
              "_0" : {
                "generation" : 0,
                "num_docs" : 1,
                "deleted_docs" : 0,
                "size_in_bytes" : 4092,
                "memory_in_bytes" : 1698,
                "committed" : false,
                "search" : true,
                "version" : "7.5.0",
                "compound" : true,
                "attributes" : {
                  "Lucene50StoredFieldsFormat.mode" : "BEST_SPEED"
                }
              },
              "_1" : {
                "generation" : 1,
                "num_docs" : 1,
                "deleted_docs" : 0,
                "size_in_bytes" : 4092,
                "memory_in_bytes" : 1698,
                "committed" : false,
                "search" : true,
                "version" : "7.5.0",
                "compound" : true,
                "attributes" : {
                  "Lucene50StoredFieldsFormat.mode" : "BEST_SPEED"
                }
              }
            }
          }
        ],
        "2" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 0,
            "num_search_segments" : 1,
            "segments" : {
              "_0" : {
                "generation" : 0,
                "num_docs" : 1,
                "deleted_docs" : 0,
                "size_in_bytes" : 4092,
                "memory_in_bytes" : 1698,
                "committed" : false,
                "search" : true,
                "version" : "7.5.0",
                "compound" : true,
                "attributes" : {
                  "Lucene50StoredFieldsFormat.mode" : "BEST_SPEED"
                }
              }
            }
          }
        ],
        "3" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 0,
            "num_search_segments" : 0,
            "segments" : { }
          }
        ],
        "4" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 0,
            "num_search_segments" : 0,
            "segments" : { }
          }
        ]
      }
    }
  }
}

여기서 segments 의 크기를 병합 후에 확인 한다면?

POST segments_test/_forcemerge/?max_num_segments=1

GET segments_test/_segments

아래의 결과대로 1번의 샤드의 사용되는 메모리는 1698 바이트 의 두배가 되어야한다고 생각했지만, 메모리의 사용량은 1698 바이트 그대로 인것을 보면 segments의 term이 중복되는 경우에는 메모리의 양이 줄어든 것을 알수 있다.

{
  "_shards" : {
    "total" : 10,
    "successful" : 5,
    "failed" : 0
  },
  "indices" : {
    "segments_test" : {
      "shards" : {
        "0" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 0,
            "num_search_segments" : 0,
            "segments" : { }
          }
        ],
        "1" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 1,
            "num_search_segments" : 1,
            "segments" : {
              "_2" : {
                "generation" : 2,
                "num_docs" : 2,
                "deleted_docs" : 0,
                "size_in_bytes" : 4165,
                "memory_in_bytes" : 1698,
                "committed" : true,
                "search" : true,
                "version" : "7.5.0",
                "compound" : false,
                "attributes" : {
                  "Lucene50StoredFieldsFormat.mode" : "BEST_SPEED"
                }
              }
            }
          }
        ],
        "2" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 1,
            "num_search_segments" : 1,
            "segments" : {
              "_0" : {
                "generation" : 0,
                "num_docs" : 1,
                "deleted_docs" : 0,
                "size_in_bytes" : 4092,
                "memory_in_bytes" : 1698,
                "committed" : true,
                "search" : true,
                "version" : "7.5.0",
                "compound" : true,
                "attributes" : {
                  "Lucene50StoredFieldsFormat.mode" : "BEST_SPEED"
                }
              }
            }
          }
        ],
        "3" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 0,
            "num_search_segments" : 0,
            "segments" : { }
          }
        ],
        "4" : [
          {
            "routing" : {
              "state" : "STARTED",
              "primary" : true,
              "node" : "uCyuJNg-TVu3E7g7nzRAZw"
            },
            "num_committed_segments" : 0,
            "num_search_segments" : 0,
            "segments" : { }
          }
        ]
      }
    }
  }
}

객체지향 책을 보고 정리 하는중입니다.

객체 지향은 인간 지향이다.

기계 종속적인 개발이 아니라 우리가 눈으로 보고 느끼고, 생활하는 현실 세계처럼 프로그래밍 할 수는 없을까? 라는 고민 속에서 객체 지향의 개념이 탄생했다.

함수로 인해 프로그래밍이 조금 편해지고 더욱 파격적인 제안이 나옴, 그게 바로 객체 지향이다.

객체 지향은 직관적이고 쉽고, 인간적이다는 증거를 이제부터 하나씩 알아보자

객체 지향의 4대 특성 - 캡! 상추다

캡 - Encapsulation, : 정보 은닉

상 - 상속(Inherit) : 재사용

추 - 추상화 (Abstraction): 모델링

다 - 다형성 (Polymorphism): 사용 편의

객체 지향에 대한 질문

  • 사람의 나이는 몇 살인가?

  • 김연아의 나이는 몇 살 인가?

  • 뽀로로의 나이는 몇 살인가?

  • 펭귄의 나이는 몇 살인가?

클레스: 객체 = 사람: 김연아 = 펭귄 : 뽀로로

추상화

추상 : 여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용

공통 특성 / 공통 속성 추출

객체 지향의 추상화는 곧 모델링이다 라는 관점을 살펴보자

객체 지향의 4대 특성들은 클래스를 통해 구현된다.

객체는 세상에 존재하는 유일무이한 사물로 해석을 하고, 클래스는 분류, 집합. 같은 속성과 기능을 가진 객체를 총칭하는 개념 이라고 하면

사람 morris = new 사람();class Person {
String name;
int age;
int numberOfLeg ;
public void eat(){
System.out.println("냠냠");
}
}

public class ObjectMain{

public static void main( String []args){
Person morris = new Person();
morris.name = "Kim Morris";
morris.age = 29;
morris.numberOfLeg = 2;
}
}

참고할점은 사람의 다리는 전부 2개 이기 때문에, heap에 메모리를 줄여주기 위해서 static으로 변경하여 Static 영역에 배치 하게 하면 더 좋은 효과를얻을수 있다.

새로운 인스턴스(객체)를 생성하게 되면 또다른 참조변수를 만들고 heap에 Person 클래스를 다시 힙에 배치

자바에서는 포인터가 객체 참조변수에 할당된다는 사실 !!

Heap : Person의 인스턴스를 하나 만들어 heap에 배치 한다.

Stack : Person 객체에 대한 참조 변수 morris를 만든다.

Static : Person class의 String name, int age, int numberOfLeg, eat() 클래스가 전부 스태틱 영역에 배치 됨

아래와 같이 Person 클래스가 있을 경우, 객체를 생성하게 되면 메모리의 구조는 아래와 같다.

메모리는 ??

자바는 객체 지향의 추상화를 어떻게 지원을 할까? 바로 class 키워드를 통해 지원한다.

  • 상속을 통한 추상화, 구체화

  • 인터페이스를 통한 추상화

  • 다형성을 통한 추상화

추상화의 개념을 넓게 본다면 아래 내용도 포함된다.

  • OOP의 추상화는 모델링이다.

  • 클래스 : 객체 = 펭귄 : 펭수

  • 클래스 설계에서 추상화가 사용된다.

  • 클래스 설계를 위해서는 애플리케이션의 경계부터 정해야한다.

  • 객체지향에서 추상화의 결과는 클래스이다.

추상화에 대한 핵심을 다시 정리 해보면

추상화란 구체적인 것을 분해해서 관심 영역에 있는 특성만 가지고 재조합하는 것 => 모델링

추상화란 구체적인 것을 분해해서 관심 영역에 대한 특성만 가지고 재조합하는 것

추상화의 일반적인 뜻을 다시 살펴 보면

병원에 대한 애플리케이션이면 병원에는 환자라는 구체적인 사람으로 바꿀 수 있고, 설계도 달라질 것이다.

이럴때 내가 만들고자하는 애플리케이션은 어디에서 사용될 것인가? 를 질문을 하면된다.

여기서 애플리케이션 경계라는 것이 나오는데, 애플리케이션 경계를 Context라고 부르기도한다.

사람에 대한 클레스에 대해 공통적인 특성들을 나열하다보면 끝이 없다.

'ProgramLanguage > Java' 카테고리의 다른 글

Lambda_Expression(2)  (0) 2020.01.25
객체 지향 설계 5원칙 - SOLID  (0) 2019.12.26
Java jar파일 만들기  (0) 2019.08.04
인터페이스와 추상클래스  (0) 2019.06.10
람다 식 Lambda Expression (1)  (0) 2019.06.09

주변 세차장 찾기 (2)

현재 위치를 중심으로 쿼리 만들기

현재 위치는 다양한맵의 주소에서 찾을수 있다.

구글 맵에서 검색을 하게 되면 쿼리 파라미터에 위도경도가 나오는것을 알수 있다.

https://www.google.co.kr/maps/place/%EC%8B%A0%EB%8F%84%EB%A6%BC%EC%97%AD/@37.5088099,126.8890174,17z/data=!3m1!4b1!4m5!3m4!1s0x357c9e5dbb76b179:0x2f88a2d1152886e2!8m2!3d37.5088099!4d126.8912061?hl=ko

위도 경도를 찾아서 다음과 같은 정보를 얻을수 있다.

이제 쿼리를 만들어보자

위치를 사용한 쿼리는 아래와같이 4가지의 종류가 있다.

  • Geo_shape
    • Intersects, disjoint, within, contains 등의 모양에 맞게 검색
    • Geoshape document
  • Geo_bounding_box
    • 사각형의 범위를 가지며 왼쪽 상단, 오른쪽 하단의 위도 경도를 사용하여 범위안의 값을 찾음
      bounding_box docuemnt
  • Geo_distance
    • 특정 위도 경도와의 거리를 사용하여 특정 거리안의 범위값을 찾음
      distance document
  • Geo_polygon
    • 특정 지점들을 연결연결 하여 다각형을 그리고 그 구역내의 범위를 찾음
      polygon document

스터디를 하는곳인 신도림역 37.5088099,126.8890174 을 중심으로 10Km 안에 주차장이 어디에 있는지 검색을 해봤다.

GET car_wash/_search
{
  "query": {
        "bool" : {
            "must" : {
                "match_all" : {}
            },
            "filter" : {
                "geo_distance" : {
                    "distance" : "10km",
                    "location": {
                        "lat" : 37.5088099,
                        "lon" : 126.8890174 
                    }
                }
            }
        }
    },"size":5
}

결과값

{
  "took" : 8,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 584,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "car_wash",
        "_type" : "_doc",
        "_id" : "I_HOcW4BGQw9X5k0OQxe",
        "_score" : 1.0,
        "_source" : {
          "privider_name" : "3170000",
          "column12" : "서울특별시 금천구",
          "name" : "화성자동차정비공업사",
          "state" : "서울특별시",
          "location" : "37.460736,126.898655",
          "water_quality" : "433",
          "sector" : "정비업소",
          "address" : "서울특별시 금천구 시흥대로 304 (독산동)",
          "phone" : "02-3286-8572",
          "city" : "금천구",
          "date,provider_id" : "2019.9.10"
        }
      },
      {
        "_index" : "car_wash",
        "_type" : "_doc",
        "_id" : "J_HOcW4BGQw9X5k0OQxe",
        "_score" : 1.0,
        "_source" : {
          "privider_name" : "3170000",
          "column12" : "서울특별시 금천구",
          "name" : "금천자동차검사정비센타",
          "state" : "서울특별시",
          "location" : "37.441008,126.902064",
          "water_quality" : "559",
          "sector" : "정비업소",
          "address" : "서울특별시 금천구 시흥대로27길 26 (시흥동)",
          "phone" : "02-893-5500",
          "city" : "금천구",
          "date,provider_id" : "2019.9.10"
        }
      },
      {
        "_index" : "car_wash",
        "_type" : "_doc",
        "_id" : "n_HOcW4BGQw9X5k0OwxT",
        "_score" : 1.0,
        "_source" : {
          "privider_name" : "3170000",
          "column12" : "서울특별시 금천구",
          "name" : "동해자동차정비",
          "state" : "서울특별시",
          "location" : "37.470815,126.891905",
          "water_quality" : "273",
          "sector" : "정비업소",
          "address" : "서울특별시 금천구 두산로7길 10 (독산동)",
          "phone" : "02-851-4972",
          "city" : "금천구",
          "date,provider_id" : "2019.9.10"
        }
      },
      {
        "_index" : "car_wash",
        "_type" : "_doc",
        "_id" : "pPHOcW4BGQw9X5k0OwxT",
        "_score" : 1.0,
        "_source" : {
          "privider_name" : "3170000",
          "column12" : "서울특별시 금천구",
          "name" : "SK에너지(주)이가주유소",
          "state" : "서울특별시",
          "location" : "37.472984,126.897897",
          "water_quality" : "50",
          "sector" : "주유소",
          "address" : "서울특별시 금천구 시흥대로 441 (독산동)",
          "phone" : "02-861-2241",
          "city" : "금천구",
          "date,provider_id" : "2019.9.10"
        }
      },
      {
        "_index" : "car_wash",
        "_type" : "_doc",
        "_id" : "HfHOcW4BGQw9X5k0PQ0y",
        "_score" : 1.0,
        "_source" : {
          "privider_name" : "3170000",
          "column12" : "서울특별시 금천구",
          "name" : "대하운수(주)",
          "state" : "서울특별시",
          "location" : "37.466048,126.894731",
          "water_quality" : "53",
          "sector" : "운수업 등",
          "address" : "서울특별시 금천구 범안로16길 8 (독산동)",
          "phone" : "02-805-0487",
          "city" : "금천구",
          "date,provider_id" : "2019.9.10"
        }
      }
    ]
  }
}

전국 세차장 정보 검색

자신의 위치에서 가까운 전국의 세차장 을 검색하기 위해서 새로운 주제를 시작했다.

실제로는 geo_point를 써보고싶어서 맞춰서 작업!!

https://www.data.go.kr/dataset/15013193/standard.do

수정을 한 세차장 정보는 다음과 같다 .

image-20191116010342675

이제 데이터를 넣어보자.

잠깐 데이터를 넣기 전에 geopoint 형식으로 데이터를 삽입할것이기때문에 location의 데이터 타입을 geo-point 로 변경하자 .

injest pipeline 을 사용해보는것도 추천한다.

PUT car_wash
{
  "mappings": {
    "_doc": {
      "properties": {
        "location": {
          "type": "geo_point"
        }
      }
    }
  }
}

다양한 방법이 있지만 logstash를 통해서 쉽게 데이터를 넣어보자 !

logstash 를 사용해서 편리하게 넣을수 있지만, 다음에는 java를 REST API를 사용해서 넣어보도록 하기로함

logstash의 파일은 다음 과 같다.

input{
    file{
        path => "/Users/daeyunkim/Documents/07.ELK_v6/car_wash/cleanCar_edit.csv"
        start_position => "beginning"
        sincedb_path => "/dev/null"
    }
}

filter{
    csv{
        separator => ","
        columns => [ "name","state","city","sector","address","phone","water_quality" ,"latitude","longitude","date,provider_id","privider_name"]
    }
    mutate {
    add_field => { "location"=> "%{latitude},%{longitude}"}
    remove_field => ["@version","@timestamp","path","host","tags","message","latitude", "longitude"]
    }


}

output{
    stdout{}
    elasticsearch {
        hosts => "http://localhost:9200"
        index => "car_wash"
        document_type=>"_doc"
    }
}

logstash add field

https://www.elastic.co/guide/en/logstash/6.2/plugins-filters-mutate.html#plugins-filters-mutate-add_field

$ ./bin/logstash -f ../car_wash/car_wash.conf

위에 대로 하면 그대로들어갈것이라 생각했건만 현실은 한글 깨짐 !!

{
    "date,provider_id" => "2019.5.8",
               "phone" => "02-507-5100",
               "state" => "\\xB0\\xE6\\xB1\\u2D75",
             "address" => "\\xB0\\xE6\\xB1\\u2D75 \\xB0\\xFAõ\\xBD\\xC3 \\xC1\\u07FEӷ\\xCE 417",
                "name" => "\\xB0渶\\xC0\\xE5\\xC1\\xD6\\xC0\\xAF\\xBC\\xD2",
       "privider_name" => "3970000",
                "city" => "\\xB0\\xFAõ\\xBD\\xC3",
            "column12" => "\\xB0\\xE6\\xB1\\u2D75 \\xB0\\xFAõ\\xBD\\xC3\\r",
       "water_quality" => "2000-010",
            "location" => "37.450708,126.999478",
              "sector" => "\\xC1\\xD6\\xC0\\xAF\\xBC\\xD2"
}

Excel에서는 한글로 열리지만 실제로 vi 를 사용하여 열어보니 한글이 깨져있었다.

인코딩방법을 해결하고 다시 삽입!

es-data

Kibana 를 통해 시각화 한번 해보자

새로 넣은 데이터를 사용해서 시각화를 해봤다.

잘 넣은 것같다.
carwash_map

사용자 계정으로 접속하지 않게 하는방법

/bin/false , /bash/nologin 두가지 방법이 있다.

/etc/passwd 사용자 계정 부분에 사용할수 있음

  1. False

/bin/false

시스템의 로그인은 불가능, FTP 서버 프로그램 같은 프로그램도 불가능

쉘 ,ssh 홈디렉토리를 사용할 수 없음. 단순히 계정만 필요할 경우 생성

  1. Nologin

/sbin/nologin

/sbin/nologin

사용자 계정의 쉘 부분에 /bin/nologin 으로 설정 하면 로깅 불가하고, 메세지들은 반환 됨.

ssh 사용 불가, ftp의 경우에는 사용 가능

예시

ntp:x:38:38::/etc/ntp:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
morriskim:x:1001:1001::/home/morriskim:/bin/bash

'BackEnd > Linux' 카테고리의 다른 글

Yum Repository 만들기 (2)  (0) 2019.12.24
Yum Repository 만들기 (1)  (0) 2019.12.23
Swap 메모리 늘리기  (0) 2019.09.17
cache 삭제하기  (0) 2019.08.27
Bash 프로그래밍 기초 - 파라미터 받아오기  (0) 2019.08.20

+ Recent posts