스프링 프레임워크 정적 자원 버전 관리




HTTP 캐싱

  • 네트워크를 통해 자원을 가져오는 작업은 느리고 비용이 발생한다. 특히, 크기가 크면 그만큼 브라우저가 화면을 표시하는데 오래 걸려 사용자 경험이 나빠진다.
  • 가져온 자원을 캐시했다가 재활용하는 것은 성능 최적화에 중요하다.
  • 모든 브라우저는 HTTP 캐시 구현 기능이 포함되어 있다.
  • 개발자는 각 서버 응답이 브라우저에 응답을 캐시할 수 있는 시점과 그 기간을 지시하게 위한 HTTP Header를 올바르게 제공해야한다.

정적 자원 버전 관리

  • 브라우저는 한 번 방문한 사이트의 정적 자원은 캐시가 되어 만료 될 때까지 사용한다.
  • 이때문에 정적 자원이 수정된 후에 사이트를 방문한 사용자는 최신 정적 자원을 사용하는 반면, 이전에 방문했던 사용자는 과거 정적 자원을 사용하게 되어 이슈가 발생할 수 있다.
  • 예) 이미지가 다르게 보임, 수정된 자바스크립트가 실행이 안되거나 동작이 달라짐
  • 따라서 정적 자원의 버전관리를 통해 수정된 정적 자원일 경우 새로운 버전이 제공되어 사용자들이 서버에서 최신 버전 정적 자원을 받을 수 있도록 해야한다.

정적 자원 캐시 만료되는 경우

  • 사용자 직접 삭제
  • max-age 또는 expires로 정해진 기한이 지난 경우
  • 정적 자원의 URL을 변경한 경우

스프링 프레임워크에서 정적 자원 버전 관리

  • 스프링 프레임워크는 4.1 버전 이후부터 WebMvcConfigureraddResourceHandlers 설정 메서드에서 버전 관리 핸들러를 리졸버를 등록하여 관리할 수 있다.
  • ContentVersionStrategy 통해서 브라우저가 요청한 자원 각 파일의 내용에 따라 MD5 해쉬된 문자열이 요청한 자원 파일명 뒤에 버전처럼 붙는다.
  • 수정된 정적 자원의 경우 파일 내용이 바뀌므로 서버에서 응답한 요청한 자원 파일명에 붙은 MD5 해쉬 문자열이 사용자의 브라우저가 캐시해서 가지고 있던 것과 다르기 때문에 새로 내려받게 된다.

WebMvcConfig 설정

@Configuration
public class MvcConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**", "/webjars/**")
                .addResourceLocations("/resources/", "classpath:/META-INF/resources/webjars/")
                .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
                .resourceChain(true)
                .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
                .addResolver(new WebJarsResourceResolver());
	}

}

정적 자원 접근 처리 설정

  • 컨트롤러 어드바이스 설정을 ResourceUrlProvider를 모든 응답에 urls라는 이름으로 제공한다.
  • 템플릿에서 urls로 접근이 가능하다.
@ControllerAdvice
public class ResourceUrlAdvice {

    @Autowired
    private ResourceUrlProvider resourceUrlProvider;

    @ModelAttribute("urls")
    public ResourceUrlProvider urls() {
        return this.resourceUrlProvider;
    }
}

JSP에서 사용

<!-- CSS -->
<link rel="stylesheet" href="${urls.getForLookupPath('/resources/sss/style.css')}" />

<!-- JavsScript -->
<script src="${urls.getForLookupPath('/resources/js/common/common.js')}"></script>
<script src="${urls.getForLookupPath('/resources/js/main.js')}"></script>

예시

이전 버전


변경된 버전


흐름



생각해볼 점

  • 하나의 HTTP 요청에 필요한 정적 자원을 하나씩 검사하는 부분이 추가 되므로 극악한 상황의 네트워크, 서버 환경에서는 성능에 악영향을 줄 수도 있을 것 같다.
  • 하지만 일반적으로 문제는 없고, 오히려 버전 관리가 안되서 사용자가 과거 버전의 자원을 가진 채로 사이트가 운영됨으로 발생하는 이슈에 대한 비용이 더 클 것 같다.

참고


매직 넘버 치환

  • 소스 코드에 특정한 숫자(매직 넘버(magic number))를 직접 작성하는 것은 나쁜 코딩 스타일

나쁜 예

public class MagicNumber {
    public static void main(String[] args) {
        MagicNumber magicNumber = new MagicNumber();
        MagicNumber.Player player = magicNumber.new Player("Hoonmaro");
        // 0은 공격
        player.action(0);
        // 1은 방어
        player.action(1);
    }

    public class Player {

        private String name;

        public Player() {
        }

        public Player(String name) {
            this.name = name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public void action(int command) {
            if (command == 0) {
                attack();
            } else if (command == 1) {
                defence();
            }
        }

        private void attack() {
            System.out.println(this.name + " is going to Attack!!");
        }

        private void defence() {
            System.out.println(this.name + " is going to Defence!!");
        }

    }
}

나쁜이유

  1. 매직 넘버의 의미를 알기 어렵다
    • 0과 1이 무슨 의미인가?
    • COMMAND_ATTACK과 같은 기호 상수를 쓰면 의미를 알기 쉽다
  2. 매직 넘버는 수정하기 어렵다
    • 0 또는 1 커맨드 숫자가 변경 될 경우 치환해야 하는데, 만약 많은 곳에서 동일한 커맨드를 쓴다면?
    • 손이 많이 가고, 틀리기 쉽고, 빼먹는 경우가 생길 수도 있다.

카탈로그

이름 매직 넘버를 기호 상수로 치환 (Replace Magic Number with Symbolic Constant)
상황 상수를 사용하고 있음
문제 • 매직 넘버는 알기 어려움
• 매직 넘버가 여러 곳에 있으면 변경하기 어려움
해법 매직 넘버를 기호 상수로 치환함
결과 장점
• 상수의 의미를 알기 쉬워짐
• 기호 상수의 값을 변경하면 상수를 사용하는 모든 곳이 변경됨
단점/주의 • 이해하기 어려운 이름을 사용하면 오해가 생길 수 있음
방법
  1. 기호 상수 선언하기
    • 1. 기호 상수 선언
    • 2. 매직 넘버를 기호 상수로 치환
    • 3. 기호 상수에 의존하는 다른 매직 넘버를 찾아서 기호 상수를 사용한 표현식으로 변환
    • 4. 컴파일
  2. 2. 테스트
    • 1. 모든 기호 상수 치환이 끝나면 컴파일해서 테스트
    • 2. 가능하다면 기호 상숫값을 변경한 후 컴파일해서 테스트 |
관련 항목 • 분류 코드를 클래스로 치환
• 분류 코드를 상태/전략 패턴으로 치환

리팩토링

기호 상수 선언하기

  1. 기호 상수 선언
  • public static final 클래스 필드 사용
  • 또는 enum 사용
  • 어떤 클래스 안에서만 사용할 기호 상수를 선언할 경우 private 접근지시자를 사용할 수 있다
public static final int COMMAND_ATTACK = 0;
public static final int COMMAND_DEFENCE = 1;
  1. 매직 넘버를 기호 상수로 치환
  • 0, 1과 같은 매직 넘버를 기호 상수로 치환
// if (command == 0) {
if (command == COMMAND_ATTACK) {

// else if (command == 1) {
} else if (command == COMMAND_DEFENCE) {


// player.action(0)
// player.aciton(1)
player.action(Player.COMMAND_ATTACK);
player.action(Player.COMMAND_DEFENCE);
  1. 기호 상수에 의존하는 다른 매직 넘버를 기호 상수를 사용한 표현식으로 변환
  • 상수 의존 관계는 상수 사이에 의존 관계가 있어 한 상수의 변경이 다른 상수에게도 영향을 미치는 경우를 말한다.
  • 이 때, 표현식으로 의존 관계를 표현해야 한다.
// public static final int MAX_INPUT_LENGTH = 100;
// public static final int WOR_ARE_LENGTH = 100 * 2;

public static final int MAX_INPUT_LENGTH = 100;
public static final int WOR_ARE_LENGTH = MAX_INPUT_LENGTH * 2;

테스트

  1. 모든 기호 상수 치환이 끝나면 컴파일해서 테스트

    • 테스트 결과는 리팩토링하기 전과 같아야 한다.
  2. 가능하다면 기호 상숫값을 변경한 후 컴팡리해서 테스트

    • 기호 상수의 값을 다른 값으로 변경한 후 테스트하면 빠드린 곳이 없는지 확인할 수 있다.
    • COMMAND_ATTACK 값을 0에서 1000으로 변경해도, 매직 넘버가 없다면 테스트가 성공하지만 매직 넘버가 있다면 테스트가 실패한다.

리팩토링 후

public class MagicNumber {
    public static void main(String[] args) {
        MagicNumber magicNumber = new MagicNumber();
        MagicNumber.Player player = magicNumber.new Player("Hoonmaro");
        player.action(Player.COMMAND_ATTACK);
        player.action(Player.COMMAND_DEFENCE);
    }

    public class Player {

        public static final int COMMAND_ATTACK = 0;
        public static final int COMMAND_DEFENCE = 1;


        private String name;

        public Player() {
        }

        public Player(String name) {
            this.name = name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public void action(int command) {
            if (command == COMMAND_ATTACK) {
                attack();
            } else if (command == COMMAND_DEFENCE) {
                defence();
            }
        }

        private void attack() {
            System.out.println(this.name + " is going to Attack!!");
        }

        private void defence() {
            System.out.println(this.name + " is going to Defence!!");
        }

    }
}
  • 기호 상수가 충분한 정보를 제공하므로 주석이 필요 없다.

더 나은 리팩토링

  • 기호 상수로 만든다고 해도 실제로는 상수 값이므로 매직 넘버를 직접 적어도 문제없이 컴파일 된다.
  • 실수가 생길 수 있다.
  • 커맨드 클래스 객체를 활용하거나 enum을 활용한다.

enum 활용

  • 자바 5부터 enum을 사용할 수 있다.
public class EnumMagicNumber {
    public static void main(String[] args) {
        EnumMagicNumber magicNumber = new EnumMagicNumber();
        Player player = new Player("Hoonmaro");
        player.action(Player.Command.ATTACK);
        player.action(Player.Command.DEFENCE);
    }
}

// Player 클래스 분리
public class Player {

    public enum Command {
        ATTACK,
        DEFENCE
    }

    private String name;

    public Player() {
    }

    public Player(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void action(Command command) {
        if (command == Command.ATTACK) {
            attack();
        } else if (command == Command.DEFENCE) {
            defence();
        }
    }

    private void attack() {
        System.out.println(this.name + " is going to Attack!!");
    }

    private void defence() {
        System.out.println(this.name + " is going to Defence!!");
    }

}

  • 기존 Player Inner 클래스를 분리하였다.
  • 증첩 enum 은 암묵적으로 static 클래스 이기 때문에 Inner 클래스 안에 선언할 수 없기 때문이다.
  • Java Language Spec 8.9 Enums 참고
  • enum을 활용하여 직관적으로 의미를 전달 할 수 있다.
  • 상수가 아니므로 잘못 사용된 곳에서 컴파일에서 경고가 발생하여 에러를 사전에 방지할 수 있다.

기호 상수가 적합하지 않은 경우

  • 배열 길이
    • 배열 길이는 배열 객체에 length라는 필드가 있다.
    • 기호 상수가 언제나 올바른 배열길이가 아닐 수도 있다.
  • 잘 알려진 값을 대체하는 기호 상수 (오히려 가독성이 떨어짐)

바이트 코드에 내장된 상수에 주의

  • 필드값이 컴파일할 때 정해지는 상수일 경우 리컴파일시 변경된 값으로 바뀌겠지만,
  • 이를 사용하는 다른 클래스에서는 리컴파일 하기 전에 이전 상수 값을 가지고 있으므로 문제가 발생한다.
  • 매직 넘버를 치환한 모든 소스코드를 리컴파일 해야 정상 작동 된다.

AJAX Patterns

  • Vue에서 AJAX를 사용하는 가장 좋은 방법에 대해서는 개발자들 사이에서도 의견이 갈린다.
  • 그 중 4가지의 디자인 패턴을 소개하며, 각각의 장단점을 알고 상황에 맞게 쓸 수 있어야 한다.
  • AJAX Design Patterns in Vue.js
    1. Root instance
    2. Components
    3. Vuex ations
    4. Route navigation guards

1. Root instance

  • 이 아키텍쳐에서는 root instance로부터 모든 AJAX 요청이 보내지고 모든 상태가 저장된다.

  • 다른 하위 컴포넌트들이 data를 필요로 한다면, props를 통해 전달한다.

  • 하위 컴포넌트들이 data 최신화를 원하면, 커스텀 이벤트를 통해 root instacne의 AJAX 요청을 호출한다.

  • 예제

new Vue({
  data: {
    message: ''
  },
  methods: {
    refreshMessage(resource) {
      this.$http.get('/message').then((response) {
        this.message = response.data.message;
      });
    }
  }
})

Vue.component('sub-component', {
  template: '<div>{{ message }}</div>',
  props: [ 'message' ]
  methods: {
    refreshMessage() {
      this.$emit('refreshMessage');
    }
  }
});

장점

  • 모든 AJAX 로직과 data를 한 곳에서 관리할 수 있다.
  • 모든 컴포넌트들이 프레젠테이션에 집중할 수 있다.

단점

  • 많은 props와 커스텀 이벤트가 필요하면서 앱의 크기가 커진다.

2. Components

  • 이 아키텍쳐에서는 컴포넌트 별로 AJAX 요청과 상태를 독립적으로 관리한다.

  • 일반적으로 컨테이너 역할을 하는 컴포넌트가 data를 관리하고 하위 컴포넌트들을 프레젠테이션에 집중시킨다.

  • 예제

let mixin = {
  methods: {
    callAJAX(resource) {
      ...
    }
  }
}

Vue.component('container-comp', {
  // No meaningful template, I just manage data for my children
  template: '<div><presentation-comp :mydata="mydata"></presentation-comp></div>', 
  mixins: [ myMixin ],
  data() {
    return { ... }
  },

})

Vue.component('presentation-comp', {
  template: <div>I just show stuff like {{ mydata }}</div>,
  props: [ 'mydata' ]
})

장점

  • 컴포넌트 결합도를 낮추고 재활용성을 높인다.
  • data를 필요할 때 얻을 수 있다.

단점

  • 다른 컴포넌트들과 data를 주고받기 쉽지 않다.
  • 컴포넌트가 너무 많은 책임을 가지게 되거나 기능적 중복이 발생할 수 있다.

3. Vuex actions

  • 이 아키텍쳐에서는 AJAX 로직과 상태를 Vuex Store에서 관리할 수 있다.

  • 컴포넌트들은 action을 호출하여 새로운 data를 요청할 수 있다.

  • 이 패턴을 구현하는 경우, AJAX요청(예, 로딩 스피너 숨기기, 버튼 재활성화)의 해결에 반응할 수 있도록 액션에서 promise를 반환하는 것이 좋다.

  • 예제

store = new Vuex.Store({
  state: {
    message: ''
  },
  mutations: {
    updateMessage(state, payload) {
      state.message = payload
    }
  },
  actions: {
    refreshMessage(context) {
      return new Promise((resolve) => {
        this.$http.get('...').then((response) => {
          context.commit('updateMessage', response.data.message);
          resolve();
        });
      });
    }
  }
});

Vue.component('my-component', {
  template: '<div>{{ message }}</div>',
  methods: {
    refreshMessage() {
      this.$store.dispatch('refeshMessage').then(() => {
        // do stuff
      });
    }
  },
  computed: {
    message: { return this.$store.state.message; }
  }
});

장점

  • 추가적인 props와 커스텀 이벤트 없이도 Root instance 패턴과 Components 패턴의 장점을 모두 가진다.

단점

  • Vuex를 사용하기 위한 학습비용 등의 오버헤드

4. Route navigation guards

  • 애플리케이션이 여러 페이지로 분할되고 route가 변경되면 해당 페이지와 하위 컴포넌트들에 필요한 모든 데이터를 가져온다.

  • 이 방식의 주요 이점은 UI가 굉장히 단순해지는 것이다.

  • 만약 컴포넌트들이 독립적으로 data를 가져오면, 컴포넌트 데이터가 임의의 순서로 입력되어 페이지가 예측 불가능하게 재전송된다.

  • 예제

import axios from 'axios';

router.beforeRouteEnter((to, from, next) => {
  axios.get(`/api${to.path}`).then(({ data }) => {
    next(vm => Object.assign(vm.$data, data))
  });
})

장점

  • UI를 보다 쉽게 예측할 수 있다.

단점

  • data가 준비될 때가지 페이지가 렌더링 되지 않으므로 전체적으로 느려진다.
  • routes를 사용하지 않는다면 도움이 되지 않는다.

참고


객체지향 프로그래밍

  • Object Oriented Programming, OOP *객체
    • 생활에서 일종의 물건
    • 속성(Attribute)와 행동(Action)을 가짐
  • OOP는 속성은 변수, 행동은 함수로 객체의 개념을 프로그램으로 표현

클래스, 객체, 인스턴스

  • 클래스는 객체의 구체적인 형태를 설계한 명령어의 집합, 템플릿 또는 설계도
  • 객체는 속성과 행위로 구성된 사물 또는 추상적 개념들의 정보를 표현한 것
  • 인스턴스는 클래스로부터 인스턴스화를 통해 구현된 객체

추상화 기법

  • 추상화 기법의 하나로 분류/인스턴스화(classification/instantiation) 개념 존재
  • 분류는 객체들을 공통적인 속성을 공유하는 개념으로 범주화
  • 인스턴스화는 추상화된 범주로부터 실재하는 객체를 만드는 과정을 의미
  • 인스턴스라는 말은 추상적인 개념과 구체적인 객체 사이의 관계에 초점에 맞춘 용어

프로그램에서의 클래스, 인스턴스

  • 추상화의 과정을 거쳐 속성과 행위를 가진 객체를 클래스로 표현하며, 클래스는 변수와 메서드를 가진다
  • 프로그램 언어별로 클래스를 만드는 문법을 사용하여 인스턴스를 생성하게 된다.
    • Java: ExampleClass exampleClass = new ExampleClass();
    • Python: example_class = ExampleClass()

문법

[접근지정자] [기타제어자] class 클래스명 [extends Super클래스] [implements 인터페이스…] {
	/* 필드(멤버변수) */
	/* 메서드(멤버함수) */
}
  • 멤버: 클래스 안에 선언된 것들

클래스명 작성 규칙

작성규칙
하나 이상의 문자로 이루어져야 한다 Car, SportsCar
첫 번째 글자는 숫자가 올 수 없다 Car, 3Car(x)
'$','_' 외의 특수 문자는 사용할 수 없다 $car, _Car, @Car(x), #Car(x)
자바 키워드(예약어)는 사용할 수 없다 int(x), for(x)
단일 단어 => 첫문자는 대문자 혼합 단어 => 각 단어 첫글자는 대문자

예제

  • Cat 클래스
public class Cat {
	
	/* 클래스 필드 (객체의 속성) */
	// 이름
	private String name;
	// 품종
	private String breed;
	// 나이
	private int age;
	
	/* 클래스 메서드 (객체의 행동) */
	public String cry() {
		return "냐옹";
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void setBreed(String breed) {
		this.breed = breed;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public String getName() {
		return this.name;
	}
	
	public String getBreed() {
		return this.breed;
	}
	
	public int getAge() {
		return this.age;
	}
	
	// 모든 클래스의 부모인 Object 클래스의 toString 메서드 오버라이드
	@Override
	public String toString() {
		final StringBuilder sb = new StringBuilder("Cat{");
			sb.append("name='").append(name).append('\'');
			sb.append(", breed='").append(breed).append('\'');
			sb.append(", age='").append(age).append('\'');
			sb.append('}');
		return sb.toString();
	}
}
  • Cat 클래스 인스턴스화
public class CatClassTest {
	public static void main(String[] args) {
		// new 연산자를 통해 Cat 클래스를 인스턴스화
		Cat nabi = new Cat();
		nabi.setName("나비");
		nabi.setBreed("페르시안");
		nabi.setAge(2);
		System.out.println(nabi);
	}
}
  • 결과
Cat{name='나비', breed='페르시안', age='2'}

예제 설명

  • Cat 클래스를 만들고 클래스의 필드와 메서드를 선언
  • CatClassTest 클래스에서 Cat 클래스를 new 연산자를 통해 인스턴스화하여 인스턴스를 생성 후 nabi라는 변수에 레퍼런스 저장
  • 이 때 new 연산자를 통해 생성된 인스턴스는 힙(heap) 메모리 영역에 저장되며 nabi 변수는 메모리 레퍼런스(주소)를 가지고 있다.
  • setter(세터) 메서드를 통해 name, breed, age를 세팅 후 오버라이드한 toString 메서드를 통해 필드값들을 출력한다.

구성 멤버

필드(field)

  • 객체의 고유 데이터, 상태 정보를 저장하는 곳
  • 생성자와 메소드 전체에서 사용되며 객체가 소멸되지 않는 한 객체와 함께 존재
  • 초기화 하지 않으면 각 자료형의 기본값으로 초기화 됨
  • 필드선언
    • 생성자 선언과 메소드 선언의 앞 뒤 어떤 곳에서도 필드 선언 가능
    • 단, 생성자와 메소드 내부에서는 선언될 수 없음 (생성자,메소드 내부의 변수는 지역변수)
  • 필드사용
    • 필드 값을 읽고 변경하는 작업
    • 클래스 내부에서는 단순히 필드 이름으로 읽고 변경
    • 클래스 외부에서는 클래스로부터 객체 생성 후 사용 (일반적으로 직접 접근 못하게 캡슐화)

생성자(Constructor)

  • new 연산자로 호출되는 특별한 중괄호 블록
  • 객체 생성 시 초기화 담당
  • 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비
  • 클래스 이름으로 되어 있고 리턴 타입이 없다
  • 생성자 선언
    • 생성자를 선언 안해도 기본적으로 컴파일시 디폴트 생성자가 생성됨
    • 생성자는 메소드와 비슷한 모양을 가지나, 리턴 타잆이 없고 클래스 이름과 동일
    • 클래스에 생성자가 명시적으로 선언되어 있을 경우 반드시 선언된 생성자를 호출해서 객체를 생성
    • 하나라도 인자값을 가진 다른 생성자를 호출할 경우 디폴트 생성자는 자동으로 생성되지 않으므로 디폴트 생성자를 호출하기 위해선 디폴트 생성자도 명시적으로 선언해줘야 함
  • 필드 초기화
    • 필드를 선언할 때 초기값을 주면 동일한 클래스로부터 생성되는 객체들은 모두 같은 데이터를 가짐
    • 객체 생성 시점에 외부에서 제공되는 다양한 값들로 초기화 되어야 한다면 생성자에서 초기화 해야 함
  • 관례적으로 필드와 동일한 이름을 갖는 매개변수 사용
    • 이 경우 필드와 매개변수 이름이 동일하므로 생성자 내부에서 해당 필드에 접근할 수 없다
    • why? 동일한 이름의 매개 변수가 사용 우선순위가 높다. 따라서 this 를 사용한다.
    • this는 객체 자신의 참조
public class Cat {
	private String name;
	public setName(String name) {
		// 필드 name과 매개변수 name의 이름이 같다
		// name = name
		this.name = name
	}
	
}
  • 생성자 오버로딩
    • 매개변수를 달리하는 생성자를 여러 개 선언하는 것
    • 오버로딩 시 주의점은 매개 변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우 매개 변수 이름만 바꾸는 것은 오버로딩이라고 볼 수 없음
  • 다른 생성자 호출(this())
    • 생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드 발생
    • 이 경우 필드 초기화한 내용은 한 생성자에만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선
    • 생성자에서 다른 생성자 호출할 때 this() 코드 사용
    • this()는 자신의 다른 생성자를 호출하는 코드, 반드시 생성자 첫줄에서만 허용
public Cat(String name, String breed) {
        this.name = name;
        this.breed = breed;
}

public Cat(String name, String breed, int age) {
        this(name, breed);
        this.age = age;
}


메서드(Method)

  • 객체의 동작에 해당하는 중괄호 블록
  • 메서드 호출 => 중괄호 블록 내 모든 코드 실행
  • 용도
    • 필드 읽고 수정
    • 다른 객체 생성해서 다양한 기능 수행
    • 객체 간의 데이터 전달 수단
    • 이외 다양한 행동 구현
  • 메서드 선언
[접근제한자] [기타제어자] 반환자료형 메서드명(매개변수) {
    [return 리턴값;]
}
  • 메서드 선언부 = 메서드 시그너처

  • 리턴 타입

    • 메서드가 실행 후 리턴하는 값의 타입
    • 메서드 실행 후 결과를 호출한 곳에 넘겨줄 경우에는 리턴 값이 있어야 함
    • 리턴 값의 타입은 선언부의 반환자료형과 동일해야 함
    • 리턴 타입이 있다고 해서 반드시 리턴값을 변수에 저장할 필요 없음
    • void 타입의 경우 리턴문 없이 사용 가능
  • 매개 변수의 수를 모를 경우

    • 매개 변수를 배열 타입으로 선언
    • … 으로 선언후 리스트 나열
public int sum(int ... args) {
        return IntStream.of(args).sum();
}
  • 메서드 호출
  • 메서드는 클래스 내/외부의 호출에 의해 실행
    • 클래스 외부에서 호출할 경우 우선 클래스로부터 객체 생성
    • 클래스 참조변수 = new 클래스(매개값); * 참조변수.메서드(매개값); (리턴값 없거나, 받지 않을 경우) * 타입 변수 = 참조변수.메서드(매개값); (리턴값 받고 싶을 때)
  • 메서드 오버로딩
    • 클래스 내에 같은 이름의 메서드를 여러 개 선언하는 것
    • 매개 변수의 타입, 개수, 순서 중 하나가 달라야 한다 (시그니처가 달라야 한다)

PMM(Percona Monitoring and Management) 설치

PMM 이란?

  • PMM은 서버/클라이언트로 구성되어 MySQL(MariaDB), MongoDB, OS(Linux)를 모니터링 할 수 있는 플랫폼
  • PMM Server: PMM Client에서 수집된 데이터를 저장하겨 웹기반의 대시보드와 그래프 표시
  • PMM Client: 모니터링 대상 서버에 설치되는 에이전트로 서버정보, DB정보, 쿼리정보 등을 수집하여 PMM Server에 전달

설치

  • 테스트 목적으로는 한 대의 서버에 Server/Client를 모두 설치하나 실제 운영상에서는 분리하는 것이 좋음

설치환경

  • CentOS 7
  • Docker

Docker 설치

  • PMM Server는 Docker 이미지로 배포되므로 Docker 설치가 필요하다.

이전 버전의 Docker 삭제 (필요시)

> sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine

스크립트를 활용한 Docker 설치

> wget -qO- https://get.docker.com/ | sh

PMM Server 설치

  • Docker에서 이미지 받아오기
> docker pull percona/pmm-server
  • 이미지 확인
> docker images | grep pmm
  • PMM 데이터 컨테이너 생성
> docker create -v /opt/prometheus/data -v /opt/consul-data -v /var/lib/mysql --name pmm-data  percona/pmm-server /bin/true
  • PMM 서버 컨테이너 생성 / 실행 (포트 변경이 필요하다면 80:80을 사용할포트:80으로 변경)
> docker run -d  -p 80:80 --volumes-from pmm-data  --name pmm-server  --restart always  percona/pmm-server
  • 생성된 컨테이너 확인
> docker ps -a

PMM Client 설치

> rpm -ivh https://www.percona.com/downloads/pmm-client/1.8.1/binary/redhat/7/x86_64/pmm-client-1.8.1-1.x86_64.rpm
  • 다운로드 링크에서해당 OS의 최신버전 URL을 따와서 위와같이 실행
  • 혹은, 파일을 직업 올린 후에 해당 위치에서 위의 명령어 실행

Server 등록하기

> pmm-admin config --client-name 클라이언트이름 --server 서버아이피:포트
# --bind-address 사설아이피 --client-address 공용아이피 (방화벽 설정이 되어있을 경우)

모니터링 서비스 등록하기

  • 모니터링 서비스
    • linux:metrics > 일반 시스템 모니터링
    • mysql:metrics > MySQL 모니터링
    • mysql:queries > MySQL 쿼리 모니터링
    • mongodb:metrics > MongoDB 모니터링
    • mysql > linux:metrics + mysql:metrics + mysql:queries
    • mongodb > linux:metrics + mongodb:metrics
> pmm-admin add mysql --user root --password 루트비밀번호
  • 등록 확인하기
> pmm-admin list

설치 확인


Gmail Alert 설정

> docker ps
# 결과
CONTAINER ID        IMAGE                COMMAND                CREATED             STATUS              PORTS                           NAMES
d99b87dbc8f1        percona/pmm-server   "/opt/entrypoint.sh"   13 days ago         Up About a minute   443/tcp, 0.0.0.0:9001->80/tcp   pmm-server
> docker exec -it CONTAINER ID /bin/bash
# pmm-server 컨테이너의 bash 쉘에 접속

> vi /etc/grafana/grafana.ini

grafana 설정 수정

[smtp]
enabled = true
host = smtp.gmail.com:465
user = your.gmail.account@gmail.com
password = yourpassword
cert_file =
key_file =
skip_verify = false
from_address = admin@grafana.localhost
from_name = PMM
  • ctrl + d 또는 ctrl + p + ctrl + q 로 도커 컨테이너 쉘 종료
  • pmm-server 도커 컨테이너 재시작
> docker restart pmm-server
  • Grafana 대쉬보드 접속 → 좌측 상단 Grafana 아이콘 클릭 → 드롭다운 메뉴에서 Alerting 클릭
  • Create an alert notification 클릭
Name: Gmail Alert
Type: email
Send on all alerts: Check
Include Images: Check
Email Address: 받을 사람 주소 목록 (여러개일 경우 ; 로 구분)

Example (Grafana Dashboard)




Zabbix Slack 연동

스크립트

#!/bin/sh

webhook_url=$1
message=$2

curl -k -X POST -d "payload={\"username\":\"zabbix\", \"text\":\"$message\"}" $webhook_url
  • 스크립트 위치는 zabbix_server.conf 설정 파일에서 AlertScriptPath에 설정된 위치
  • 해당 위치에 쉘스크립트를 넣어놓고 진행

Slack Web Hook Url

  • Slack App > Incoming WebHooks
  • Add Configuration > Choose Channel > Add Incoming WebHooks integration > url 확인

미디어 타입 설정

  • 관리 - 미디어 타입 - 연락방법 작성
  • 첨부 그림 참고




내용

  • 이름: 미디어 타입 명
  • 종류: 스크립트
  • 스크립트 이름: 작성한 스크립트명 (예: zabbix-slack.sh)
  • 스크립트 파라미터
  • 파라미터1: Slack WebHook URL
  • 파라미터2: {ALERT.MESSAGE} (메시지 내용 매크로)



Zabbix Java Gateway / JMX

zabbix-java-gateway 설치

# Zabbix Server 설치된 곳에서 설치
> yum install -y zabbix-java-gateway

catalina-jmx-remote.jar 설치

# 모니터링 대상 호스트에서 설치
# TOMCAT 8
# TOMCAT_HOME\lib 폴더
> wget http://apache.mirror.cdnetworks.com/tomcat/tomcat-8/v8.0.49/bin/extras/catalina-jmx-remote.jar

bin/catalina.sh 수정

# TOMCAT_HOME\bin\catalina.sh
# JAVA_OPTS 하단에 추가
 
JAVA_OPTS="$JAVA_OPTS
    -Dcom.sun.management.jmxremote \
    -Djava.rmi.server.hostname=HOST_SERVER_IP \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Dcom.sun.management.jmxremote.ssl=false
  "

conf/server.xml 수정

<Server port="8005" shutdown="SHUTDOWN">
...
  <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener"
    rmiRegistryPortPlatform="12345" rmiServerPortPlatform="12346"/>
...
</Server>

방화벽 설정

# CentOS 7
firewall-cmd --permanent --add-port=12345/tcp
firewall-cmd --permanent --add-port=12346/tcp
firewall-cmd --reload
systemctl restart firewalld
 
# CentOS 6
vi /etc/sysconfig/iptables
 
-A INPUT -p tcp -m tcp --dport 12345 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 12346 -j ACCEPT
# 포트 변경시 그에 맞춰 변경
 
service iptables restart

Zabbix Server Install Manual (자빅스 서버 설치 매뉴얼)


Zabbix

  • 네트워크나 서버(가상)등을 포함한 서비스들을 감시하고 실시간으로 자원을 체크하여 관리자에게 신속히 알리기위한 네트워크 관리 솔루션 소프트웨어 입니다.
  • zabbix 에이전트를 Unix, Linux, Windows 등의 OS에 설치하여 CPU,MEM,파일시스템(용량),특정 TCP 등을 포함한 많은 정보를 포함하여 감시를 할수 있으며 장애대비 모니터링으로써도 탁월합니다.

설치환경

  • OS: CentOS 7 64bit 1708
  • Kernel: 3.10
  • Zabbix: 3.4
  • mariadb: 5.5.56
  • php: 5.4.16
  • Zabbix-server-mysql: 3.4.5
  • zabbix-web-mysql.noarch: 3.4.5

Zabbix 설치

Zabbix Server

Yum 설치를 위한 EPEL 저장소 추가

# yum install epel-release -y
 
Installed:
epel-release.noarch 0:7-9
 
Complete!

Zabbix Package 설치

# rpm -ivh http://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-1.el7.centos.noarch.rpm
 
Updating / installing...
1:zabbix-release-3.4-1.el7 ################################# [100%]############### webtest11.com End #################

[Zabbix-DB, Zabbix-Web / DB(mariadb) / WEB(Apache) / PHP] yum 으로 한번에 설치

# yum -y install zabbix-server-mysql zabbix-web-mysql mysql mariadb-server httpd php

DB 실행 및 설정

DB 실행 및 프로세스 확인

# systemctl start mariadb
# systemctl enable mariadb
 
Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.
 
# ps -ef | grep mysql
 
mysql 11918 1 0 12:09 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe --basedir=/usr
mysql 12080 11918 1 12:-0 ? 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/log/mariadb/mariadb.log --pid-file=/var/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock
root 12134 11523 0 12:09 tty1 00:00:00 grep --color=auto mysql
 

기본설정 (DB 구동된 상태)

# mysql_secure_installation
 
Enter current password for root (enter for none): (패스워드 입력)
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y

DB 접속 및 설정

  • 프록시는 생략 가능
# mysql -u root -p
Enter password: (패스워드 입력)
 
MariaDB [(none)]> create database zabbix_server;
MariaDB [(none)]> grant all privileges on zabbix_server.* to zabbix@localhost identified by 'ironman';
 
MariaDB [(none)]> create database zabbix_proxy;
MariaDB [(none)]> grant all privileges on zabbix_proxy.* to zabbix@localhost identified by 'ironman';
 
MariaDB [(none)]> flush privileges;
 
MariaDB [(none)]> exit;

Zabbix 테이블값 정보 데이터베이스에 적용

# cd /usr/share/doc/zabbix-server-mysql-3.4.5
# gunzip create.sql.gz
# ls
AUTHORS COPYING ChangeLog NEWS README create.sql (해당파일)
# mysql -u root -p zbx_server < create.sql
Enter password: (DB ROOT 패스워드 입력)
Zabbix Proxy
  • 프록시 생략 가능
# cd /usr/share/doc/zabbix-proxy-mysql-3.4.6
# gunzip schema.sql.gz
# ls
AUTHORS COPYING ChangeLog NEWS README schema.sql (해당파일)
# mysql -u root -p zbx_proxy < schema.sql
Enter password: (DB ROOT 패스워드 입력)

Config 설정

Zabix Config 설정

# vi /etc/zabbix/zabbix_server.conf
 
(맨 아래 추가)
 
DBHost=localhost
DBName=zabbix_server
DBUser=zabbix
DBPassword=ironman
 
:wq (저장)
Zabbix Proxy
  • 프록시 생략 가능
# vi /etc/zabbix/zabbix_proxy.conf
 
(맨 아래 추가)
 
# 0 - active mode
# 1 - passive mode
ProxyMode=0
Server=[서버 아이피 입력]
Hostname=[원하는 호스트명 입력 예) Zabbix proxy]
DBName=zabbix_proxy
DBUser=zabbix
DBPassword=ironman

PHP Config 설정

# vi /etc/php.ini
max_execution_time = 600
max_input_time = 600
memory_limit = 256M
post_max_size = 32M
upload_max_filesize = 16M
date.timezone = Asia/Seoul (앞에 ; 주석제거후 한국시간으로 설정)
:wq (저장)

iptables 방화벽 포트 허용 및 재시작

# CentOS 7
firewall-cmd --permanent --add-port=10050/tcp
firewall-cmd --permanent --add-port=10051/tcp
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload
systemctl restart firewalld
 
# CentOS 6
vi /etc/sysconfig/iptables
 
# Zabbix Agent Port
-A INPUT -p tcp -m tcp --dport 10050 -j ACCEPT
# Zabbix Server Port
-A INPUT -p tcp -m tcp --dport 10051 -j ACCEPT
# Zabbix Web Port
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
# 포트 변경시 그에 맞춰 변경
 
service iptables restart

Apache & Zabbix 서버 구동

Apache Server 구동 및 재부팅시 자동시작 처리

#systemctl start httpd
#systemctl enable httpd

Zabbix Server 구동 및 재부팅시 자동시작 처리

#systemctl start zabbix-server
#systemctl enable zabbix-server

Zabbix 서버 웹으로 접속

  • http://localhost/zabbix
  • 하단의 설정 DB설정/server details 설정 후
  • 관리자 페이지 로그인(admin/zabbix)
  • VM일경우 ifconfig를 통해 inet 주소/zabbix, 연결이 안될경우 NAT 혹은 BRIDGE 방식 등의 관련하여 VM에서 웹서버 접속하는 법 찾기

Configure DB connection

  • 웹 관리자 페이지의 DB 설정을 위의 mariaDB에서 zabbix-server 설정한 것과 동일하게 설정
  • Database type: MySQL
  • Database host: localhost
  • Database port: 0
  • Database name: zabbix_server
  • User: zabbix
  • Password: ironman

Zabbix server details

  • Host: localhost
  • Port: 10051
  • Name: (웹 페이지 접속시 보여주고 싶은 메인페이지 명)

Trouble Shooting

아파치 80 Port 막혀서 웹페이지 안 뜰 경우

# 80 포트 방화벽 추가 확인
# 방화벽 확인
netstat -nlp | grep 80
 
# iptables 등록 확인
iptables -nL | grep 80
 
# 등록되어있을 경우 포트 변경
vi /etc/httpd/con/httpd.conf
Listen 다른 포트
# 다른 포트 방화벽 등록
위의 방화벽 포트 허용 및 재시작 부분 참고

SElinux

# SElinux 해제
vi /etc/sysconfig/selinux
SELINUX=disabled
 
reboot
 
# reboot 해도 SElinux 활성화 되어있을 경우
vi /etc/grub.conf
kernel ..., selinux=0 # 맨뒤에 selinux=0 추가
 
# SElinux 활성화 된 상태에서 등록
 
vi /etc/zabbix/zabbix_agent_t.te
 
# 아래 내용 신규 생성된 파일에 추가 후 저장/종료 (:wq)
module local-zabbix 1.0;
 
require {
    type zabbix_agent_t;
    class process setrlimit;
}
 
#============= zabbix_agent_t ==============
allow zabbix_agent_t self:process setrlimit;
 
:wq
 
semanage permissive -a zabbix_agent_t

Zabbix Server Install Manual (자빅스 서버 설치 매뉴얼)


Zabbix

  • 네트워크나 서버(가상)등을 포함한 서비스들을 감시하고 실시간으로 자원을 체크하여 관리자에게 신속히 알리기위한 네트워크 관리 솔루션 소프트웨어 입니다.
  • zabbix 에이전트를 Unix, Linux, Windows 등의 OS에 설치하여 CPU,MEM,파일시스템(용량),특정 TCP 등을 포함한 많은 정보를 포함하여 감시를 할수 있으며 장애대비 모니터링으로써도 탁월합니다.

설치환경

  • OS: CentOS 7 64bit 1708
  • Kernel: 3.10
  • Zabbix: 3.4
  • mariadb: 5.5.56
  • php: 5.4.16
  • Zabbix-server-mysql: 3.4.5
  • zabbix-web-mysql.noarch: 3.4.5

Zabbix 설치

Zabbix Server

Yum 설치를 위한 EPEL 저장소 추가

# yum install epel-release -y
 
Installed:
epel-release.noarch 0:7-9
 
Complete!

Zabbix Package 설치

# rpm -ivh http://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-1.el7.centos.noarch.rpm
 
Updating / installing...
1:zabbix-release-3.4-1.el7 ################################# [100%]############### webtest11.com End #################

[Zabbix-DB, Zabbix-Web / DB(mariadb) / WEB(Apache) / PHP] yum 으로 한번에 설치

# yum -y install zabbix-server-mysql zabbix-web-mysql mysql mariadb-server httpd php

DB 실행 및 설정

DB 실행 및 프로세스 확인

# systemctl start mariadb
# systemctl enable mariadb
 
Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.
 
# ps -ef | grep mysql
 
mysql 11918 1 0 12:09 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe --basedir=/usr
mysql 12080 11918 1 12:-0 ? 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/log/mariadb/mariadb.log --pid-file=/var/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock
root 12134 11523 0 12:09 tty1 00:00:00 grep --color=auto mysql
 

기본설정 (DB 구동된 상태)

# mysql_secure_installation
 
Enter current password for root (enter for none): (패스워드 입력)
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y

DB 접속 및 설정

  • 프록시는 생략 가능
# mysql -u root -p
Enter password: (패스워드 입력)
 
MariaDB [(none)]> create database zabbix_server;
MariaDB [(none)]> grant all privileges on zabbix_server.* to zabbix@localhost identified by 'ironman';
 
MariaDB [(none)]> create database zabbix_proxy;
MariaDB [(none)]> grant all privileges on zabbix_proxy.* to zabbix@localhost identified by 'ironman';
 
MariaDB [(none)]> flush privileges;
 
MariaDB [(none)]> exit;

Zabbix 테이블값 정보 데이터베이스에 적용

# cd /usr/share/doc/zabbix-server-mysql-3.4.5
# gunzip create.sql.gz
# ls
AUTHORS COPYING ChangeLog NEWS README create.sql (해당파일)
# mysql -u root -p zbx_server < create.sql
Enter password: (DB ROOT 패스워드 입력)
Zabbix Proxy
  • 프록시 생략 가능
# cd /usr/share/doc/zabbix-proxy-mysql-3.4.6
# gunzip schema.sql.gz
# ls
AUTHORS COPYING ChangeLog NEWS README schema.sql (해당파일)
# mysql -u root -p zbx_proxy < schema.sql
Enter password: (DB ROOT 패스워드 입력)

Config 설정

Zabix Config 설정

# vi /etc/zabbix/zabbix_server.conf
 
(맨 아래 추가)
 
DBHost=localhost
DBName=zabbix_server
DBUser=zabbix
DBPassword=ironman
 
:wq (저장)
Zabbix Proxy
  • 프록시 생략 가능
# vi /etc/zabbix/zabbix_proxy.conf
 
(맨 아래 추가)
 
# 0 - active mode
# 1 - passive mode
ProxyMode=0
Server=[서버 아이피 입력]
Hostname=[원하는 호스트명 입력 예) Zabbix proxy]
DBName=zabbix_proxy
DBUser=zabbix
DBPassword=ironman

PHP Config 설정

# vi /etc/php.ini
max_execution_time = 600
max_input_time = 600
memory_limit = 256M
post_max_size = 32M
upload_max_filesize = 16M
date.timezone = Asia/Seoul (앞에 ; 주석제거후 한국시간으로 설정)
:wq (저장)

iptables 방화벽 포트 허용 및 재시작

# CentOS 7
firewall-cmd --permanent --add-port=10050/tcp
firewall-cmd --permanent --add-port=10051/tcp
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload
systemctl restart firewalld
 
# CentOS 6
vi /etc/sysconfig/iptables
 
# Zabbix Agent Port
-A INPUT -p tcp -m tcp --dport 10050 -j ACCEPT
# Zabbix Server Port
-A INPUT -p tcp -m tcp --dport 10051 -j ACCEPT
# Zabbix Web Port
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
# 포트 변경시 그에 맞춰 변경
 
service iptables restart

Apache & Zabbix 서버 구동

Apache Server 구동 및 재부팅시 자동시작 처리

#systemctl start httpd
#systemctl enable httpd

Zabbix Server 구동 및 재부팅시 자동시작 처리

#systemctl start zabbix-server
#systemctl enable zabbix-server

Zabbix 서버 웹으로 접속

  • http://localhost/zabbix
  • 하단의 설정 DB설정/server details 설정 후
  • 관리자 페이지 로그인(admin/zabbix)
  • VM일경우 ifconfig를 통해 inet 주소/zabbix, 연결이 안될경우 NAT 혹은 BRIDGE 방식 등의 관련하여 VM에서 웹서버 접속하는 법 찾기

Configure DB connection

  • 웹 관리자 페이지의 DB 설정을 위의 mariaDB에서 zabbix-server 설정한 것과 동일하게 설정
  • Database type: MySQL
  • Database host: localhost
  • Database port: 0
  • Database name: zabbix_server
  • User: zabbix
  • Password: ironman

Zabbix server details

  • Host: localhost
  • Port: 10051
  • Name: (웹 페이지 접속시 보여주고 싶은 메인페이지 명)

Trouble Shooting

아파치 80 Port 막혀서 웹페이지 안 뜰 경우

# 80 포트 방화벽 추가 확인
# 방화벽 확인
netstat -nlp | grep 80
 
# iptables 등록 확인
iptables -nL | grep 80
 
# 등록되어있을 경우 포트 변경
vi /etc/httpd/con/httpd.conf
Listen 다른 포트
# 다른 포트 방화벽 등록
위의 방화벽 포트 허용 및 재시작 부분 참고

SElinux

# SElinux 해제
vi /etc/sysconfig/selinux
SELINUX=disabled
 
reboot
 
# reboot 해도 SElinux 활성화 되어있을 경우
vi /etc/grub.conf
kernel ..., selinux=0 # 맨뒤에 selinux=0 추가
 
# SElinux 활성화 된 상태에서 등록
 
vi /etc/zabbix/zabbix_agent_t.te
 
# 아래 내용 신규 생성된 파일에 추가 후 저장/종료 (:wq)
module local-zabbix 1.0;
 
require {
    type zabbix_agent_t;
    class process setrlimit;
}
 
#============= zabbix_agent_t ==============
allow zabbix_agent_t self:process setrlimit;
 
:wq
 
semanage permissive -a zabbix_agent_t

Zabbix Agent Install Manual (자빅스 에이전트 설치 매뉴얼)

Linux Install

Zabbix Agent

Yum 설치를 위한 EPEL 저장소 추가

# yum install epel-release -y
 
Installed:
epel-release.noarch 0:7-9
 
Complete!

Zabbix Package 설치

rpm -ivh http://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-1.el7.centos.noarch.rpm
 
Updating / installing...
1:zabbix-release-3.4-1.el7 ################################# [100%]############### webtest11.com End #################

Zabbix Agent 설치

yum -y install zabbix-agent

설정

vi /etc/zabbix/zabbix_agentd.conf
 
Server=Zabbix Server IP
# 기본 포트는 10050

Windows Install

Zabbix Agent

다운로드

설치

  • 다운로드 받은 파일 압축을 풀면 bin, conf 폴더가 존재
  • bin 폴더에서 운영체제에 맞는 32비트 또는 64비트 폴더 안의 내용을 복사 후 c:\zabbix 에 복사
  • conf 폴더째로 c:\zabbix 에 복사
  • 커맨드창 실행
> cd c:\zabbix
> zabbix_agentd.exe -c C:\zabbix\conf\zabbix_agentd.win.conf -i

설정

  • conf\zabbix_agentd.conf 에디터로 열기
Server IP = Zabbix Server IP
Server Active IP = Zabbix Server IP
Host Name = Host Name you wrote in host configuration in Web Frontend

실행

  • 윈도우 제어판 - 서비스 - Zabbix Agent 시작


+ Recent posts