반응형

Openssl SSL 인증서 만들기 / 웹서버(apache2) SSL 설정

- pem, key 파일 생성

; 서버 개인키 발급
openssl genrsa -des3 -out server.key 2048

; 인증요청서 생성 (csr)
openssl req -new -key server.key -out server.csr
!!!! CN 입력(Common Name)시에 맵핑할 도메인을 적는다. www.abc.com !!!
; kr seoul seoul mycompany myteam www.abc.com 나머지는계속엔터.

; 개인키에서 패스워드 제거 (키에 패스워드가 있으면 아파치 구동시마다 물어보니
; 패스워드 지우면 편리, 기존 암호화 파일은 org로 백업.)
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key

; 인증서 생성
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
; 이제 key와 crt 파일로 SSL 설정시 사용하면 된다. 또는 pem으로 변경하여 사용. 
; 형식변환
openssl x509 -outform pem -in server.crt -out servercert.pem

아래 두 파일을 사용하면 된다.
server.key
servercert.pem

 

- Apache2 웹서버에 SSL 설정


* 인증서 등록
$vi /etc/apache2/sites-available/default-ssl.conf
; 기존 SSLCertificateFile, SSLCertificateKeyFile 두 줄을 아래와 같이 수정한다. 
; (인증서 파일 경로 확인)

SSLCertificateFile /etc/apache2/servercert.pem
SSLCertificateKeyFile /etc/apache2/server.key
# AJP tomcat 연동을 할 경우에는 JkMount 설정으로 worker 연결한다. 
# JkMount /* myworker

* SSL 활성화
; 아래 커맨드들을 실행한다.

a2enmod ssl
cd /etc/apache2/sites-available
a2ensite default-ssl.conf

; apache2 재시작
systemctl restart apache2
반응형

docker debian apache2 tomcat 연동

도커 환경으로 apache 웹 서버와 뒤에 tomcat WAS를 1개 띄우는 형식. 두 개의 분리된 서버(Web, WAS)
웹 서버는 80포트로 받아서 WAS1에 8010 포트로 연결한다.

데비안으로 할 거라서 먼저 준비 과정이 필요함. 이미지를 만들기 위해 모든 설치과정 커맨드들을 준비해야 한다. 설정 파일들에서 어디를 고칠지 확인.

여기서는 foreground 로 실행할 예정.

test. 준비 과정.

docker run -it -p 80:80 -p 18080:8080 -p 443:443 -p 18443:8443 debian

docker run -it -p 80:80 -p 443:443 -p 18443:8443 myweb

$

apt update
apt install -y curl wget net-tools systemd vim
curl -sSL https://packages.sury.org/apache2/README.txt | bash -x
apt install apache2 libapache2-mod-jk openjdk-11-jre -y

mkdir -p /usr/local
cd /usr/local
wget --no-check-certificate https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.51/bin/apache-tomcat-8.5.51.tar.gz
tar xvfz apache-tomcat-8.5.51.tar.gz
mv apache-tomcat-8.5.51 tomcat8
rm apache-tomcat-8.5.51.tar.gz

-----------------------------

# 도커라 systemctl 커맨드가 안됨. service 커맨드는 작동하네.
service apache2 start
service apache2 status

# 이렇게 실행하면 종료되지 않는다. 
환경변수 세팅 필요.
source /etc/apache2/envars

apachectl -D FOREGROUND
또는
/usr/sbin/apache2 -D FOREGROUND

바로 foreground로 돌리면 경로 없어서 실패가 발생함. 
mkdir -p /var/run/apache2

tomcat docker
http://IP:18080/

apache2
http://IP/

-- 설정 변경 스크립트를 만들기 위해... 
cat -n 000-default.conf ; 줄번호가 출력됨. 오호.. 이런 기능이!

설정파일에서 스트링 변경
worker 설정 경로를 따로 만들어 주었다. 
sed -i 's/libapache2-mod-jk\/workers.properties/apache2\/workers.properties/g' /etc/apache2/mods-available/jk.conf

13번 라인에 insert 하고 싶은데. 아래 baclash 사이에 내용을 쓴다. 
sed -i '줄번호i\내용\' 파일명  ; 줄번호라인 위에 한줄이 삽입됨. 
즉, 추가한 줄이 입력한 줄번호가 된다.

sed -i '13i\ JkMount /* myworker\' 000-default.conf



-- workers.properties
# cat workers.properties
#
workers.tomcat_home = /usr/local/tomcat8
workers.java_home = /usr/lib/jvm/java-11-openjdk-amd64

worker.list = myworker
worker.myworker.port = 8009
worker.myworker.host = mywas1c
worker.myworker.type = ajp13

 


web1 apache2 : myweb1 (HTTP)

root@mobiledeep:/home/psychic/docker/docker_gpms/web# cat Dockerfile
FROM debian

RUN apt update
RUN apt install -y curl wget net-tools systemd vim
RUN curl -sSL https://packages.sury.org/apache2/README.txt | bash -x
RUN apt install apache2 libapache2-mod-jk openjdk-11-jre -y

COPY workers.properties /etc/apache2/workers.properties
RUN sed -i 's/libapache2-mod-jk\/workers.properties/apache2\/workers.properties/g' /etc/apache2/mods-available/jk.conf
RUN sed -i '13i\ JkMount /* myworker\' /etc/apache2/sites-available/000-default.conf

#RUN mkdir -p /usr/local && cd /usr/local && wget --no-check-certificate https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.51/bin/apache-tomcat-8.5.51.tar.gz && tar xvfz apache-tomcat-8.5.51.tar.gz && mv apache-tomcat-8.5.51 tomcat8
#RUN rm /usr/local/apache-tomcat-8.5.51.tar.gz

RUN mkdir -p /var/run/apache2
ENV APACHE_RUN_USER=www-data
ENV APACHE_RUN_GROUP=www-data
ENV APACHE_PID_FILE=/var/run/apache2/apache2.pid
ENV APACHE_RUN_DIR=/var/run/apache2
ENV APACHE_LOCK_DIR=/var/lock/apache2
ENV APACHE_LOG_DIR=/var/log/apache2
ENV export LANG=C

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]
#CMD ["/bin/bash"]

EXPOSE 80
EXPOSE 443

구동 스크립트

root@mobiledeep:/home/psychic/docker/docker_gpms/web# cat startup.sh
# docker build -t myweb1 .
docker rm -f myweb1c
docker run --rm --name myweb1c -it -p 80:80 -p 443:443 --link mywas1c:mywas1c myweb1
  • link 옵션 때문에 tomcat이 먼저 떠 있어서 작동한다.

tomcat 8.5 ; mywas1

root@mobiledeep:/home/psychic/docker/docker_gpms/was# cat Dockerfile
FROM debian

RUN apt update
RUN apt install -y curl wget net-tools systemd vim
RUN apt install openjdk-11-jre -y

RUN mkdir -p /usr/local && cd /usr/local && wget --no-check-certificate https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.51/bin/apache-tomcat-8.5.51.tar.gz && tar xvfz apache-tomcat-8.5.51.tar.gz && mv apache-tomcat-8.5.51 tomcat8 && perl -p -i -e '$.==114 and print " <Connector protocol=\"AJP/1.3\" secretRequired=\"false\" address=\"0.0.0.0\" port=\"8009\" redirectPort=\"8443\" />\n"' /usr/local/tomcat8/conf/server.xml
ENTRYPOINT ["/usr/local/tomcat8/bin/catalina.sh", "run"]

#COPY server.xml /etc/apache2/qauth.conf
#CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]
#CMD ["/bin/bash"]

EXPOSE 8080
EXPOSE 8009
EXPOSE 8443

----
빌드
# docker build -t mywas1 .
  • 구동 스크립트. foreground.
root@mobiledeep:/home/psychic/docker/docker_gpms/was# cat startup.sh
# docker build -t mywas1 .
docker rm -f mywas1c
docker run --rm --name mywas1c  -it -p 8080:8080 -p 8443:8443 -p 8009:8009 mywas1

web2 : SSL 설정 (myweb2)

  • SSL 설정은 web 만 하면 된다.
  • SSL 인증서는 테스트용으로 self-sign 인증서를 만들면 된다. (openssl 커맨드로 쉽게 만들 수 있음.)
  • 필요한 커맨드 조사
기존에서 더 작업해야 할 것들.

sed -i '32,33d' /etc/apache2/sites-available/default-ssl.conf
sed -i '32i\SSLCertificateFile /etc/apache2/servercert.pem\' /etc/apache2/sites-available/default-ssl.conf
sed -i '33i\SSLCertificateKeyFile /etc/apache2/server.key\' /etc/apache2/sites-available/default-ssl.conf
sed -i '34i\JkMount /* myworker\' /etc/apache2/sites-available/default-ssl.conf

a2enmod ssl
cd /etc/apache2/sites-available
a2ensite default-ssl.conf

root@mobiledeep:/home/psychic/storage/docker/docker_gpms/web# cat Dockerfile
FROM debian

RUN apt update
RUN apt install -y curl wget net-tools systemd vim
RUN curl -sSL https://packages.sury.org/apache2/README.txt | bash -x
RUN apt install apache2 libapache2-mod-jk openjdk-11-jre -y

COPY workers.properties /etc/apache2/workers.properties

RUN sed -i 's/libapache2-mod-jk\/workers.properties/apache2\/workers.properties/g' /etc/apache2/mods-available/jk.conf
RUN sed -i '13i\ JkMount /* myworker\' /etc/apache2/sites-available/000-default.conf

# SSL
COPY server.key /etc/apache2/server.key
COPY servercert.pem /etc/apache2/servercert.pem
RUN sed -i '32,33d' /etc/apache2/sites-available/default-ssl.conf
RUN sed -i '32i\SSLCertificateFile /etc/apache2/servercert.pem\' /etc/apache2/sites-available/default-ssl.conf
RUN sed -i '33i\SSLCertificateKeyFile /etc/apache2/server.key\' /etc/apache2/sites-available/default-ssl.conf
RUN sed -i '34i\JkMount /* myworker\' /etc/apache2/sites-available/default-ssl.conf

#RUN mkdir -p /usr/local && cd /usr/local && wget --no-check-certificate https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.51/bin/apache-tomcat-8.5.51.tar.gz && tar xvfz apache-tomcat-8.5.51.tar.gz && mv apache-tomcat-8.5.51 tomcat8
#RUN rm /usr/local/apache-tomcat-8.5.51.tar.gz

RUN mkdir -p /var/run/apache2
ENV APACHE_RUN_USER=www-data
ENV APACHE_RUN_GROUP=www-data
ENV APACHE_PID_FILE=/var/run/apache2/apache2.pid
ENV APACHE_RUN_DIR=/var/run/apache2
ENV APACHE_LOCK_DIR=/var/lock/apache2
ENV APACHE_LOG_DIR=/var/log/apache2
ENV export LANG=C

# SSL
RUN a2enmod ssl && cd /etc/apache2/sites-available && a2ensite default-ssl.conf

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]
#CMD ["/bin/bash"]

EXPOSE 80
EXPOSE 443

구동스크립트

root@mobiledeep:/home/psychic/storage/docker/docker_gpms/web# cat startup.sh
docker build -t myweb1 .
docker rm -f myweb1c
docker run --rm --name myweb1c -it -p 80:80 -p 443:443 --link mywas1c:mywas1c myweb1
반응형

gradle5 API server

로그를 기록하도록 해 보자. 개발시에는 콘솔로 디버그 로그도 확인할 필요가 있고, 나중에 로그 파일에 기록된 것을 확인해 볼 필요도 있다....

log4j2

  • 이전 글에서 사용했던 것을 보면 다음과 같은 것이 있는데, 이게 로그 라이브러리를 추가한 것이다. 없으면 추가
  • build.gradle에 dependencies 섹션에 추가

        implementation 'org.apache.logging.log4j:log4j-api:2.13.1'
    implementation 'org.apache.logging.log4j:log4j-core:2.13.1'

    annotationProcessor 'org.apache.logging.log4j:log4j-api:2.13.1'
    annotationProcessor 'org.apache.logging.log4j:log4j-core:2.13.1'
  • 버전에 따라 사용법이 달라 질 수 있다.
  • VC 에서 로그 설정 파일을 추가한다.
  • 전에 app/src/main/webapp/WEB-INF 까지 폴더를 만들었을 것이다. 여기에 파일 추가를 누르고, 파일명을 classes/log4j2.xml 을 생성한다. (classes 폴더가 생성되고 그 안에 파일이 추가된다.)
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>

 <!-- Appender, Layout 설정 -->
 <Appenders>
  <Console name="console" target="SYSTEM_OUT">
   <PatternLayout/>
  </Console>
  <File name="file" fileName="./logs/file/sample.log" append="false">
   <PatternLayout pattern="%d %5p [%c] %m%n"/>
  </File>
 </Appenders>

 <!-- Logger 설정 -->
 <Loggers>
  <Logger name="egovLogger" level="DEBUG" additivity="false">
   <AppenderRef ref="console"/>
   <AppenderRef ref="file"/>
  </Logger>
  <Root level="INFO">
   <AppenderRef ref="console"/>
   <AppenderRef ref="file"/>
  </Root>
 </Loggers>

</Configuration>
  • 가장 아래 Root level을 보면 된다. 로그 등급을 어떻게 설정하냐에 따라 로그 기록양이 달라진다.
  • 로그 등급은 DEBUG < INFO < WARN < ERROR < FATAL 이 있다.
  • 소스에서 로그 기록은 logger.debug("aaa"), logger.info("bbb") 이런 식으로 로그 메시지를 출력하는데, 함수 명에 따라 등급이 결정된다.
  • 로그 설정에서 DEBUG로 하면 debug 레벨 이상(즉, 모든 로그)이 모두 출력된다.
  • 로그 설정에서 INFO로 하면 info 레벨 이상(즉, debug()는 출력안됨)만 출력된다.
  • 로그 설정에서 OFF로 하면 기록안함.
  • Appender에 따라서 콘솔만 출력할지 파일로도 출력할지 등을 설정한다.
  • 로그 파일은 /app/logs/file/sample.log 에 생성되었다.

log 기록

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

@WebServlet("/add")
public class Add extends HttpServlet {
      private static final Logger logger = LogManager.getLogger();
...

        @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
                  throws IOException, ServletException {
            logger.debug("[debug] /add : doPost");
            logger.info("[info] /add : doPost");
            logger.warn("[warn] /add : doPost");
            logger.error("[error] /add : doPost");
            process(request, response);
    }

        public void process(HttpServletRequest request, HttpServletResponse response)
                        throws IOException, ServletException {
                        BufferedReader br = request.getReader();
            char[] cbuf = new char[request.getContentLength()];
            br.read(cbuf);
            String input = new String(cbuf);
            System.out.println("/add: INPUT=" + input);

            PrintWriter out = response.getWriter();
            response.setContentType("application/json");

            JSONObject jret = new JSONObject();
            JSONParser jp = new JSONParser();
            long a = 0, b = 0, c = 0;
            try {
                  JSONObject jobj = (JSONObject) jp.parse(input);
                  System.out.println("name=" + jobj.get("name"));
                  System.out.println("age=" + jobj.get("age"));
                  a = (Long) jobj.get("a");
                  b = (Long) jobj.get("b");
                  c = a + b;
                  jret.put("sum", c);
            } catch (ParseException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }

            logger.info("[info] /add : process " + String.format("%d+%d=%d", a, b, c));

            out.write(jret.toJSONString());
        }
  • app/logs/sample.log 파일이 자동으로 생성된다.
2021-11-13 20:33:06,630  INFO [com.my.test.controller.Add] [info] /add : doPost
2021-11-13 20:33:06,633  WARN [com.my.test.controller.Add] [warn] /add : doPost
2021-11-13 20:33:06,634 ERROR [com.my.test.controller.Add] [error] /add : doPost
2021-11-13 20:33:06,638  INFO [com.my.test.controller.Add] [info] /add : process 324+5343=5667
2021-11-13 20:33:09,881  INFO [com.my.test.controller.Add] [info] /add : doPost
2021-11-13 20:33:09,881  WARN [com.my.test.controller.Add] [warn] /add : doPost
2021-11-13 20:33:09,881 ERROR [com.my.test.controller.Add] [error] /add : doPost
2021-11-13 20:33:09,882  INFO [com.my.test.controller.Add] [info] /add : process 1+2=3
  • 서버 실행 콘솔에서도 출력이 된다.
20:33:01 INFO  Tomcat 9.0.48 started and listening on port 8080
20:33:01 INFO  addserver runs at:
20:33:01 INFO    http://localhost:8080/addserver
[info] /add : doPost
[warn] /add : doPost
[error] /add : doPost
/add: INPUT={"a":324,"b":5343}
name=null
age=null
[info] /add : process 324+5343=5667
[info] /add : doPost
[warn] /add : doPost
[error] /add : doPost
/add: INPUT={"a":1,"b":2}
name=null
age=null
[info] /add : process 1+2=3
<===========--> 87% EXECUTING [1h 12m 11s]
> :app:tomcatStart

Log Pattern

   <PatternLayout pattern="%d %5p [%c] %m%n"/>
위에서 출력 패턴을 설정한 것이 있다. 각각의 의미.
2021-11-13 20:33:06,638  INFO [com.my.test.controller.Add] [info] /add : process 324+5343=5667

%d : 날짜시간 (2021-11-13 20:33:06,638)
%5p : 5컬럼으로 로그레벨 출력 (INFO )
[%c] : 카테고리 ([com.my.test.controller.Add])
%m : 메시지 ([info] /add : process 324+5343=5667)
%n : 줄바꿈
-----------------
기타.
%t : 쓰레드
%% : %문자
%F : 로그 발생 소스 파일명.
%l : Caller 
%L : 라인번호
%M : Method

Appender

- File 속성에 append를 false로 주면, 실행시 로그 파일이 초기화된다.
<File name="file" fileName="./logs/file/sample.log" append="false">

RollingFileAppender

  • FileAppender를 그대로 두면 로그파일이 한 없이 커지는 문제가 생긴다.
  • Size Based Trigger
    • 로그 파일이 일정 크기가 되면, 기존 파일을 백업(넘버링하여 이름변경)하고 로그 파일을 초기화하여 처음부터 기록한다.
    • 파일 사이즈별 로그 기록
      • rollingSample.log, rollingSample.1.log, rollingSample.2.log, ... 순서대로 항상 최신 로그가 기록되게 유지됨. ; 최대 백업개수는 3개. (3.log까지)
      • 각 파일은 최대 100메가.
    • Appender에 아래를 추가한다.
<!-- attribute: name(Appender명), fileName(target파일명), filePattern(history파일명), append, immediateFlush, ignoreExceptions, bufferedIO -->
<!-- element: Layout(출력패턴설정), Filters, Policy(file rolling 조건 설정), Strategy(file name과 location 관련 설정) -->
 <RollingFile name="rollingFile" fileName="./logs/rolling/rollingSample.log" filePattern="./logs/rolling/rollingSample.%i.log">
  <PatternLayout pattern="%d %5p [%c] %m%n" />
  <Policies>
   <!-- size 단위: Byte(default), KB, MB, or GB -->
   <SizeBasedTriggeringPolicy size="100MB" />
  </Policies>
  <!-- 기존 maxIndex 속성이 Strategy 엘리먼트로 변경됨 -->
  <!-- index는 min(default 1)부터 max(default 7)까지 증가 -->
  <!-- fileIndex="min"이므로 target file의 size가 지정크기를 넘어가면, fileIndex가 1(min)인 history file에 백업 (fixed window strategy) -->
  <!-- 지정크기를 넘어가면, rollingSample.1.log을 rollingSample.2.log 파일에 복사하고, target 파일을 rollingSample.1.log에복사한 후 target 파일에 새로 로깅 -->
  <DefaultRolloverStrategy max="3" fileIndex="min" />
 </RollingFile>
  • Time Based : 날짜별로 로그 기록
    • 최신 로그는 fileName 명칭으로 기록되고, 날짜가 변경되면 filePattern으로 백업된다고 보면 된다.
    • filePattern이 시간단위 (yyyy-MM-dd-HH) 까지 있으면 시간단위 백업이 된다.
<RollingFile name="rollingFile" fileName="./logs/rolling/dailyRollingSample.log" filePattern="./logs/daily/dailyRollingSample.log.%d{yyyy-MM-dd}">
  <PatternLayout pattern="%d %5p [%c] %m%n" />
  <Policies>
   <TimeBasedTriggeringPolicy />
  </Policies>
 </RollingFile>
  • 월별 폴더로 정리
<RollingFile name="file" fileName="./logs/file/all.log" filePattern="./logs/file/$${date:yyyy}/$${date:MM}/all_%d{yyyyMMddHH}.log"> 
    <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> 
  <Policies> 
      <TimeBasedTriggeringPolicy />
  </Policies> 
</RollingFile>

기타 로그

<Loggers> 
    <Logger name="java.sql" level="off" additivity="false"> 
        <AppenderRef ref="console" /> 
    </Logger> 
    <Logger name="egovframework" level="ERROR" additivity="false"> 
        <AppenderRef ref="console" /> 
        <AppenderRef ref="file"/> 
    </Logger> 
    <Logger name="org.springframework" level="DEBUG" additivity="false"> 
        <AppenderRef ref="console" /> 
        <AppenderRef ref="file"/> 
    </Logger> 
    <Logger name="jdbc.sqltiming" level="off" additivity="false"> 
        <AppenderRef ref="console" /> 
    </Logger> 
    <Logger name="jdbc.resultsettable" level="off" additivity="false"> 
        <AppenderRef ref="console"/> 
    </Logger> 
    <Logger name="jdbc.sqlonly" level="info" additivity="false">
        <AppenderRef ref="console"/> 
    </Logger> 
    <Root level="ERROR"> 
        <AppenderRef ref="console" /> 
    </Root> 
</Loggers>

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

gradle4 API server  (0) 2021.11.13
gradle3 API server  (0) 2021.11.13
gradle2 API server  (0) 2021.11.13
gradle1 기초  (0) 2021.11.13
이클립스 단축키 이것만.  (0) 2019.11.10
반응형

gradle4 API server

간단하게 더하기 서버 만들기2

  • 이번엔 브라우저에서 값을 입력하여 ajax로 서버로 보내 더하기 처리 결과를 받아서 화면에 출력하도록 해 보자.

  • index.jsp 를 수정한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding= "UTF-8"%>

<html>
    <head>
        <title> Add Server </title>
        <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

<script>

function onlyNumber(){
  if((event.keyCode<48)||(event.keyCode>57))
       event.returnValue=false;
}

$(function() {
    $('#btn_sum').click(function() {
        var jsonData = JSON.stringify( {
            a : parseInt($('#edit_a').val()),
            b : parseInt( $('#edit_b').val())
        }) ;
        $.ajax({
            type:"POST",
            url:"add",
            data:jsonData,
            contentType:"application/json;charset=utf-8",
            success : function(data) {
                // alert(JSON.stringify(data)) ;
                $('#edit_c').val(data.sum) ;
            },
            error : function(err) {
                alert(err) ;
            }
        });
    }) ;
});

</script>

    </head>
<p>
context path: ${pageContext.request.contextPath}
</p>
<form>
    A: <input type="text" id="edit_a" onkeypress="onlyNumber();"/> + 
    B: <input type="text" id="edit_b" onkeypress="onlyNumber();"/> 
    <br/>
    <button type="button" id="btn_sum"> 합계 </button>
    <br/>
    SUM: <input type="text" id="edit_c" readonly/>
</form>
</html>
  • 결과를 보자

https://user-images.githubusercontent.com/6326475/141620951-b815b346-bf6f-40c6-93f3-f24568d14805.png

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

gradle5 API server. log  (0) 2021.11.14
gradle3 API server  (0) 2021.11.13
gradle2 API server  (0) 2021.11.13
gradle1 기초  (0) 2021.11.13
이클립스 단축키 이것만.  (0) 2019.11.10
반응형

gradle3 API server

간단하게 더하기 서버 만들기2

  • POST 방식으로 JSON 형식으로 데이터를 보내고 받기로 한다.

서블릿에서 입력 추출

  • 입력값을 읽어 그대로 출력하도록 했다.
  • GET 방식은 사용안함. POST만 처리하도록 수정.
@WebServlet("/add")
public class Add extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
      PrintWriter out = response.getWriter();
      out.write("not support get!");
}

  @Override
  public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
        process(request, response);
  }

  public void process(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
      BufferedReader br = request.getReader() ;
      char[] cbuf = new char[request.getContentLength()] ;
      br.read(cbuf) ;
      String input = new String(cbuf) ;
      System.out.println("/add: INPUT="+input);

      PrintWriter out = response.getWriter();

      out.write(input);
    }
}
  • 브라우저로 localhost:8080/addserver/add 접속하면 "not support get!" 이라고 출력.
  • POST 방식으로 보낼수 있는 크롬 툴을 써서 테스트. (ARC 를 사용)

https://user-images.githubusercontent.com/6326475/141604330-2844e04b-014d-4abc-a5d4-19c849df2b29.png

  • POST 입력값을 그대로 출력하는 것을 확인하였다.

JSON 형식으로 받아 출력하도록

  • https://user-images.githubusercontent.com/6326475/141604392-4425a2dc-8cf8-4531-8fe2-37738f208e8d.png

  • 위 사이트에서 JSON 라이브러리를 찾아 추가한다. 아래 Gradle 형식으로 추가하려면 어떻게 해야 하는지 나온다. 복사하여 붙여넣기.

  • app/build.gradle에 위 한줄을 추가한다.

...
dependencies {
...
    implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1'
...
}
...

기능 구현

  • JSON 형식으로 받고, 출력한다.
public void process(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
      BufferedReader br = request.getReader() ;
      char[] cbuf = new char[request.getContentLength()] ;
      br.read(cbuf) ;
      String input = new String(cbuf) ;
      System.out.println("/add: INPUT="+input);

      PrintWriter out = response.getWriter();
      response.setContentType("application/json");

      JSONObject jret = new JSONObject() ;
      JSONParser jp = new JSONParser() ;
      try {
            JSONObject jobj =  (JSONObject) jp.parse(input);
            System.out.println("name="+jobj.get("name"));
            System.out.println("age="+jobj.get("age"));
            long a, b ;
            a = (Long)jobj.get("a");
            b = (Long)jobj.get("b");
            jret.put("sum", a+b) ;
      } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
      }
      out.write(jret.toJSONString());
    }

https://user-images.githubusercontent.com/6326475/141604596-1dd577f0-20cf-4bee-9b2d-16dc6352700c.png

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

gradle5 API server. log  (0) 2021.11.14
gradle4 API server  (0) 2021.11.13
gradle2 API server  (0) 2021.11.13
gradle1 기초  (0) 2021.11.13
이클립스 단축키 이것만.  (0) 2019.11.10
반응형

gradle2 API server

간단하게 더하기 하는 API 서버.

프로젝트 초기화


mkdir addserver
cd addserver
gradle init
    application type
    나머지는 다 default
    source package: com.my.test

VC에서 "Add Folder to Workspace" 로 추가.

-------------
app/src/main/java/com/my/test/App.java 가 자동 생성됨.
필요없으니 삭제한다.

https://user-images.githubusercontent.com/6326475/141603735-225b687e-db86-4e7f-8bfe-7b95bcd744e0.png

웹 프로젝트 설정

  • 패키지명에 맞춰서 변경한다.
## 아래에서 ^Z전까지 복사하고, 컨트롤 Z를 수동으로 입력해 줘야 한다.

mkdir app\src\main\webapp\WEB-INF\views

copy con app\src\main\webapp\WEB-INF\web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
</web-app>
^Z

mkdir app\src\main\java\com\my\test\controller
copy con app\src\main\java\com\my\test\controller\Add.java
package com.my.test.controller;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;

@WebServlet("/add")
public class Add extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
        process(request, response);
  }

  @Override
  public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
        process(request, response);
  }

  public void process(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
        PrintWriter out = response.getWriter();
        out.write("hello");
    }
}
^Z

copy con app\src\main\webapp\WEB-INF\views\add.jsp
<html>
           <body>
               view page
           </body>
</html>
^Z

copy con app\src\main\webapp\index.jsp
<html>
    index page
    <p>
        context path: ${pageContext.request.contextPath}
    </p>
</html>
^Z

https://user-images.githubusercontent.com/6326475/141603860-a691f4b4-2049-4a4e-8261-9899759b6308.png

  • app/build.gradle
    • contextPath를 맞게 변경한다.
plugins {
    id 'war'
    id 'org.gretty' version '3.0.5'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'

    compileOnly 'javax.servlet:javax.servlet-api:4.0.1'
    compileOnly 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.3'

    // This dependency is used by the application.
    implementation 'org.apache.logging.log4j:log4j-api:2.13.1'
    implementation 'org.apache.logging.log4j:log4j-core:2.13.1'

    annotationProcessor 'org.apache.logging.log4j:log4j-api:2.13.1'
    annotationProcessor 'org.apache.logging.log4j:log4j-core:2.13.1'

    gretty 'org.apache.tomcat:tomcat-dbcp:9.0.13'
}

gretty {
    servletContainer = 'tomcat9'
    httpPort=8080
    contextPath = '/addserver'
    enableNaming = true
}
  • gitignore
    • 디폴트로 .gitignore가 생기는데, 형상관리에서 제외할 것들 설정.
**/.classpath
**/.project
**/.settings
**/.factorypath
.gradle
app/tomcat.8080
app/bin
app/build
*.swp
*.sublime-project
*.sublime-workspace
  • .vscode/tasks.json (task로 검색하여 생성하면 된다.)
    • 쉬프트 컨트롤 P ; task 입력. Tasks: Configure default build task - addserver 라고 있는 항목 선택
    • 아래 내용으로 교체.
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Tomcat Start",
            "type": "shell",
            "command": "${workspaceRoot}/gradlew tomcatStart",
            "problemMatcher": "$msCompile",
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "label": "Tomcat Debug",
            "type": "shell",
            "command": "${workspaceRoot}/gradlew tomcatStartDebug",
            "problemMatcher": "$msCompile"
        },
        {
            "label": "Tomcat Stop",
            "type": "shell",
            "command": "${workspaceRoot}/gradlew tomcatStop",
            "isBackground": true,
            "presentation": {
                "reveal": "never"
            },
            "problemMatcher": []
        }
    ]
}
  • RUN해서 /addserver/add 주소로 잘 되는지 확인한다.

    • 쉬프트 알트 R - tomcatStart : addserver 를 선택.

    • 단축키 설정은 이전편에서....

      https://user-images.githubusercontent.com/6326475/141604004-3f2c4ed6-cd90-4a5d-9234-06eeb6d9534d.png

https://user-images.githubusercontent.com/6326475/141604017-5bcfb582-55eb-4460-baf8-0ac543938b0b.png

  • 서버 중지는 쉬프트+알트+R 에서 tomcatStop : addserver 를 선택한다.
  • 기본틀은 완성되었다. 이제 기능을 구현하자...

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

gradle4 API server  (0) 2021.11.13
gradle3 API server  (0) 2021.11.13
gradle1 기초  (0) 2021.11.13
이클립스 단축키 이것만.  (0) 2019.11.10
Short URL(단축URL) API  (1) 2019.11.07
반응형

gradle1 기초

빌드 자동화 툴로 요즘은 Maven 보다 gradle이 대세라고 한다... 그래서 어떻게 쓰는지 한 번 알아봤다. 덤으로 이클립스 대신 Visual Studio Code로 java 개발하는 것도 알아봤다.

이클립스는 너무 느려서 답답하다.

VC는 대신 초반에 설정해 줘야 할 것들이 많아 귀찮긴 하다.

gradle 설치

  1. gradle을 다운로드 받아 설치 (압축해제)
  2. 환경변수 PATH에 bin 폴더를 걸어둔다.
  3. gradle -v ; 버전 확인. 잘 실행되는지 확인.

HelloWorld

프로젝트 폴더를 생성한다.

-프로젝트 폴더 생성
mkdir hello
cd hello

-프로젝트 초기화
gradle init --type java-application

폴더들이 생성된다. (.gradle, app, gradle 등등)

-빌드
gradle compilejava

-실행
gradle run
실행관련 정보와 결과가 출력됨.

gradle run -q
quiet 모드. 실행 결과만 출력됨.

-라이브러리로 만들기
gradle jar

-build 폴더 삭제
gradle clean
  • DOS에서 디렉터리 구조를 보려면 tree 를 사용하면 된다. /f 옵션을 주면 파일목록도 나옴.
  • 초반에 빠르게 구조 파악에 도움이 된다.

프로젝트 초기화

gradle init --type java-application
  • init type
    • basic (디폴트임)
    • java-application
      • App.java 가 기본 main 클래스.
    • java-library
      • jar 파일 생성용.
      • main 클래스가 없음.
    • groovy-application
    • pom
      • 기존 Maven 프로젝트를 마이그레이션한다

Tasks

gradle tasks

gradle 커맨드 목록, 도움말이 나옴.

init, jar, clean, run, 등등 모두가 Task임.

  • 태스크는 사용자 정의로 추가가 가능하다.
  • app 폴더 안의 build.gradle 파일에 정의하면 된다.
task hello {
    println 'hello gradle'
    doLast {
        println 'bye~'
    }
    doFirst {
        println 'first line.'
    }
}
gradle tasks --all
app:hello 가 생겼다.

gradle -q hello  ; 실행
  • 자세한건 groovy 문법을 알아야 한다.

Authoring Tasks

웹 어플리케이션

mkdir helloweb
cd helloweb
gradle init --type java-application

(중간 경로를 자동으로 만들어줌.)
mkdir app\src\main\webapp\WEB-INF\views

copy con app\src\main\webapp\WEB-INF\web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">

</web-app>
^Z

mkdir app\src\main\java\test
copy con app\src\main\java\test\TestServlet.java
package test;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;

@WebServlet("/test")
public class TestServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
        process(request, response);
  }

  @Override
  public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
        process(request, response);
  }

  public void process(HttpServletRequest request, HttpServletResponse response)
  throws IOException,ServletException {
        PrintWriter out = response.getWriter();
        request.getRequestDispatcher("/WEB-INF/views/test.jsp").forward(request, response);
    }
}
^Z

copy con app\src\main\webapp\WEB-INF\views\test.jsp
<html>
           <body>
                     <h1>Hello Gradle!!</h1>
           </body>
</html>
^Z

copy con app\src\main\webapp\index.jsp
<html>
    hello world.... index.
    <p>
        context path: ${pageContext.request.contextPath}
    </p>
</html>
^Z
  • 이제 빌드 설정
    • war 기능 추가. gretty는 경량웹서버 기능의 플러그인.
notepad app\build.gradle

build.gradle 파일을 열고 아래와 같이 작성.

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'gretty'

buildscript {
           repositories {
                     jcenter()
           }
           dependencies {
                     classpath group:'org.akhikhl.gretty', name:'gretty-plugin', version:'+'
           }
}

repositories {
           jcenter()
}

dependencies {
           testCompile group:'junit', name:'junit', version:'4.12'
}

==> deprecated.... 너무 옛날거라 이 방식이 안 돌아간다... 
수정 필요...!!
  • 배포
gradle war

VS Code 로 개발하기

위 작업한 폴더를 연다.

java 파일을 열면, java 확장을 설치하라고 뜬다. 설치.

확장프로그램 설치

Code Runner

Ant Target Runner

Log Viewer

Sort lines

Rainbow

VC 설정

settings.json (^+, 단축키. 오른쪽에 json으로 보기.)

java 경로는 환경에 맞게 설정

{
    "editor.fontFamily": "D2Coding, Consolas, 'Courier New', monospace",
    "editor.renderWhitespace": "all",
    "editor.insertSpaces": false,
    "workbench.colorTheme": "Default Dark+",
    "editor.suggestSelection": "first",
    "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
    "files.exclude": {
        "**/.classpath": true,
        "**/.project": true,
        "**/.settings": true,
        "**/.factorypath": true,
        ".gradle":true,
        "app/tomcat.8080":true
    },
    "search.exclude": {
        "**/node_modules": true,
        "**/bower_components": true,
        "**/*.code-search": true,
        "**/.classpath": true,
        "**/.project": true,
        "**/.settings": true,
        "**/.factorypath": true,
        ".gradle":true,
        "app/tomcat.8080":true
    },
    "window.titleBarStyle": "custom",
    "window.title": "${dirty}${activeEditorMedium}${separator}${rootName}",
        "java.home":"C:\\Program Files\\Java\\jdk-14.0.2"
}

.gitignore 설정

**/.classpath
**/.project
**/.settings
**/.factorypath
.gradle
app/tomcat.8080
app/bin
app/build
*.swp
*.sublime-project
*.sublime-workspace

Save As WorkSpace로 workspace를 저장하고 VC 재시작.

Add Folder to Workspace로 워크스페이스에 다른 프로젝트 들을 추가할 수 있다.

주의!

첫 번째 프로젝트로 위치해야 좋다?

프로젝트명을 선택하여 가장 위에 WORKSPACE 왼쪽 아래화살표 밑으로 드래그하면 첫번째로 이동된다.

build.gradle

  • 설정이 까다롭다....
  • 버전이 틀리면 실패.. 예전 버전으로 설정하니 에러가 발생해서 버전을 올리니까 돌아감.. :-(
plugins {
    id 'war'
    id 'org.gretty' version '3.0.5'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'

    compileOnly 'javax.servlet:javax.servlet-api:4.0.1'
    compileOnly 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.3'

    // This dependency is used by the application.
    implementation 'org.apache.logging.log4j:log4j-api:2.13.1'
    implementation 'org.apache.logging.log4j:log4j-core:2.13.1'

    annotationProcessor 'org.apache.logging.log4j:log4j-api:2.13.1'
    annotationProcessor 'org.apache.logging.log4j:log4j-core:2.13.1'

    gretty 'org.apache.tomcat:tomcat-dbcp:9.0.13'
}

gretty {
    servletContainer = 'tomcat9'
    httpPort=8080
    contextPath = '/helloweb'
    enableNaming = true
}

https://mvnrepository.com

라이브러리 의존성 확인시 위 사이트에서 검색하여 버전을 맞춘다.

gradlew tasks
tomcat관련 명령어들이 추가된 것을 알 수 있다.

gradlew tomcatrun
에러가 없어야 하는데.... 잘 되네요. 

http://localhost:8080/helloweb
index.jsp 가 구동됨.

http://localhost:8080/helloweb/test
서블릿 구동됨. (TestServlet.java → views/test.jsp )

VC 작업 만들기

Terminal - configure task - tasks.json을 생성한다.

템플릿은 MSBuild 기본형으로 선택.

create tasks.json 메뉴가 안보이면, 이미 있어서 그렇다. .vscode 폴더에 tasks.json. (삭제하고 다시 만들면 된다.)

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Tomcat Start",
            "type": "shell",
            "command": "${workspaceRoot}/gradlew tomcatStart",
            "problemMatcher": "$msCompile",
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "label": "Tomcat Debug",
            "type": "shell",
            "command": "${workspaceRoot}/gradlew tomcatStartDebug",
            "problemMatcher": "$msCompile"
        },
        {
            "label": "Tomcat Stop",
            "type": "shell",
            "command": "${workspaceRoot}/gradlew tomcatStop",
            "isBackground": true,
            "presentation": {
                "reveal": "never"
            },
            "problemMatcher": []
        }
    ]
}

preference - keyboard shortcut (^+shfit+p 로 short로 검색)

keybindings.json

// Place your key bindings in this file to override the defaults
[
    {
        "key":"shift+alt+r",
        "command":"workbench.action.tasks.runTask"
    },
    {
        "key": "ctrl+shift+alt+s",
        "command":"workbench.action.files.saveAll"
    },
    {
        "key": "ctrl+alt+u",
        "command":"editor.action.transformToUppercase"
    },
    {
        "key": "ctrl+alt+l",
        "command":"editor.action.transformToLowercase"
    }
]

shift+alt+r 을 누르면 tasks 3개가 뜬다. tomcat run , run debug, stop.

디버깅시에는 tomcat debug를 실행하면, 디버깅 별도 포트를 알려준다.

5005로 나옴.

VC의 디버깅창에서 디버깅 configuration을 만들어준다.

launch.json

{
    "version": "0.2.0",
    "configurations": [

        {
            "type": "java",
            "name": "Tomcat Debug",
            "request": "attach",
            "hostName": "localhost",
            "port": 5005
        }

    ]
}

이제 디버그 메뉴에서 Tomcat Debug로 실행하면 디버그 포트로 연결되면서 콜스택에

쓰레드 정보가 나올 것이다.

bp 설정하여 디버깅 가능.

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

gradle3 API server  (0) 2021.11.13
gradle2 API server  (0) 2021.11.13
이클립스 단축키 이것만.  (0) 2019.11.10
Short URL(단축URL) API  (1) 2019.11.07
[JavaScript] 스탑와치 밀리초/StopWatch milliseconds  (0) 2019.08.27
반응형

Docker tomcat mysql mongo

tomcat 서버에서 mysql과 mongodb를 동시에 사용할 일이 있어서 도커 환경으로 만들어봤다.

clean.sh

#!/bin/sh
/usr/bin/sudo rm -rf ./db ./webapps ./mongo
mkdir db
mkdir mongo
mkdir -p webapps
mkdir initdb
cd initdb
initdb.sql : 테이블 스키마. 초기 데이터 쿼리
mkdir initmongo
cd initmongo
cat > initdb.js
db.createUser(
    {
        user: "myhome",
        pwd: "myhome00.",
        roles:[
            {
                role: "readWrite",
                db:   "DB_ANALYZE"
            }
        ]
    }
);
mkdir locallib
cd locallib
*.so 파일 복사. (/usr/local/lib 으로 연결)
mkdir myhome
cd myhome
was에서 사용하는 설정 파일들

docker-compose.yml

version: '2'
services:
        db:
                image: mysql:5.7
                environment:
                        MYSQL_ROOT_PASSWORD: myhome00.
                        MYSQL_DATABASE: DB_ANALYZE
                        MYSQL_USER: myhome
                        MYSQL_PASSWORD: myhome00.
                ports:
                        - "3306:3306"
                volumes:
                        - ./mycustom.cnf:/etc/mysql/conf.d/custom.cnf
                        - ./db:/var/lib/mysql
                        - ./initdb:/docker-entrypoint-initdb.d
                restart: always
        mongo:
                image: mongo
                environment:
                        MONGO_INITDB_ROOT_USERNAME: myhome
                        MONGO_INITDB_ROOT_PASSWORD: myhome00.
                        MONGO_INITDB_DATABASE: DB_ANALYZE
                ports:
                        - "27018:27017"
                volumes:
                        - ./mongo:/data/db
                        - ./initmongo:/docker-entrypoint-initdb.d
                restart: always

        web:
                image: crazyj7/ubuntu16.04-tomcat8-jre8
                depends_on:
                        - db
                        - mongo
                environment:
                        JDBC_URL: jdbc:mysql://db:3306/DB_ANALYZE?connectTimeout=0&amp;socketTimeout=0&amp;autoReconnect=true
                        JDBC_USER: myhome
                        JDBC_PASS: myhome00.
                ports:
                        - "9090:8080"
                mac_address: 02:42:ac:15:00:03
                volumes:
                        - ./webapps:/usr/local/tomcat/webapps
                        - ./myhome:/myhome
                        - ./locallib:/usr/local/lib
                links:
                        - db
                        - mongo
                restart: always

mycustom.cnf

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
skip-character-set-client-handshake
skip-name-resolve

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

! 중요!! skip-name-resolve를 위에 지정하지 않으면 DB 접속시 1분정도??? Delay가 발생하는 현상이 생길수 있다!

실행

docker-compose up

다른 쉘에서 war를 webapps에 복사한다.

9090 포트로 접속하여 테스트

반응형

윈도우 cmd 창에서 폴더(디렉터리) 복사를 하려고 할 때 막상 해보면 잘 되지 않는다...

리눅스 처럼 간단하게 cp -rf 같은 게 있으면 될 텐데, 이러저리 해봐도 쉽지 않았다.

팁!

xcopy /hickey [소스] [목적지]

xcopy의 옵션이 워낙 많아서 읽어보려면 시간이 많이 걸린다. 

한 번 정리해본 결과. 최종 옵션은 hickey 다.

hickey ;  어떻게 쉽게 외울까 하다가 옵션 순서를 영어 단어가 있는 것으로 배열해 봤다.

히키로 외우자. (영어 단어 뜻은 여드름. 흠집. 키스마크.^^ 이다.)

옵션 정리

a ; 보관특성만 복사. 보관특성 유지
m ; 상동. 단, 보관특성 삭제.
d:m-d-y ; 지정날짜 이후 수정파일만 복사. 미지정시, 대상 파일보다 최신인 것만 복사.
p ; 사용자에게 물어보기. 
s ; sub 포함. 단, empty dir 제외.
e ; sub 포함. 단, empty dir 포함.
q ; 조용히
c ; 에러무시하고 진행
h ; hidden 포함
l ; 파일 목록 표시 list
t ; tree 구조만 복사.
u ; update
k ; 특성도 복사
o ; 파일소유권 owner 복사
y ; overwrite할때 묻지 않음. yes
i ; directory 자동인식

 

 

 

반응형

도커 환경에서 tomcat, mariadb 컨테이너 구성하여 테스트하는 중.

이상한 증상이 있었음.

war를 올려서 구동하는데, 너무 늦게 구동됨. 1분 정도?? 딜레이가 발생하였다...

tomcat 로그를 봐도 알수가 없었음. WAR가 풀리고 중간에 1분 정도 멈췄다가 다시 진행되어 WAS가 구동되는 현상.

원인은??? DB의 name resolve 문제였음. DBMS가 외부에서 온 접속을 IP 주소에서 호스트명으로 변환을 시도하다 호스트명 resolve를 못하고 타임아웃까지 기다리는 현상이 원인이었던 것으로 추정된다. (어디서는 이런 현상이 없었는데, 어디서는 이런 현상이 발생하고 그랬다. 어떤 환경차이인지는 모르겠다.)

해결방안 my.cnf 파일을 만들어 DB 컨테이너 만들때 config에 넣어준다. 아래에서 보면 skip-name-resolve  한 줄을 추가했더니, 위에 1분간 딜레이되던 현상이 없어졌다. 바로 war가 풀리고 정상 가동되었다. 

my.cnf

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
skip-character-set-client-handshake
skip-name-resolve
#default-authentication-plugin=mysql_native_password
#sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
#sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

(sql_mode가 DBMS에 따라 가끔 지원하지 않는 필드들이 있어서 위에 주석처리한 것들이 있음.)

 

+ tomcat, mariadb 도커 환경 구축

여기서는 식별을 위해서 컨테이너 이름이나 포트번호에 2를(db2, 23306, tomcat2, 28080 등) 붙였다. (이후에 또 만들것들은 3, 4, 등으로 연속해서 추가하는 방식으로 관리하였다.)

1. create_db.sh ; DB 컨테이너 생성하여 실행 또는 있으면 재실행

현재 폴더에 db 폴더가 없으면 최초 실행으로 판단하여 db 설정(my.cnf)를 복사하고 DB를 초기화한다.

#!bin/sh
if [ "$(ls -A db)" ]; then
	echo "db dir is already exist."
else
	echo "created db dir and copied my.cnf."
	mkdir -p db/config
	cp my.cnf db/config
fi

docker rm -f db2
docker run -d --restart always \
--name db2 \
-v /home/storage/2.mysvc/db/config/my.cnf:/etc/mysql/my.cnf \
-v /home/storage/2.mysvc/db/data:/var/lib/mysql \
-v /home/storage/2.mysvc/db/log:/var/log/mysql \
-v /home/storage/2.mysvc/db/temp:/temp \
--privileged \
-p 23306:3306 \
-e TZ=Asia/Seoul \
-e LC_ALL=C.UTF-8 \
-e MYSQL_ROOT_PASSWORD=mysvc00. \
mariadb:latest

위 쉘을 실행하여 mariadb가 떴으면 23306 포트로 접속하여 쿼리로 데이터베이스와 테이블들을 생성해 주면 된다.

 

2. create_tomcat.sh ; tomcat 실행 또는 재실행(이미 컨테이너가 떠 있는 경우)

아래의 경우 맥주소를 고정할 필요가 있어서 --mad-address 옵션을 추가한 것이다. (필요시 사용)

webapps 폴더가 생성될 것이고, 여기에 war를 올리면 구동될 것이다.

myconfig라고 폴더를 지정한 것은 war에서 사용할 설정 파일들을 특정 위치에 고정시키려고 한 것이다. (필요시 사용)

locallib 폴더는 native library (*.so)를 JVM에서 사용하려고 올려 넣은 것이다. (필요시 사용)

link로 위에서 만든 컨테이너 db2를 사용할수 있도록 지정함.

#!/bin/sh
docker rm -f tomcat2
docker run -d --restart always \
--mac-address=12:33:44:55:66 \
--name tomcat2 \
-v /home/storage2/2.mysvc/myconfig:/myconfig \
-v /home/storage2/2.mysvc/webapps:/usr/local/tomcat/webapps \
-v /home/storage2/2.mysvc/locallib:/usr/local/lib \
--privileged \
--link db2:db2 \
-p 28080:8080 \
-e TZ=Asia/Seoul \
-e LC_ALL=C.UTF-8 \
-e JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT+9:00 -Djava.library.path=/usr/local/lib" \
tomcat:8

war 설정 파일들(/myconfig)과 war 파일을 다 올렸으면, 로그를 확인함.

3. log.sh  ; 톰캣 최근 1분 로그부터 보기

#!/bin/sh
docker logs -f --since 1m tomcat2

4. stop.sh ; 컨테이너 종료.

#!/bin/sh
docker rm -f db2
docker rm -f tomcat2

 

이제 간단하게 shell script 만 실행하면서 쉽게 개발 테스트를 할 수 있다.

 

+ Recent posts