2012-11-20 1 views
2

로그 메시지를 GZIP로 인코딩하고 UDP로 보내야하는 로깅 시스템을 구현하고 있습니다. 내가 지금까지있어 무엇GZIP 및 UDP에 가장 빠른 방법은 Java에서 대량의 문자열입니다.

은 다음과 같습니다

초기화 :이의 PrintStream가 다음 로거에서 전달되는

DatagramSocket sock = new DatagramSocket(); 
baos = new ByteArrayOutputStream(); 
printStream = new PrintStream(new GZIPOutputStream(baos)); 

- 메시지는 그 다음

때마다 메시지를 통해 도착합니다 도착 :

byte[] d = baos.toByteArray(); 
DatagramPacket dp = new DatagramPacket(d,d.length,host,port); 
sock.send(dp); 

나는 현재 나를 괴롭 히며 방법은 ByteArrayOutputStream에서 데이터를 제거하려면 (toByteArray()는 복사본을 가져옵니다) 나는 매번 세 개의 스트림 객체를 재생성하는 것이 비효율적 일 것이라고 생각합니다.

보낸 데이터를 스트림에서 제거 할 수있는 방법이 있습니까? 아니면 전 완전히 다른 방향으로보아야합니까?

+1

참고 : 문자열이 짧으면 GZIP이면 더 커집니다. –

답변

0

대답은 내 문제의 다른 측면에 도움이되었다, 그러나 실제 질문에 대한 -있는 ByteArrayOutputStream에서 데이터를 삭제하는 방법이 . 그것은 reset() 메소드를 가지고있다. 실제로 버퍼를 지우지는 않지만 count 속성을 0으로 재설정하여 버퍼에 이미있는 데이터를 무시하게합니다.

기본 ByteArrayOutputStream을 재설정 한 후 GZIPOutputStream에 기록하면 오류가 발생하므로 모든 것을 재사용 할 수있는 방법을 찾지 못했습니다.

1

각 메시지에 대해 새 스트림을 만들어야합니다. 그렇지 않으면 toByteArray()을 호출 할 때마다 이전의 모든 메시지가 다시 전송됩니다.

더 좋은 방법은 GZIPOutputStream와 TCP 소켓의 OutputStream을 래핑하는 아마 :

printStream = new PrintStream(new GZIPOutputStream(sock.getOutputStream())); 

는 또한 모든 메시지 나 일어날 아무것도 후 PrintStream를 플러시하는 것을 잊지 마세요.

속도가 정말 중요하다면 오래된 (느린) 증기 API 대신 DatagramChannel을 사용해야합니다. 이것은 당신이 시작할 수 있어야합니다

ByteBuffer buffer = ByteBuffer.allocate(1000); 
ByteBufferOutputStream bufferOutput = new ByteBufferOutputStream(buffer); 
GZIPOutputStream output = new GZIPOutputStream(bufferOutput); 
OutputStreamWriter writer = new OutputStreamWriter(output, "UTF-8"); 
writer.write("log message\n"); 
writer.close(); 

sock.getChannel().open(); // do this once 
sock.getChannel().write(buffer); // Send compressed data 

참고 : 당신은 그것을 되감기하여 buffer를 재사용 할 수 있지만, 모든 스트림 메시지 당 한 번만 작성해야합니다.

1

속도가 중요한 경우 GZIP을 사용하면 도움이되는지 확인하는 것이 좋습니다. (그것은 약간의 대기 시간을 추가합니다)

public static void main(String... args) throws IOException { 
    test("Hello World"); 
    test("Nov 20, 2012 4:55:11 PM Main main\n" + 
      "INFO: Hello World log message"); 
} 

private static void test(String s) throws IOException { 
    byte[] bytes = s.getBytes("UTF-8"); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    GZIPOutputStream outputStream = new GZIPOutputStream(baos); 
    outputStream.write(bytes); 
    outputStream.close(); 
    byte[] bytes2 = baos.toByteArray(); 
    System.out.println("'" + s + "' raw.length=" + bytes.length + " gzip.length=" + bytes2.length); 
} 

인쇄

'Hello World' raw.length=11 gzip.length=31 
'Nov 20, 2012 4:55:11 PM Main main 
INFO: Hello World log message' raw.length=63 gzip.length=80 
+0

GZIP는 내 결정이 아닙니다. Graylog에 로그 메시지를 보내서 GZIP와 UDP를 강제로 보내겠습니다. –

+0

호환성을 위해 GZIP가 합리적입니다. 효율성을 획기적으로 향상시킬 로그 항목을 일괄 적으로 결합하는 방법을 찾을 수 있다면. BTW DeflatorOutputStream은 앞으로 옵션이 될 경우 훨씬 더 작은 머리글/바닥 글을 갖습니다. –

관련 문제