반응형
반응형
package global.configuration;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;

public class iniTest {

	static final String INI_PATH = "src/main/java/global/configuration/properties.ini"; 
	
	public static void main(String[] args) throws InvalidFileFormatException, IOException {
		
		/** ini4j 라이브러리 이용 하지 않기 **/
		// ini 파일 내용
		// mode = external_local

		Properties prop = new Properties();
		prop.load(new FileInputStream(INI_PATH));
        
		System.out.println(prop.getProperty("mode")); // external_local
		
		
		/** ini4j 라이브러리 사용 → 대괄호 읽을 수 있음**/
		// ini 파일 내용 
		// [mode]
		// mode = external_local

		Ini ini = new Ini();
		File iniFile = new File(INI_PATH);
		ini = new Ini(iniFile);
		
		System.out.println(ini.get("mode", "mode")); // external_local
		
		
	}

}
<!-- https://mvnrepository.com/artifact/org.ini4j/ini4j -->
<dependency>
    <groupId>org.ini4j</groupId>
    <artifactId>ini4j</artifactId>
    <version>0.5.4</version>
</dependency>
반응형
반응형

📝Tomcat 큰 3가지 구성

Coyote : Tomcat TCP 프로토콜 지원
Catalina : Java Servlet을 호스팅 해준다.
Jasper : JSP 페이지 요청 처리 Servlet

 

📝톰캣 동작 구조

Tomcat Server가 그 밑에 Service 객체를 생성한다 (그 하위에는 Engine, Connector(호출 포트), Host, Context(URI Mapping) 등이 존재)

HTTP 통신 요청 → 호출 포트에 해당하는 Connector 연결 → Service → Engine → Host → Context(기본적으로 webapps에 있는 곳 참조해 프로젝트 URI Mapping → 프로젝트 내 web.xml 읽기 → 프로젝트 내 web.xml 기반으로 프로젝트 URI 매핑

 

 


하나의 Server에는 여러개 Service가 존재할 수 있다.
하나의 Service에는 1개의 Engine과 여러개의 Connector로 구성
하나의 Engine에는 여러개 Host 존재할 수 있다.
하나의 Host에는 여러개 Context가 존재할 수 있습니다.

 

Tomcat Server → Engine(Connector로 통해 전달) → Host → Context 

[Tomcat에서는 server.xml에 적혀있는 내용을 가지고 객체를 만드는 거라고 생각하면 된다. 그렇기 때문에 Connector에 포트번호를 적어두면 어떤 Service를 이용할지 방향을 알려준다]

 

📝Server

port : Shutdown 명령을 보낼 수 있는 TCP/IP 주소

<Server port="8005" shutdown="SHUTDOWN">

 

📝Service

Serivce의 유일한 이름으로 Log를 남길 때 사용한다 (Catalina.out)

<Service name="Catalina">

 

 

📝Connector

 

특정 TCP port에서 request들을 listen해 engine으로 보내준다.

  • port
    • 리슨할 포트
  • protocol
    • TCP/IP 방식 
  • HTTP/1.1
    • 기본적으로 Connection당 하나의 요청을 처리 하도록 설계 동시 전송이 불가능하고 요청과 응답이 순차적으로 이뤄진다
  • HTTP/2
    • HTTP1.1을 완전하게 재작성한 것이 아니라 프로토콜의 성능에 초첨을 맞춰 수정한 버전 기본적으로 connection 한 개로 동시에 여러 개의 메시지를 주고 받을 수 있으며, 응답은 순서에 상관없이 stream으로 주고 받는다
  • AJP
    • "Apache JServ Protocol"의 약자로, Tomcat과 웹 서버(주로 Apache) 간의 통신을 위한 프로토콜로 Web서버인 Apache에서 어떤 포트를 들어오면 포트포워딩할 지에 대한 포트 설정을하고 Tomcat도 이에 대한 걸 받기 위한 프로토콜 설정 및 포트 개방을 한다
<!-- Apache 설정 -->
<VirtualHost *:80>
    ServerName yourdomain.com
    # 기타 설정

    ProxyPass / ajp://localhost:8009/    # Tomcat과의 AJP 연결 설정
    ProxyPassReverse / ajp://localhost:8009/
</VirtualHost>

<!-- Tomcat 설정 -->
<Connector protocol="AJP/1.3" port="8009" redirectPort="8443" />


위 프로토콜의 동작 방식 설정
- BIO : Tomcat 7 기본 방식 하나의 Thread가 하나의 Connection을 담당
- NIO :  Tomcat 8.5 기본 방식 하나의 Thread가 하나 이상의 Connection을 담당
- APR :  10.x 버전 부터 ARP 방식 삭제

<Connector port="7104" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="7004" URLEncoding="UTF-8" />

 

 

📝Thread Pool 설정

maxThreads : Connector가 생성할 수 있는 최대 Thread 수
maxConnections : 동시 처리 가능한 최대 Connection 수
maxSpareThreads : 최소로 실행을 유지할 thread 수
acceptCount : thread가 꽉 찼을 때 queue에 저장 가능한 최대 request 수

Thread Pool
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150", maxConnections >
공유 Thread Poll
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>

 

 

📝 Engine

name : Engine의 유일한 이름으로 Log를 남길 때 사용한다.
defaultHost ?

<Engine name="Catalina" defaultHost="localhost">

 

 

📝Host

name : 유일한 가상 Host명 (http://hostname/~)
appBase : app 폴더 (default webapps) Host마다 다른 appBase를 지정할 수 있다. (여러개 Domain 효율적 관리가능)
autoDeploy : appBase에 변동사항이 있을 때 자동으로 Deploy(배포) 해준다.
unpackWARs : war파일 deploy 설정 여부

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

 

 

📝Context

Host안에 있으며 하나의 WebApplication이며 주로 .war 형태로 배포됩니다.

docBase : 호출할 경로 URI이다. (/ABC/testing.jsp 호출시 /webapps/DEF/testing.jsp를 호출하게 된다.)

path : 실제 호출시킬 경로이다

만약 Context가 없으면 기본적으로 docBase는 webapps안에 있는 폴더 이름을 따라가게 된다.

즉, webapps/ABC 폴더가 존재시 /ABC/ 이런식으로 호출함

<Host name="localhost" appBase="webapps"
            unpackWARs="true" autoDeploy="true">
  <Context docBase="ABC" path="/DEF" reloadable="true"></Context>

 

 

 

 

🔗 참고 및 출처

https://velog.io/@hyunjae-lee/Tomcat-2-%EA%B5%AC%EC%A1%B0

 

Tomcat - (2) 구조

Tomcat의 구조에 대해 자세히 알아봅니다.

velog.io

 

https://bogyum-uncle.tistory.com/m/219

 

[Tomcat] server.xml 구조

톰캣의 server.xml 은 메인 설정 파일이며, Tomcat startup 초기 설정을 명세하는 책임이 있음 1. server.xml 태그 예시 2. 태그 상세 태그 설명 Server root element, shutdown port 지정, 전체 설정파일의..

bogyum-uncle.tistory.com

https://ijbgo.tistory.com/m/26

 

HTTP/1.1 VS HTTP/2

HTTP/1.1 동작 방식 HTTP/1.1는 기본적으로 Connection당 하나의 요청을 처리 하도록 설계동시 전송이 불가능하고 요청과 응답이 순차적으로 이뤄짐HTTP 문서 안에 포함된 다수의 리소스 (Images, CSS, Script)

ijbgo.tistory.com


https://velog.io/@wiostz98kr/HTTP1.1%EA%B3%BC-HTTP2.0%EC%9D%98-%EC%B0%A8%EC%9D%B4-e2v4x4t1

 

반응형
반응형

- 톰캣 포트 변경

${tomcat 설치경로}/conf/server.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at
...
-->
...
<Server port="8005" shutdown="SHUTDOWN">
...

    <Connector port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000"
               redirectPort="8443" />

....

      </Host>
    </Engine>
  </Service>
</Server>

Connector port="8080" → Connector port="${바꿀 포트번호}" 로 변경

 

SSL 인증서 발급

 

 

 

반응형
반응형
package com.lsj.chatting;

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	@RequestMapping(value = "/getServerInfo", method = RequestMethod.GET)
	public void getServerInfo() throws UnknownHostException {
		
		System.out.println("HostName : " + InetAddress.getLocalHost().getHostName());
		System.out.println("Address : " + InetAddress.getLocalHost().getHostAddress());


        String osName = System.getProperty("os.name").toLowerCase();

        System.out.println("os.name property: " + osName);

        if (osName.contains("win")) {
            System.out.println("This is Windows");
        } else if (osName.contains("mac")) {
            System.out.println("This is Mac");
        } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) {
            System.out.println("This is Unix or Linux");
        } else if (osName.contains("sunos")) {
            System.out.println("This is Solaris");
        } else {
            System.out.println("Your OS is not support!!");
        }
		
	}
	
}
반응형
반응형

📝HttpServletRequest

클라이언트가 보낸 요청의 정보를 가지고있다.
→ 즉, 요청이 들어오면 그 요청에대한 정보를 가지고 있다.

request.getHeader("host"); → 요청한 host에 대한 정보를 가지고있다.

 

📝HttpServletResponse

HTTP 요청에 대한 응답 메시지를 생성하고, 기타 편의 기능을 제공한다.
→ 즉, 사용자에게 보낼 응답에 대한 정보를 가지고 있다.

response.setContentType("text/plain");
response.setCharacterEncoding("utf-8"); → text/plain utf-8 형태로 응답을 보내겠다.

반응형
반응형

HTTP 통신 Request와 Response를 보기 좋게 보여주고 요청을 쉽게 도와주는 프로그램이다.

 

- 설치

https://chrome.google.com/webstore/search/postman?hl=ko

 

Chrome 웹 스토어

Chrome에 사용할 유용한 앱, 게임, 확장 프로그램 및 테마를 찾아보세요.

chrome.google.com

 

설치 후에 사용방법은 간단합니다.

 

 

Method가 Http 통신 방식을 정하시고 URL을 적어주시면 됩니다.

GET의 경우 웹브라우저로 요청해도 오니 POST방식을 알려드리겠습니다.

 

 

package com.lsj.chatting;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
	@GetMapping("/test/get")
	public String hello() {
		return "<h1> get </h1>";
	}

	@DeleteMapping("/test/delete")
	public String delete() {
		return "<h1> delete </h1>";
	}
	
	@PostMapping("/test/post")  // Body : json → application/json (Text → text/plain로 요청시 에러 발생 [자동매핑이 안 되어서])
	public String post(@RequestBody Account account) { // MessageConverter라는 Class가 자동 Injection을 해준다.
		return "id : " + account.getId() + "\n password : " + account.getPassword(); 
		// {id:1,password:1234} 으로 요청 
	}
	
	@PostMapping("/test/post2") // Body : Text → text/plain 
	public String post2(@RequestBody String text) { // @requestBody body 데이터를 받기 위해 필요
		return text; // 정말로 맛있어요 으로 요청 
	} 
	
	@PutMapping("/test/put")
	public String put() {
		return "<h1> put </h1>";
	}
	
}
package com.lsj.chatting;

public class Account {

	private String id;
	private int password;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public int getPassword() {
		return password;
	}
	public void setPassword(int password) {
		this.password = password;
	}
	
	
}

기본적으로 form 따위 방식으로 보낼 때 x-www-form-urlencoded 방식으로 body에 담아 보냅니다. 

 

Header에 보시면 text/plain으로 보낸 걸 알 수 있습니다.

 

Body에 담아서 보낼 경우 Text 방식과 Json 방식을 설정할 수 있습니다.

 

반응형
반응형

 

병렬 작업 처리가 많아지면 스레드 개수가 무한정으로 증가하고 CPU가 바빠지며 메모리 사용량이 늘어난다.

따라서 애플리케이션의 성능이 급격하게 저하되게 된다.

 

스레드 풀

작업 처리에 사용되는 스레드를 제한된 개수 만큼 미리 생성해서 작업 큐에 쌓여지는 작업들을 하나씩 스레드가 맡아서 처리한다. 제한을 걸기 때문에 무한정으로 증가하지 않으며 서버가 뻗지 않게 된다.

 

코어 스레드 수  

최소 스레드 수 (60초 동안 추가된 스레드가 아무 작업 하지 않으면 놀고 있는 스레드가 존재해 없애야한다.)

 

스레드풀의 스레드는 기본적으로 데몬 스레드가 아니기 때문에 main 스레드가 종료되더라도 계속 실행 되므로

반드시 종료시키려면 스레드 풀을 따로 종료시켜야한다.

 

 

 

반응형
반응형
package runnable_jar;

public class PrintThread extends Thread {
	@Override
	public void run() {
		while (true) {
		}
	}
}
package runnable_jar;

import java.util.Map;
import java.util.Set;

public class InterruptExample {

	public static void main(String[] args) {

		PrintThread printThread = new PrintThread();
		printThread.setName("Print Thread");
		printThread.setDaemon(true);
		printThread.start();
		
		Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
		Set<Thread> threads = map.keySet();
		for(Thread thread : threads) {
			System.out.println("Name : " + thread.getName() + ((thread.isDaemon() ? " 데몬" : "주")));
			System.out.println("\t" + "소속그룹 : " + thread.getThreadGroup().getName());
			System.out.println();
		}
	}
	/** 기본 스레드 그룹 **/
	// system : JVM 운영에 필요한 스레드를 포함
	// main : 메인 스레드를 포함 (Print Thread는 Main Thread의 데몬 스레드이기 때문에 main 소속)
	
//	Name : Notification Thread 데몬
//	소속그룹 : system
//
//	Name : main주
//		소속그룹 : main
//	
//	Name : Signal Dispatcher 데몬
//		소속그룹 : system
//	
//	Name : Common-Cleaner 데몬
//		소속그룹 : InnocuousThreadGroup
//	
//	Name : Finalizer 데몬
//		소속그룹 : system
//	
//	Name : Print Thread 데몬
//		소속그룹 : main
//	
//	Name : Reference Handler 데몬
//		소속그룹 : system
//	
//	Name : Attach Listener 데몬
//		소속그룹 : system


}

 

 

 

 

package runnable_jar;

public class PrintThread extends Thread {

	// 스레드 그룹 정해주는 생성자
	public PrintThread(ThreadGroup threadGroup, String threadName) {
		super(threadGroup, threadName);
	}
	
	@Override
	public void run() {
		while (true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				System.out.println(getName() + " interrupted");
				break;
			}
		}
		System.out.println(getName() + "종료됨");
	}
	

}
package runnable_jar;

public class ThreadGroupExample {

	public static void main(String[] args) {

		ThreadGroup myGroup = new ThreadGroup("myGroup"); // main - myGroup (계층도)
		PrintThread printThreadA = new PrintThread(myGroup, "printThreadA"); // main - myGroup - printThreadA
		PrintThread printThreadB = new PrintThread(myGroup, "printThreadB"); // main - myGroup - printThreadB
		
		printThreadA.start();
		printThreadB.start();
		
		System.out.println("[main 스레드 그룹 list() 메소드 출력 내용]");
		ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
		mainGroup.list();
		System.out.println();
		

		
//		[main 스레드 그룹 list() 메소드 출력 내용]
//				java.lang.ThreadGroup[name=main,maxpri=10]
//				    Thread[main,5,main]
//				    java.lang.ThreadGroup[name=myGroup,maxpri=10]
//				        Thread[printThreadA,5,myGroup]
//				        Thread[printThreadB,5,myGroup]

		myGroup.interrupt(); // 상위 스레드 그룹에서 interrupt 발생시 하위 스레드도 전부 interupt 발생
		
//		printThreadA interrupted
//		printThreadA종료됨
//		printThreadB interrupted
//		printThreadB종료됨
	}

}
반응형
반응형

1. Runnable
Runnable은 이름부터 인터페이스의 느낌이 강하다.
implements Runnable 을 통해서 Runnable 인터페이스를 구현할 수 있다.

Runnable 인터페이스를 구현하게되면 재사용성이 높고, 코드의 일관성을 유지할 수 있어서 Thread보다 더 효율적인 방법이라 할 수 있다.

2. Thread
상속을 받아 사용해야 하기 때문에 다른 클래스를 상속받아 사용할 수 없다는 단점이 있다.
따라서 일반적으로는 Runnable 인터페이스를 구현해서 스레드를 사용한다.

반응형