반응형
반응형

사전에 apm (httpd, php, mysql)이 설치되어 있어야 한다.

httpd를 yum으로 설치했다는 가정하에 작성


1. PhpMyAdmin 설치


httpd document root로 이동

$ cd /var/html/www


phpmyadmin을 다운받음

$ wget https://files.phpmyadmin.net/phpMyAdmin/4.4.12/phpMyAdmin-4.4.12-all-languages.zip


unzip 해준다. (unzip이 없으면 yum으로 설치)

$ unzip phpMyAdmin-4.4.12-all-languages.zip


httpd 서비스를 재시작 후 브라우저에서 http://localhost/phpMyAdmin 확인

$ service httpd restart



2. 세부 설정


phpMyAdmin root에 보면, config.sample.inc.php 파일이 있는데, 

해당 파일을 copy후 config directory를 생성하여,  config.inc.php로 rename후 생성된 directory에 넣어준다.

$ cd /var/html/www/phpMyAdmin
$ mkdir config
$ cp config.sample.inc.php ./config/config.inc.php

브라우저에서 setup url을 호출하여 세부설정을 진행한다. (http://localhost/phpMyAdmin/setup)


※ mysql 계정설정에서 사전에 phpMyAdmin이 설치되어 있는 ip에 대해서 권한설정을 해주어야 한다.

ex) phpMyAdmin이 localhost1에 설치되어 있고, abcd라는 계정으로 모든 DB에 접근하고 싶은 경우 아래와 같이 한다.

mysql> GRANT ALL PRIVILEGES ON *.* TO abcd@localhost1 IDENTIFIED BY 'password'


※ mysql 서버를 여러대 관리하고 싶은 경우, setup에서 등록한 서버 목록을 선택할 수 있게끔 설정이 가능하다.

생성해두었던 config폴더에 들어가서, config.inc.php 파일만 바로 위 depth로 끄집어 내고, config 폴더를 날려버린 후에

config.inc.php 파일을 열어 아래와 같은 옵션을 추가해주면 된다.

$cfg['DisplayServersList'] = TRUE;
반응형

'개발 > Database' 카테고리의 다른 글

[MSSQL] SET ANSI_NULLS  (0) 2016.06.10
[Mysql] 5.5 패키지 설치 (CentOS 6.5)  (0) 2016.06.10
[Mysql] local-infile  (0) 2016.06.10
[MongoDB] 기본 세팅 + ReplicaSet 구성 및 Arbiter  (0) 2016.06.10
[Mysql] group_concat  (0) 2016.06.10
,
반응형

게임DB에서 데이터를 추출하여, 통계를 위한 DB로 보내야 하는 경우가 생겼다.


스크립트 언어로 개발하는게 귀찮아서, 그냥 mysql 터미널 명령어로 해결하기로 했음.

-e 옵션으로 쿼리 날려서 txt파일로 끄집어낸 후,

통계 DB에 해당 파일을 import시켜야 하는데, 이런 경우 local-infile이라는 옵션을 안주면,

원격지에 가서 파일을 검색한다.


이런 경우 local-infile=1옵션을 추가로 주면, 해당 머신에서 찾아서 import시켜준다. 

반응형
,
반응형

MongoDB 세팅을 해볼 기회가 생겨서, Auto FailOver를 지원한다는 ReplicaSet 구성부터 살펴보기로 하였다.


기본적으로 아무세팅도 건들지 않고, 서비스하는 경우 3.0버전 기준으로 Locking은 Read / Write Lock 형태로 Collection에 Lock이 걸리게 되기 때문에, 데이터 변동이 자주 일어나는 게임 서비스에는 부적합하다. 하지만, 3.0버전부터는 WiredTiger engine을 사용하여 Document 단위의 Lock을 지원하며, 현재 최신버전인 3.2버전부터는 WiredTiger engine을 기본 Storage Engine으로 제공하여, Document Lock을 지원한다.


자세한 설명은 아래 링크에 나와있다.

https://docs.mongodb.org/manual/core/storage-engines/


기본 Engine으로 제공할 정도면, 충분히 안정적이 되었다는 것이겠고, 앞으로 MongoDB는 3.2버전이상을 사용하는 것으로 하면 도움이 될 것 같다.


커널튜닝도 조금 필요하다. 

Ubuntu머신 기준으로 /sys/kernel/mm/transparent_hugepage/enabled

/sys/kernel/mm/transparent_hugepage/defrag 값이 always로 되어 있으면, Mongod데몬이 올라가면서 warning 메시지를 뱉게 된다.


Never로 세팅을 해주게 되면, 해당 Warning들이 없어지게 되며, 데이터베이스의 경우 저 옵션이 always로 되어 있는 경우에 예측하기 힘든 System Hang현상이 올 수도 있다고 한다.

아래 링크를 참고했음.

http://infoages.tistory.com/1297


여기까지 했으면, 중요하게 짚고 넘어가야할 설정에 대해서는 마무리 된 것 같고, 

다음으로 ReplicaSet에 대해 알아보자.


각 노드에서 mongod.conf (apt-get 설치 기준 default 위치 /etc/mongod.conf)를 열어서,

아래와 같은 내용을 추가한다.


replication:
   oplogSizeMB: 2048       // mysql의 binlog와 비슷한 개념으로, 데이터 복원 시 사용됨. 
                                // (숫자를 지정하지 않으면, 
                                //무한정 커지기 때문에 값을 지정해주는 것을 권장한다고 한다.)
   replSetName: rs-uvm      // replicaSet의 이름


각 노드들의 데몬을 재시작 한다.


마스터가 될 노드로 들어가서, mongo를 입력하여 command line으로 들어가서, 아래와 같은 명령어를 입력한다. (syntax만 맞다면 json 포맷이 마무리 되기 전까지 엔터를 쳐서 연결해도 문제 없다.)


# replicaSet의 정보를 config 변수에 담는다.


>  config = {
... _id: 'rs-uvm',
... members: [ {_id:0, host:'192.168.33.13:27017'},
... {_id:1, host:'192.168.33.14:27017'},
... {_id:2, host:'192.168.33.15:27017'}]}


# replicaSet을 config변수의 정보를 참조하여 start시킨다. (이때부터 각 노드의 데이터에 대해 복제가 시작됨)

> rs.initiate(config);


※ mongo에서 지원하는 replicaSet에 대한 auto FailOver의 경우 기본적으로 노드가 홀수로 구성이 되어야 한다. 그 이유는 master가 죽은 경우 나머지 노드들끼리 투표를 하여 누가 master가 될지를 정해야하는데, master를 제외한 노드가 하나밖에 없는 경우 어떤 장비가 더 적합한지 내부에서 판단하여 투표를 해서 master로 승격을 시켜야 하는데, 하나 밖에 없는 경우 그 기준이 애매하기 때문에 그렇다. 이런 경우 Arbiter노드라는 노드를 설정하여, 실제로는 데이터가 복제되지 않는 노드지만, master 장애 시 투표에 참여할 수 있게끔 구성이 가능하다. (장비가 부족하거나, 굳이 장비를 3대까지 세팅할 필요가 없는 경우에 유용)


Arbiter 노드는 위에 config 변수에 노드에 대한 정보를 넣을 때, arbiterOnly라는 element를 추가하여 true로 설정해주면 가능하다! ("arbiterOnly" : true)


아직 제대로 운영을 해본적은 없어서, 나머지 정보는 운영 후 다른 포스팅에 추가하는걸로.. 


테스트만 해보고 작성한거라, 잘못된 내용이 있을 수 있으니, 테클은 언제든 환영!

반응형

'개발 > Database' 카테고리의 다른 글

[Mysql] 5.5 패키지 설치 (CentOS 6.5)  (0) 2016.06.10
[Mysql] phpMyAdmin 여러대의 Mysql 서버관리  (0) 2016.06.10
[Mysql] local-infile  (0) 2016.06.10
[Mysql] group_concat  (0) 2016.06.10
[MongoDB] Log Rotate  (0) 2016.06.10
,
반응형

비슷한 구조를 가진 Table이 이름만 다른채로 여러개로 퍼져서 운영되는 경우,

join, union을 사용해서 데이터를 추출하려고 해도, Table이 많아지면 결국 노가다가 된다.


이런 경우 GROUP_CONCAT을 이용하면 유용하다.


# 결과 쿼리가 들어갈 변수 선언
SET @resultQuery = NULL;

# GROUP_CONCAT으로 쿼리 문자열에 쿼리문을 생성하여 등록
SELECT 
    GROUP_CONCAT(
    DISTINCT      // 문자열이 중복된 경우 제거해주는 옵션인 듯)
    CONCAT('(select 컬렴명1, 컬럼명2 from ', table_name, ' limit 1)') 
    SEPARATOR '\r\nUNION\r\n' // 각 쿼리를 뭘로 연결할 것인지 (센스있게 마지막쿼리엔 붙지 않음)
    )
INTO @resultQuery
FROM information_schema.TABLES
WHERE table_name LIKE '테이블명%';      // 본인의 경우 prefix가 같아서 이렇게 사용

# 문자열로 쿼리가 등록된 상황이므로, prepare statement를 이용하여 실행해준다. (select로 하게되면, 문자열 자체가 결과로 나오게됨)
PREPARE stmt FROM @resultQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;



이슈1) UNION 문과 limit문을 같이 사용하는 경우, 쿼리에 괄호가 누락되면 제대로 동작을 하지 않는다. 각 쿼리에 limit문이 들어간다면, 괄호문을 꼭 넣어주도록 하자.


이슈2) 아마 쿼리문이 1024 byte를 넘어가면, 짤리는 현상이 생겨서 실행이 제대로 되지 않을 것이다.


이런 경우 아래 명령어로 group_concat의 최대 사이즈를 늘려주자. (varchar니깐 65535까지 되는 것 같음)


SET SESSION group_concat_max_len = 65535;


DBA에게 위에 요구사항을 만족하는 쿼리 요구를 했더니, 엑셀을 열더니 노가다 방법을 알려주시더군.. 뭐 그럴수있지;

반응형
,
반응형

몽고 DB의 Replication을 이용하는 경우, 로그 레벨을 production 레벨로 올려도 

쓸데없이 Info 로그가 찍히는 경우가 발생을 한다.


서비스를 오래하는 경우 무자비하게 파일이 커지기 때문에, Rotate기능을 찾던 중,

Mongo Shell에서 커맨드 한번으로 Rotate가 되는 기능을 찾을 수 있었다.


아래와 같이 입력하면 된다.


mongo> use admin
mongo> db.runCommand( { logRotate : 1} )


linux command line이나 bash에서 실행하고 싶은 경우,

위 커맨드를 js 파일로 만들어서 실행이 가능하다.

만약 위 명령어가 rotate.js 라고 가정해보면 아래와 같다.

$ mongo < rotate.js


반응형
,
반응형
요즘 게임 운영 페이지 등을 만드느라, script를 짤일이 자주 생기네요.
전 java는 자신있지만.. 스크립트와 화면 관련된 속성 값은 정말 자신이 없더군요.
최근에 iframe에 웹페이지를 링크시켜서 보여줄 일이 생겨서 찾아 보는 도중에
마침 테두리때문에 고민이었는데, 투명으로 표시해주는 자료를 찾아서 아래와 같이 가져왔답니다. ^^
 
보통은
<iframe allowTransparency = "true" /> 이렇게들 사용하시는데
이것은 W3C Validation (웹표준) 에 어긋나는 문법이라고들 하더군요.
 
따라서 아래와 같이 onload시에 모든 iframe태그를 찾아서 속성을 넣어주는 방식으로 우회해서 사용한답니다.
 


<script type="text/javascript">
onload = function() {
var frames = document.getElementsByTagName('iframe');   // iframe태그를 하고 있는 모든 객체를 찾는다.
for(var i = 0; i < frames.length; i++)  {
frames[i].setAttribute("allowTransparency","true");  // allowTransparency 속성을 true로 만든다.
        }
}
</script>
반응형
,
반응형

최초 초기화 시에 .ajaxStart(), .ajaxStop() 이벤트 등록만으로 구현이 가능하다.

로딩바 이미지는 첨부파일 참고


아래와 같이 div태그를 하나 만들어서 이미지를 등록해두고,


<div id="viewLoading">
 <img src="/img/viewLoading.gif" />
</div>


아래와 같이 스타일 태그를 지정해서 가운데서 돌아가도록 만들어둔다.


<style type="text/css">
div#viewLoading {
        text-align: center;
        padding-top: 70px;
        background: #FFFFF0;
        filter: alpha(opacity=60);
        opacity: alpha*0.6;
}
</style>


이제 로딩바가 항상 돌아가는 상황이 만들어졌고,

최초 진입 시에는 돌아가면 안되기 때문에 hide를 해주고, 위에서 언급한 .ajaxStart(), .ajaxStop() 이벤트를 등록해보자.


<script>
$(document).ready(function() {    // 최초 진입 시 로딩바 div를 hide시킨다.
 $('#viewLoading').hide();
})
.ajaxStart(function() {         // ajax 통신 시작 callback (로딩바 show)
 console.log('start');
      $('#viewLoading').show();
})
.ajaxStop(function() {        // ajax 통신 완료 callback (로딩바 hide)
 console.log('end');      
       $('#viewLoading').hide();
}); 
</script>



이제 $.ajax() 함수를 호출할때마다 로딩바가 돌아가는 것을 볼 수 있다.

IE, Chrome에서 테스트 결과 문제없음.


오랫만에, front-end를 접해보니 하루종일 삽질함;;

반응형
,
반응형

Spring Controller에서 ModelAndView에 addObject로 int속성이 붙은 클래스를 넘겨서

list형태로 select box의 option value에 int속성을 넣어주어야 할 일이 있었는데..


<#list>를 이용해서 forLoop을 돌면서 숫자에 콤마를 붙여버리는 문제가 있었다.

ex) 40000 -> 40,000로 변환되어 표시됨.


해당 값을 javaScript에서는 String으로 인식을 하고, Controller단 API에서도 String으로 인식을 하게 된다.


이런 경우 ?c옵션으로 해결이 가능하다.

아래와 같이 해주면, 원하는대로 값이 표시된다.

<#list tests as test>
     ${test?c}
</#list>
반응형
,
반응형

Spring Boot가 아닌 환경에서는 기존처럼 xml만들고, web.xml 수정하고, decorator.html만 만들어서

대충 추가만 해주면 되는데,


Spring Boot는 내부적으로 해주는 일이 많다보니,

FilterRegistrationBean이라는 것을 사용해서, SiteMesh설정이 되어 있는 Filter를 등록해주어야 한다.


SiteMeshFilter 설정

public class SiteMeshFilter extends ConfigurableSiteMeshFilter {

    @Override
    protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
       builder.addDecoratorPath("/*", "/decorator/decorator.ftl");
    }
}




Spring Boot Application 설정


@SpringBootApplication
public class WebApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }
    
    @Bean
    public FilterRegistrationBean siteMeshFilter() {
        FilterRegistrationBean filter = new FilterRegistrationBean();
        filter.setFilter(new SiteMeshFilter());
  
        return filter;
    }
}
별도의 xml이 필요없어서 좋다.


반응형
,
반응형

플랫폼 팀이 해야할 실시간 동접 그래프 구현을 안해주길래..

직접 만들어보는걸로 하고..

이것저것 찾다보니 jquery를 이용해서 차트를 그릴 수 있는 훌륭한 라이브러리인 jqplot을 사용해보기로 하였다.

http://www.jqplot.com/

front쪽은 잘 만들어진거 잘 가져다만 써도 거의 모든게 해결이 되는것 같음..


일단 기본 프레임워크 Spring Boot로 잡고, ui표현은 가장 익숙한 jquery + freemarker를 사용하기로 하였다.


가지고 있는 API가 현재 서버에 소켓이 몇 개 붙어있는지 정도만 가져올 수 있는 API였기 때문에,

지난 시간의 동접 파악을 위해 dbms를 이용해야 한다.


dbms는 mysql 깔고 이리저리 귀찮게 하지 않기 위해, embedded hsqldb를 사용하였고,

쿼리 작성도 귀찮아서 spring jpa를 사용하였다. 

findAll을 이용해서 데이터를 가져오려고 생각해보니, 데이터 제한이 있어야 될 것 같아서 날짜로 내림차순 후 top keyword를 사용하여

개수 제한을 두어, 데이터 량이 넘치면 차트가 서서히 밀리도록 구현함.


이제 문제는 데이터 수집인데.. 이것도 별도 데몬을 띄워서 스케줄링으로 돌리긴 너무나도 귀찮아서

Spring Boot가 올라갈 때 Quartz세팅을 하여, 올라가는 순간부터 API를 호출하여 데이터를 수집하는 방식으로 하였다.


이제 남은건 차트 표현인데, 너무나도 간단하게 잘 만들어져 있음.


최초에 API를 통해서 x, y좌표의 데이터를 배열형식으로 리턴받아, jqplot에 전달을 하고,

setTimeout + ajax call을 적용하여, ui단에서 실시간으로 갱신이 되도록 하였다.


위에서 설명한걸 소스로 표현하면, 대충 아래와 같은 느낌임. (UI단만;)


<link href="css/jquery.jqplot.min.css" rel="stylesheet" />
 
<script src="js/jquery-2.1.4.min.js"></script> 
<script src="js/jquery.jqplot.min.js"></script>
<script src="js/jqplot.dateAxisRenderer.min.js"></script>
<script src="js/jqplot.highlighter.min.js"></script>

<script>
  var plot;
  var chartData = [[0,0]];    // 초기화를 []로 해주면 차트가 안그려짐. ㅠㅠ
  
  $(document).ready(function() {
      renderChart();
      update();
  });
  
  function renderChart() {
      plot = $.jqplot('chart', [chartData], {
          title: 'Current User'
          , axes: {
              xaxis: {
                 renderer:$.jqplot.DateAxisRenderer     // X축을 날짜로 표현할 것이다.
                 , tickOptions: {
                     formatString: '%m-%d %H:%M:%S'   // 이건 다 아시는 dateformat임.
                     , showLabel: false           // 데이터가 많아지면 X축이 보이지도 않을 정도가 되서 제거
                     , showGridline: false        // 데이터 많아지면 세로라인때문에 눈이 아프더군.. 그래서 제거
                 }
                , tickInterval:'5 minutes' // X축 간격을 5분 주기로 띄운다.     
             }
          }
          , series: [{
             color: '#5FAB78'
          }]
          , highlighter: {        // X축이 뭔지는 알아야 되니깐 마우스 오버 기능을 활용하기 위해 추가함
              show: true,
              sizeAdjust: 7.5           
          }
          , cursor: {
              show: false
          }
      });
  }
  
  function getChartData() {
      $.ajax({
         url: 'getCurrentUser'
         , type: 'GET'
         , success: function(data, textStatus, jqXHR) {
             chartData = data;
           
             plot = $.jqplot('chart', [chartData], {
               title: 'Current User'
               , axes: {
                   xaxis: {
                      renderer:$.jqplot.DateAxisRenderer
                      , tickOptions: {
                          formatString: '%m-%d %H:%M:%S'
                          , showLabel: false
                          , showGridline: false
                      }
                      , tickInterval:'5 minutes'
                   }             
               }
               , series: [{
                   color: '#5FAB78'
               }]
               , highlighter:{
                   show: true,
                   sizeAdjust: 7.5           
               }
               , cursor: {
                   show: false
               }
             }).replot();    // 다시 그릴 땐 replot을 활용해야 함.
          }
          , error: function(e) {
             console.log(e);
          }
      });
  }
  
  function update() {
      getChartData();
      setTimeout(update, 1000 * 60 * 2);      // 2분 주기로 갱신
  }
 </script>



body에는 <div id="chart"></div> 이런거 하나 추가해주면 된다.


주석 달려있는 것들만 삽질한 부분이고, 나머지는 그냥 아무거나 붙여다가 적용해도 문제없음.


생각대로 표시가 안되는게 있으면, 무조건 js 파일 누락이니, 다시 확인해야 함. 

반응형
,
반응형