Tìm hiểu Apache Camel
ApacheCamel
1
EIPs
1
White

studybot viết ngày 23/05/2015

Apache Camel là gì?

Là một framework xử lý message

Cho phép bạn định nghĩa các quy tắc routing mesage thông qua DSL và sẽ giúp bạn ném mesage đến các Endpoint thích hợp.

Đặc điểm nổi bật của Camel

  • Hỗ trợ nhiều endpoint cũng như transport thông qua URIs.
  • Định nghĩa endpoint và transport dễ dàng thông qua DSL (Java, XML, scala).
  • Cho phép người dùng nối Component của riêng mình.
  • Hỗ trợ rất nhiều định dạng dữ liệu. Cho phép người dùng định nghĩa Định dạng dữ liệu.
  • Framework nhẹ, ít tốn tài nguyên
  • Chạy trên nhiều nền tảng khác nhau:
    • JavaVM
    • Tomcat
    • GoogleAppEngine
    • JBoss
    • Groovy
    • JUnit
    • Jenkins

Danh sách các EIPs (copy từ https://www.graffletopia.com/stencils/137)

alt text

Người sử dụng Camel

  1. Từ trang chủ của Camel
  2. SAP HANA Cloud Integrations

Bài toán Camel giải quyết

Bài toán

Chép từ cuốn Camel in Action:

Our fictional motorcycle parts business, Rider Auto Parts, supplies parts to motorcycle manufacturers. Over the years, they’ve changed the way they receive orders several times. Initially, orders were placed by uploading comma-separated value (CSV) files to an FTP server. The message format was later changed to XML. Currently they provide a website through which orders are submitted as XML messages over HTTP.
Rider Auto Parts asks new customers to use the web interface to place orders, but because of service level agreements (SLAs) with existing customers, they must keep all the old message formats and interfaces up and running. All of these messages are con- verted to an internal Plain Old Java Object (POJO) format before processing. A high- level view of the order processing system is shown in figure 2.2.
Rider Auto Parts faces a pretty common problem: over years of operation, they have acquired software baggage in the form of transports and data formats that were popu- lar at the time. This is no problem for an integration framework like Camel, though. In this chapter, and throughout the book, you’ll help Rider Auto Parts implement their current requirements and new functionality using Camel.

Vấn đề

  • Theo thời gian số cách thức nhận đơn đặt hàng thay đổi: Từ upload csv lên máy chủ FTP thành giao diện web. (Transport, endpoint)
  • Thay đổi định dạng dữ liệu (CSV, XML)
  • Mỗi lần thay đổi code hoàn toàn (CSV --> XML, FTP --> HTTP) dù rằng pattern (nhận order) không đổi.

Camel giúp giải quyết vấn đề thay đổi này.!

Thử dùng camel

Bài toán

Hệ thống mình đang quản lý thường xuyên phải lấy log file từ nhiều nguồn khác nhau và đưa lên hadoop để xử lý. Log được gửi đến với định dạng tar.gz. Tuỳ loại log mà log có thể được phân tích bằng hadoop hay các đưa vào queue hay được lưu trữ ở một máy chủ lưu trữ (Storage Server) khác. Bài toán đơn giản là: theo dõi một thư mục và khi thư mục có file tar.gz mới thì giải nén và lưu file vào một thư mục khác

Giải quyết

Camel có File Component cho phép lắng nghe inotify để biết khi nào có file mới. Khi có file, component sẽ chia mỗi file thành 1 message. Bằng cách hook quá trình process message, ta có thể giải nén file theo ý muốn.

Code tham khảo

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.file.GenericFile;
import org.apache.camel.component.file.GenericFileFilter;
import org.apache.camel.main.Main;

import java.io.*;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;

class TarballFileFilter<T> implements GenericFileFilter<T> {
    @Override
    public boolean accept(GenericFile<T> file) {
        return (file.isDirectory() || file.getFileName().endsWith("tar.gz"));
    }
}

public class FileCopierWithCamel {

    private static String runCommand(String cmd) {
        StringBuilder result = new StringBuilder();
        try {
            Process p = Runtime.getRuntime().exec(cmd);
            p.waitFor();
            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result.toString();
    }

    static class TarGzProcessor implements Processor {
        @Override
        public void process(Exchange exchange) throws Exception {
            File f = exchange.getIn().getBody(File.class);
            if (f.getName().endsWith(".tar.gz")) {
                BufferedInputStream bufIS = new BufferedInputStream(new FileInputStream(f));
                GzipCompressorInputStream gzcIS = new GzipCompressorInputStream(bufIS);
                TarArchiveInputStream taIS = new TarArchiveInputStream(gzcIS);
                TarArchiveEntry entry = null;
                while ((entry = (TarArchiveEntry) taIS.getNextEntry()) != null) {
                    String fileName = entry.getName();
                    System.out.println("Extracting: " + fileName);

                    if (entry.isDirectory()) {
                        File d = new File(f.getParent() + "/" + fileName);
                        d.mkdir();
                    } else {
                        byte[] buffer = new byte[4096];
                        fileName = fileName.substring(0, fileName.length() - 7);
                        BufferedOutputStream outFile = new BufferedOutputStream(
                                new FileOutputStream(f.getParent() + "/" + fileName));

                        int readLen;
                        while ((readLen = taIS.read(buffer)) > 0) {
                            outFile.write(buffer, 0, readLen);
                        }
                        outFile.close();
                    }
                }
            }
        }
    }

    public static void main(String args[]) throws Exception {
        Main main = new Main();
        main.addRouteBuilder(new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("file:data/input?noop=true&recursive=true")
                        .process(new TarGzProcessor())
                        .to("file:data/output");
            }
        });
        main.run();
    }
}

Nhận xét

  • Sử dụng camel giúp code ngắn + dễ hiểu hơn.
  • Khi thay đổi endpoint ta chỉ việc thay đổi from / to

Tài liệu tham khảo

  1. Camel document
  2. EIPs
  3. Camel In Actions
Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

studybot

15 bài viết.
9 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
14 12
Một vài thủ thuật vim mới biết, ghi lại cho khỏi quên Căn lề các cột dữ liệu Để căn lề ấn phím esc (để sang command mode) :%column t Chọn th...
studybot viết 3 năm trước
14 12
White
9 9
Javascript context (ngữ cảnh?) là một khái niệm khó hiểu trong Javascript. Tuy vậy để code Javascript thành thạo thì việc nắm vững context là điểu ...
studybot viết 3 năm trước
9 9
White
8 1
Một vài ghi chép về Java Hotspot GC Garbage collector thực hiện việc quản lý bộ nhớ thông qua 3 công việc: Gán đối tượng vào pool các đối tượng m...
studybot viết hơn 3 năm trước
8 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
15 bài viết.
9 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!