Cơ Chế Xử Lý Yêu Cầu Trong Tomcat Qua Mô Hình Container Và Pipeline

Tomcat sử dụng hệ thống Container phân cấp gồm bốn thành phần chính: Engine, Host, Context và Wrapper. Mỗi thành phần đóng vai trò cụ thể trong quy trình xử lý yêu cầu HTTP:

  • Engine: Đại diện cho toàn bộ servlet engine, triển khai mặc định là MayChuEngine. Đây là cấp cao nhất trong cấu trúc.
  • Host: Quản lý các ứng dụng web ảo (tương ứng với tên miền), triển khai qua MayChuAo.
  • Context: Biểu diễn một ứng dụng web hoàn chỉnh (tương ứng với thư mục WEB-INF), triển khai bởi UngDungWeb.
  • Wrapper: Đóng gói một servlet cụ thể, triển khai qua GoServlet.

Tất cả Container đều kế thừa từ ContainerCoBan và tuân theo giao diện LifeCycle. Cơ chế xử lý yêu cầu dựa trên mô hình Pipeline-Valve, tương tự như chuỗi bộ lọc (Filter Chain) trong Servlet API:

  • Pipeline: Đại diện cho luồng xử lý yêu cầu.
  • Valve: Từng bước xử lý trong Pipeline, tương đương với Filter.

Quy trình xử lý bắt đầu từ Engine. Trong phương thức khởi tạo MayChuEngine, hệ thống thiết lập Valve mặc định:

public MayChuEngine() {
    super();
    // Cài đặt Valve mặc định
    pipelineDatMacDinh(new XuLyEngine());
    try {
        datDuongDanJvm(System.getProperty("jvmRoute"));
    } catch (Exception ex) {
        log.canhBao("Lỗi thiết lập đường dẫn JVM");
    }
    thoiGianXuLyNen = 10;
}

Phương thức xu_ly() của XuLyEngine định tuyến yêu cầu đến Host tương ứng:

public void xu_ly(YeuCau yeuCau, PhanHoi phanHoi) {
    MayChuAo mayChu = yeuCau.layMayChu();
    if (mayChu == null) {
        phanHoi.guiLoi(SC_BAD_REQUEST, "Không tìm thấy máy chủ");
        return;
    }
    // Chuyển yêu cầu cho Pipeline của Host
    mayChu.layPipeline().layDauTien().xu_ly(yeuCau, phanHoi);
}

Tương tự, MayChuAo chuyển tiếp yêu cầu đến Context:

public void xu_ly(YeuCau yeuCau, PhanHoi phanHoi) {
    UngDungWeb ungDung = yeuCau.layUngDung();
    if (ungDung == null) {
        phanHoi.guiLoi(SC_INTERNAL_SERVER_ERROR, "Không tìm thấy ứng dụng");
        return;
    }
    // Giao yêu cầu cho Context xử lý
    ungDung.layPipeline().layDauTien().xu_ly(yeuCau, phanHoi);
}

Quá trình kết thúc tại GoServlet với phương thức phân phối servlet:

public void xu_ly(YeuCau yeuCau, PhanHoi phanHoi) {
    GoServlet servletWrapper = (GoServlet) layContainer();
    Servlet servlet = null;
    
    try {
        // Cấp phát instance servlet
        servlet = servletWrapper.phanPhoi();
    } catch (UnavailableException e) {
        // Xử lý lỗi
    }
    
    // Tạo chuỗi bộ lọc
    ChainBoLoc filterChain = TaoChainBoLoc.tao(yeuCau, servletWrapper, servlet);
    
    // Thực thi chuỗi xử lý
    if (servlet != null && filterChain != null) {
        filterChain.thucHien(yeuCau, phanHoi);
    }
    
    // Giải phóng tài nguyên
    servletWrapper.giaiPhong(servlet);
}

Quy trình phân phối servlet trong GoServlet được triển khai như sau:

public Servlet phanPhoi() {
    if (instance == null) {
        synchronized (this) {
            if (instance == null) {
                instance = taiServlet();
                khoiDongServlet(instance);
            }
        }
    }
    return instance;
}

private Servlet taiServlet() {
    try {
        // Sử dụng ClassLoader của Context
        InstanceManager manager = ((UngDungWeb)layCha()).layManager();
        return (Servlet) manager.newInstance(servletClass);
    } catch (Exception e) {
        throw new ServletException("Lỗi tải servlet", e);
    }
}

Cơ chế Pipeline-Valve tạo thành chuỗi xử lý liên tục từ Engine xuống Wrapper. Mỗi Container chuyển tiếp yêu cầu qua phương thức xu_ly() của Valve đầu tiên trong Pipeline, đảm bảo luồng dữ liệu liền mạch cho đến khi servlet đích xử lý yêu cầu.

Thẻ: Tomcat Servlet pipeline valve Lifecycle

Đăng vào ngày 13 tháng 6 lúc 21:41