package com.sample;
import java.util.concurrent.TimeUnit;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import lombok.extern.slf4j.Slf4j;

/**
 * Spring RestTemplate 샘플
 *  - 타임아웃 및 pool설정 등의 튜닝버전 
 *
 * @author 
 */
@Slf4j
public class RestTemplateSample {
     private static final String REQ_URL_1 = "https://테스트URL 1번째";
     private static final String REQ_URL_2 = "https://테스트URL 2번째";
    
    private static RestTemplate restTemplate = new RestTemplate();
     
    public static void init() {
          log.info("== Start : restTemplate 초기화");
          HttpComponentsClientHttpRequestFactory crf = new HttpComponentsClientHttpRequestFactory();
          crf.setReadTimeout(7000); //읽기시간초과 타임아웃
          crf.setConnectTimeout(7000); //연결시간초과 타임아웃
          // @formatter:off
          HttpClient httpClient = HttpClientBuilder.create()
               .setMaxConnTotal(300) //커넥션풀적용(최대 오픈되는 커넥션 수)
               .setMaxConnPerRoute(50) //커넥션풀적용(IP:포트 1쌍에 대해 수행 할 연결 수제한)
               .evictIdleConnections(2000L, TimeUnit.MILLISECONDS) //서버에서 keepalive시간동안 미 사용한 커넥션을 죽이는 등의 케이스 방어로 idle커넥션을 주기적으로 지움
               .build();
          crf.setHttpClient(httpClient);
          // @formatter:on
          restTemplate.setRequestFactory(crf);
          log.info("== end : restTemplate 초기화\n\n");
     }
     /**
      * Spring RestTemplate 샘플
      *  - 타임아웃 및 pool설정 등의 튜닝버전
      *  - https URL호출 테스트시, 로그에 SSLConnectionSocketFactory 존재 유무 등을 확인하면 pool이 활용되어 https three hand shake가 발생하는지 알 수 있음
      * 
      * @param args
      * @throws Exception
      */
     public static void main(String[] args) throws Exception {
          init();
          int testReqCnt = 3; //테스트 호출 횟수
          //1번째 요청시 커넥션을 맺어서 pool에 넣고, 2번째 요청부터는 pool을 재사용(로그를 보면 ssl핸드쉐이크 부분이 2번째에서는 없음)
          for (int i = 1; i <= testReqCnt; i++) {
               System.out.println("\n\n" + i + "번째 요청 시작");
               log.info("\n\nURL:{}의 {} 번째 결과. {}\n\n\n", REQ_URL_1, i, restTemplate.getForObject(REQ_URL_1, String.class));
               //evictIdleConnections 확인시 주석 풀어서 실행=> 로그에 "Closing connections idle longer than 2000 MILLISECONDS" 확인 됨
               Thread.sleep(3000);
               if (i != testReqCnt) {
                    log.info("\n\n3초 sleep 후 idleConnection이 pool에서 제거된 후 해당URl을 재 요청해봄\n\n");
               }
          }
          System.out.println("\n\n\n\n");
          System.out.println("=== 2번째 URL호출 테스트 시작 ===");
          for (int i = 1; i <= testReqCnt; i++) {
               System.out.println("\n\n" + i + "번째 요청 시작");
               log.info("\n\nURL:{}의 {} 번째 결과. {}\n\n\n", REQ_URL_2, i, restTemplate.getForObject(REQ_URL_2, String.class));
          }
          System.out.println("\n\n\n\n");
          System.out.println("1번째 URL 재 호출해봄");
          log.info("\n\nURL:{}의결과. {}\n", REQ_URL_1, restTemplate.getForObject(REQ_URL_1, String.class));
     }
}


* 기존 몽고 3.x 버전 설치문서를 기반으로 작성해서 몇 가지는 틀릴 수 있습니다.
참고로, 4.x에서는 기존 3.x에서 남아있던 소스를 많이 제거해서 성능적인 부분이 많이 개선되었으며, secondary에서 read 때 lock부분이 변경되어(복제 적용 중에 읽기가 허용됨) 대용량의 서비스에 더 좋아진 것 같습니다.

참고 

#OS튜닝
# nofile 및 nprc 갯수 튜닝
echo "*    soft nofile  64000" >> /etc/security/limits.conf
echo "*    hard nofile  64000" >> /etc/security/limits.conf
echo "*    soft nproc  64000" >> /etc/security/limits.conf
echo "*    hard nproc  64000" >> /etc/security/limits.conf

vim /etc/security/limits.d/20-nproc.conf 후에 64000으로 변경

Run the sysctl command below to apply the changed limits to the system:
sysctl -p

ulimit -a 명령어로 확인 가능


기타 
 - system service 의 resource limits들은 /etc/systemd/system.conf 여기에 설정해야 함

# repo 추가
vi /etc/yum.repos.d/mongodb-org-4.0.repo 이후 아래 입력

[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc

# 설치
yum install -y mongodb-org

# 기본 설정 작업
#huge 설정
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo never > /sys/kernel/mm/transparent_hugepage/enabled

#재 부팅시 자동으로 시작(필요시)
chkconfig mongod on

#몽고 데이터 저장 디렉토리 생성 및 mongod계정의 소유로 변경(예)
mkdir -p /data/mongo/repl_0
chown -R mongod:mongod /data


# 몽고 시작
#몽고 서비스 시작
systemctl start mongod

#몽고 프롬프트에 접속
mongo


#참고 : 몽고 삭제
systemctl stop mongod

#Remove any MongoDB packages that you had previously installed.
yum erase $(rpm -qa | grep mongodb-org)

#Remove MongoDB databases and log files.
rm -rf /var/log/mongodb
rm -rf /var/lib/mongo

#필요시
rm -rf /data


#참고 : 몽고 설정(/etc/mongod.conf)
     특정파일의 config 파일을 이용하려면 mongod --config 파일경로 (이 명령어로는 root로 프로세스가 실행되니 필요시 init.d 등을 이용할수도 있음)
vi /etc/mongod.conf 후 아래샘플을 참고하여 수정해서 사용

systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
  quiet: true

storage:
  dbPath: /data/mongo/repl_0
  journal:
    enabled: true
  #wiredTiger:
    #engineConfig:
      #cacheSizeGB: 0.5


net:
  port: 27017
  #bindIp: 127.0.0.1  # Listen to local interface only, comment to listen on all interfaces. (주석으로 막으면 모든 IP에서 접속 가능. AWS에서는 SG로 보안처리 하고 있어서 편의상 모두 허용하기도 함)


replication:
  replSetName: repl_set



#참고 : 몽고 replica 설정
primary가 될 서버에서 몽고 콘솔로 접속 : mongo

#Replica set 초기화
rs.initiate()

#Secondary 노드 추가
rs.add("secondary장비의 IP:27017")

#Arbiter 노드 추가
rs.add( { host: "arbiter장비IP:27017", arbiterOnly: true } )


# 잘 저장되는지 테스트
use testdb
db.test_collection.insert({'msg':'test message'})
db.test_collection.find()


#Secondary에서는 아래 명령 실행 후 조회해 보면 됨
db.slaveOk(true)



#참고 - 1개 장비에 여러개의 몽고데몬을 실행시켜야할 경우
1개의 몽고DB를 설치하면 아래에 service 파일이 생성됨
/etc/systemd/system/multi-user.target.wants

해당 디렉토리의 mongod.service 심볼릭링크가 가리키는 파일(/usr/lib/systemd/system/mongod.service) 이 하나의 데몬 파일

/usr/lib/systemd/system/mongod.service 파일을 복사하여 한개 더 생성(ex. cp /usr/lib/systemd/system/mongod.service /usr/lib/systemd/system/mongod2.service)
복사한 해당 파일의 내용을 적당히 수정

예)
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target

[Service]
User=mongod
Group=mongod
Environment="OPTIONS=--quiet -f /etc/mongod2.conf"
ExecStart=/usr/bin/mongod $OPTIONS run
ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb2
ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb2
ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb2
PermissionsStartOnly=true
PIDFile=/var/run/mongodb2/mongod.pid
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for for mongod as specified in

[Install]
WantedBy=multi-user.target


설정들 데몬에 반영
systemctl daemon-reload


#참고 mongod.conf 1번

# mongod.conf

# for documentation of all options, see:

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
  quiet: true

# Where and how to store data.
storage:
  dbPath: /data/mongo/repl_0
  journal:
    enabled: true
#  engine:
#  mmapv1:
  wiredTiger:
     engineConfig:
          cacheSizeGB: 0.4


# how the process runs
processManagement:
  fork: true  # fork and run in background
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile

# network interfaces
net:
  port: 27017
 # bindIp: 127.0.0.1  # Listen to local interface only, comment to listen on all interfaces.


#security:

#operationProfiling:

#replication:
replication:
  replSetName: repl_set

#sharding:

## Enterprise-Only Options

#auditLog:

#snmp:




#참고 mongod2.conf(1개 서버에 2개 프로세스 동시에 띄울때 사용할 목적)
# mongod.conf

# for documentation of all options, see:

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod2.log
#  quiet: true

# Where and how to store data.
storage:
  dbPath: /data/mongo/repl_1
  journal:
    enabled: true
#  engine:
#  mmapv1:
  wiredTiger:
     engineConfig:
          cacheSizeGB: 0.4


# how the process runs
processManagement:
  fork: true  # fork and run in background
  pidFilePath: /var/run/mongodb2/mongod.pid  # location of pidfile

# network interfaces
net:
  port: 27018
 # bindIp: 127.0.0.1  # Listen to local interface only, comment to listen on all interfaces.


#security:

#operationProfiling:

#replication:
replication:
  replSetName: repl_set

#sharding:

## Enterprise-Only Options

#auditLog:

#snmp:



 

메모용 글입니다.
 
1. mysql은 Clustered Index가 기본이고 모든 테이블에 존재함을 감안
2. 가능하면 불필요한 secondary index 추가는 안함(필요성에 의해서 IDX_uid가 추가되었지만)
3. 파티션 add가 안되어서 서비스 장애가 발생하는걸 방어하기 위해서 MAXVALUE 처리
4. 월 파티션으로 생성
 - 필요에 따라서 일 파티션으로 줄여도됨. 다만 mysql 파티션 최대 갯수의 제한이 있으니 서비스 특성 고민
 
 

 

내용
 
  1. DDL
-- 로그인 이력 테이블 추가(파티션 추가가 안되었을 때 방어로직으로 MAXVALUE 파티션까지 처리 해둠)
CREATE TABLE `login_hist_test`(  
  `login_ymdt` DATETIME NOT NULL COMMENT '로그인일시',
  `uid` BIGINT(19) UNSIGNED NOT NULL COMMENT '유저ID',  
  `req_ip` VARCHAR(50) NOT NULL COMMENT '요청자IP',
  `device_model` VARCHAR(100) COMMENT '요청 디바이스 모델',
  `country` VARCHAR(6) COMMENT 'Country 값',
  PRIMARY KEY (`login_ymdt`, `uid`),  
  INDEX `IDX_uid` (`uid`)
) COMMENT='로그인이력'
PARTITION BY RANGE (TO_DAYS(login_ymdt))
(
PARTITION P_2018_11 VALUES LESS THAN (TO_DAYS('2018-12-01')),
PARTITION P_max VALUES LESS THAN (MAXVALUE)
);
 
-- 파티션 추가(REORGANIZE로 방어 파티션 P_max까지 수정)
ALTER TABLE login_hist_test REORGANIZE PARTITION P_max INTO (
PARTITION P_2018_12 VALUES LESS THAN (TO_DAYS('2019-01-01')),
PARTITION P_max VALUES LESS THAN MAXVALUE
);
 
 
  1. 결과
    1. 최초 테이블 생성 결과
    2. 파티션 추가
 
 
 

 



원인 : 톰캣이 sessionId 등에서 필요한 난수를 생성할때 SecureRandom클래스에 의존되는데, 이 클래스는 디폴트로 /dev/random을 사용(자원 고갈되면 지연 발생할 수 있음)


해결 : urandom을 사용하도록 처리.

       -Djava.security.egd=file:/dev/./urandom 처리하거나 jre설치된 하위 디렉토리의 java.security 파일에서 수정



참고 : https://wiki.apache.org/tomcat/HowTo/FasterStartUp

페이스북은 캐싱문제로 바로 안나올 수 있음

이런경우 아래 페이스북 사이트에서 공유 디버거로 캐시를 활성화 시켜주면 됩니다.

 

1. https://developers.facebook.com/tools/debug/
 - 참고 : https://developers.facebook.com/docs/sharing/best-practices?locale=ko_KR

 - 주의: og 태그 이미지 파일을 페이스북은 소문자로 읽어가는듯? 이미지 파일을 소문자로 사용하는걸 추천(예. AWS S3에 소문자 파일로 업로드해둠)

 

2. 트위터 Card validator : https://cards-dev.twitter.com/validator 

 

3. 라인 메신저
 - http://poker.line.naver.jp/

 

4. 카카오 메신저

 - https://developers.kakao.com/tool/clear/og

 

기타 SNS업체들 참고 : https://trendw.kr/2015-09251296.t1m

 

 

'기타' 카테고리의 다른 글

메모 - 아파치 OFBIZ  (0) 2019.05.23
nginx limit (rate) 기능으로 요청 트래픽 제한  (1) 2019.01.04
웹 취약점 진단도구 메모  (0) 2018.07.09
좋은 코드 작성하기 참고  (0) 2018.06.29
nginx basic auth 적용  (0) 2017.12.05

웹 취약점 진단도구 메모

진단 도구

용 도

sqlmap

SQL 인젝션 자동화 툴

Fiddler

HTTP 파라미터 변경 및 조작시 사용

EditthisCookie

쿠키값 변조 및 확인 가능

WireShark

네트워크 패킷 모니터링 사용

Burp Suite

HTTP 파라미터 변경 및 조작시 사용


 

일하면서 후배에게 좋은 코드에 대해서 이런저런 얘기들을 해줬었는데,

글로 정리해뒀길래 링크해둡니다.


http://blog.geun.kr/243



P.s 

 - 해당 내용은 제 개인적인 생각이 반영되어 있습니다.

 - 개인적으로는 "7. 잘된 소스 보기" 가 실력을 올리는 가장 빠른 방법인 것도 같습니다.


public class GCTest {
     private final static int ALLOC_SIZE = (int)(Runtime.getRuntime().maxMemory() * 0.50);

     public static void main(String[] args) throws InterruptedException {
          System.out.println("Before first allocation");
          byte[] b = new byte[ALLOC_SIZE];
          b = null; //객체 레퍼런스 주소를 반환 처리함으로써 GC대상에 포함되게 됨(null 처리 안하면 full gc 발생하면서 프로그램 종료됨)
          System.out.println("After first allocation");
          //        Thread.sleep(5000);
          System.out.println("Before second allocation");
          byte[] b2 = new byte[ALLOC_SIZE];
          System.out.println("After second allocation");
     }
}

+ Recent posts