Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[톰캣 구현하기 - 3, 4단계] 헙크(정현승) 미션 제출합니다. #421

Merged
merged 15 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions study/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ server:
enabled: true
min-response-size: 10
tomcat:
accept-count: 1
max-connections: 1
accept-count: 4 # 작업큐의 사이즈
max-connections: 2 # 수립가능한 connection의 총 개수
threads:
max: 2
max: 4 # 생성할 수 있는 thread의 총 개수
# min-spare: 10 # 항상 활성화 되어있는(idle) thread의 개수 (코어 스레드)

2 changes: 1 addition & 1 deletion study/src/test/java/thread/stage0/SynchronizationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private static final class SynchronizedMethods {

private int sum = 0;

public void calculate() {
public synchronized void calculate() {
setSum(getSum() + 1);
}

Expand Down
6 changes: 3 additions & 3 deletions study/src/test/java/thread/stage0/ThreadPoolsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ void testNewFixedThreadPool() {
executor.submit(logWithSleep("hello fixed thread pools"));

// 올바른 값으로 바꿔서 테스트를 통과시키자.
final int expectedPoolSize = 0;
final int expectedQueueSize = 0;
final int expectedPoolSize = 2; // 스레드 풀의 갯수
final int expectedQueueSize = 1; // 스레드를 얻기 위해 큐에서 대기하는 요소의 사이즈

assertThat(expectedPoolSize).isEqualTo(executor.getPoolSize());
assertThat(expectedQueueSize).isEqualTo(executor.getQueue().size());
Expand All @@ -46,7 +46,7 @@ void testNewCachedThreadPool() {
executor.submit(logWithSleep("hello cached thread pools"));

// 올바른 값으로 바꿔서 테스트를 통과시키자.
final int expectedPoolSize = 0;
final int expectedPoolSize = 3;
final int expectedQueueSize = 0;

assertThat(expectedPoolSize).isEqualTo(executor.getPoolSize());
Expand Down
3 changes: 2 additions & 1 deletion study/src/test/java/thread/stage0/ThreadTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ void testExtendedThread() throws InterruptedException {
@Test
void testRunnableThread() throws InterruptedException {
// 하단의 RunnableThread 클래스를 Runnable 인터페이스의 구현체로 만들고 Thread 클래스를 활용하여 스레드 객체를 생성한다.
Thread thread = new Thread(new RunnableThread("hello thread"));
RunnableThread runnableThread = new RunnableThread("hello thread");
Thread thread = new Thread(runnableThread);

// 생성한 thread 객체를 시작한다.
thread.start();
Expand Down
15 changes: 10 additions & 5 deletions tomcat/src/main/java/org/apache/catalina/connector/Connector.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
package org.apache.catalina.connector;

import org.apache.coyote.http11.Handler;
import org.apache.coyote.http11.Http11Processor;
import org.apache.coyote.http11.RequestMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class Connector implements Runnable {

private static final Logger log = LoggerFactory.getLogger(Connector.class);

private static final int DEFAULT_PORT = 8080;
private static final int DEFAULT_ACCEPT_COUNT = 100;
private static final int MAX_THREAD_COUNT = 250;

private final ThreadPoolExecutor executor;
private final ServerSocket serverSocket;
private boolean stopped;

public Connector() {
this(DEFAULT_PORT, DEFAULT_ACCEPT_COUNT);
this(DEFAULT_PORT, DEFAULT_ACCEPT_COUNT, MAX_THREAD_COUNT);
}

public Connector(final int port, final int acceptCount) {
public Connector(final int port, final int acceptCount, final int maxThreads) {
this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(maxThreads);
BGuga marked this conversation as resolved.
Show resolved Hide resolved
this.serverSocket = createServerSocket(port, acceptCount);
this.stopped = false;
}
Expand Down Expand Up @@ -67,8 +72,8 @@ private void process(final Socket connection) {
if (connection == null) {
return;
}
var processor = new Http11Processor(connection, new Handler());
new Thread(processor).start();
var processor = new Http11Processor(connection, new RequestMapping());
executor.submit(processor);
}

public void stop() {
Expand Down
114 changes: 0 additions & 114 deletions tomcat/src/main/java/org/apache/coyote/http11/Handler.java

This file was deleted.

21 changes: 13 additions & 8 deletions tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import nextstep.jwp.exception.UncheckedServletException;
import org.apache.coyote.Processor;
import org.apache.coyote.http11.request.Request;
import org.apache.coyote.http11.response.Response;
import org.apache.coyote.http11.controller.Controller;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -16,11 +17,11 @@ public class Http11Processor implements Runnable, Processor {
private static final Logger log = LoggerFactory.getLogger(Http11Processor.class);

private final Socket connection;
private final Handler handler;
private final RequestMapping requestMapping;

public Http11Processor(final Socket connection, final Handler handler) {
public Http11Processor(final Socket connection, final RequestMapping requestMapping) {
this.connection = connection;
this.handler = handler;
this.requestMapping = requestMapping;
}

@Override
Expand All @@ -34,14 +35,18 @@ public void process(final Socket connection) {
try (final var outputStream = connection.getOutputStream();
final var bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {

final Request request = Request.from(bufferedReader);
final Response response = handler.handle(request);
final HttpRequest httpRequest = HttpRequest.from(bufferedReader);
final Controller controller = requestMapping.getController(httpRequest);
final HttpResponse response = HttpResponse.create();
controller.service(httpRequest, response);
final String result = response.toString();

outputStream.write(result.getBytes());
outputStream.flush();
} catch (IOException | UncheckedServletException e) {
log.error(e.getMessage(), e);
log.error("", e);
} catch (Exception e) {
log.error("예상치 못한 오류 : ", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

public enum HttpMethod {
GET,
POST
POST,
DELETE,
}
35 changes: 35 additions & 0 deletions tomcat/src/main/java/org/apache/coyote/http11/RequestMapping.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.apache.coyote.http11;

import org.apache.coyote.http11.controller.Controller;
import org.apache.coyote.http11.controller.DefaultController;
import org.apache.coyote.http11.controller.IndexController;
import org.apache.coyote.http11.controller.LoginController;
import org.apache.coyote.http11.controller.RegisterController;
import org.apache.coyote.http11.controller.RootController;
import org.apache.coyote.http11.controller.UnAuthorizedController;
import org.apache.coyote.http11.controller.Uri;
import org.apache.coyote.http11.request.HttpRequest;

import java.util.EnumMap;
import java.util.Map;


public class RequestMapping {
private final Map<Uri, Controller> controllerMap;

public RequestMapping() {
this.controllerMap = new EnumMap<>(Uri.class);
controllerMap.put(Uri.ROOT, new RootController());
controllerMap.put(Uri.INDEX, new IndexController());
controllerMap.put(Uri.LOGIN, new LoginController());
controllerMap.put(Uri.UNAUTHORIZED, new UnAuthorizedController());
controllerMap.put(Uri.REGISTER, new RegisterController());
controllerMap.put(Uri.DEFAULT, new DefaultController());
}

public Controller getController(final HttpRequest httpRequest) {
final String path = httpRequest.getRequestLine().getPath();
final Uri uri = Uri.from(path);
return controllerMap.get(uri);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.apache.coyote.http11.controller;

import org.apache.coyote.http11.HttpMethod;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public abstract class AbstractController implements Controller {

@Override
public void service(HttpRequest request, HttpResponse response) throws Exception {
final HttpMethod httpMethod = request.getRequestLine().getHttpMethod();
if (httpMethod == HttpMethod.GET) {
doGet(request, response);
return;
}
if (httpMethod == HttpMethod.POST) {
doPost(request, response);
return;
}
throw new UnsupportedOperationException();
}

protected void doGet(HttpRequest request, HttpResponse response) throws Exception {
throw new UnsupportedOperationException();
}

protected void doPost(HttpRequest request, HttpResponse response) throws Exception {
throw new UnsupportedOperationException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.apache.coyote.http11.controller;

import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public interface Controller {
void service(HttpRequest request, HttpResponse response) throws Exception;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.apache.coyote.http11.controller;

import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;
import org.apache.coyote.http11.response.HttpStatus;
import org.apache.coyote.http11.response.ResponseBody;
import org.apache.coyote.http11.response.StaticResource;

public class DefaultController extends AbstractController {

@Override
protected void doGet(HttpRequest request, HttpResponse response) throws Exception {
final String path = request.getRequestLine().getPath();
final StaticResource staticResource = StaticResource.from(path);
final ResponseBody responseBody = ResponseBody.from(staticResource);

response.setHttpStatus(HttpStatus.OK);
response.setResponseBody(responseBody);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.apache.coyote.http11.controller;

import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;
import org.apache.coyote.http11.response.HttpStatus;
import org.apache.coyote.http11.response.ResponseBody;
import org.apache.coyote.http11.response.StaticResource;

public class IndexController extends AbstractController {

@Override
protected void doGet(HttpRequest request, HttpResponse response) throws Exception {
final StaticResource staticResource = StaticResource.from(Uri.INDEX.getFullPath());
final ResponseBody responseBody = ResponseBody.from(staticResource);
response.setHttpStatus(HttpStatus.OK);
response.setResponseBody(responseBody);
response.setResponseHeaders(responseBody);
}
}
Loading
Loading