Apache Camel - 基于正文

时间:2017-08-17 22:35:57

标签: java amazon-s3 apache-camel

我目前正在使用apache camel来使用SQS消息,而且一切正常。

作为一个项目的一部分,我在上传文件时使用S3通知事件。文件将上载到可预测的S3密钥 - (<type>/<account-id>/<id>/<file>)

处理时,我使用camel将消息聚合到一个交换中(等待10条消息,或者在1秒后超时)。我想知道但是,是否有基于S3聚合的方法 - 例如,具有相同类型或id的聚合消息。

根据我从阅读骆驼文档中的理解,有方法可以查询Json有效负载或标头值 - 这是一种可能的方法(因为S3事件通知是Json消息,并且根据AWS文档,PUT操作会只生成一个记录条目)?或者我需要实现自己的聚合器吗?

要添加一些上下文 - 我有一个收集数据的服务,并将数据上传到S3。然后,另一项服务将在收到通知后下载此数据,处理并上传到另一个存储桶。如果我可以聚合S3通知,我可以将数据组合并上传,减少上传量和API调用等。

2 个答案:

答案 0 :(得分:1)

如果您使用camel-aws s3组件,则可以从Message的#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <netdb.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 9909 void die ( const char *fmt, ... ) { va_list vargs; va_start( vargs, fmt ); vfprintf( stderr, fmt, vargs ); va_end( vargs ); exit( 1 ); } int main ( int argc, char **argv ) { /* *** */ int listener = socket( PF_INET, SOCK_STREAM, 0 ); if( listener < 0 ) die( "socket(listener)" ); int flag = 1; if( setsockopt( listener, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(int) ) < 0 ) die( "setsockopt()" ); struct sockaddr_in svr_addr; memset( &svr_addr, 0, sizeof(struct sockaddr) ); svr_addr.sin_family = PF_INET; svr_addr.sin_port = htons( PORT ); svr_addr.sin_addr.s_addr = INADDR_ANY; if( bind( listener, (struct sockaddr*)&svr_addr, (socklen_t)sizeof(struct sockaddr) ) < 0 ) die( "bind()" ); if( listen( listener, 10 ) < 0 ) die( "listen()" ); /* *** */ fd_set fd_master; fd_set fd_select; int fd_max = listener; FD_ZERO( &fd_master ); FD_ZERO( &fd_select ); FD_SET( listener, &fd_master ); while( 1 ) { fd_select = fd_master; if( select( fd_max + 1, &fd_select, NULL, NULL, NULL ) < 0 ) die( "select()" ); for( int ifd = 0; ifd <= fd_max; ++ifd ) { if( ! FD_ISSET( ifd, &fd_select ) ) continue; struct sockaddr_in cli_addr; memset( &cli_addr, 0, sizeof(cli_addr) ); socklen_t cli_alen = sizeof(cli_addr); if( ifd == listener ) { int cli = accept( listener, (struct sockaddr*)&cli_addr, &cli_alen ); if( cli < 0 ) die( "accept()" ); FD_SET( cli, &fd_master ); if( cli > fd_max ) fd_max = cli; printf( "new connection> %s:%u\n", inet_ntoa( cli_addr.sin_addr ), ntohs( cli_addr.sin_port ) ); fflush( stdout ); } else { char buf[256]; cli_alen = sizeof(cli_addr); ssize_t nbytes = recvfrom( ifd, buf, sizeof(buf), 0, (struct sockaddr*)&cli_addr, &cli_alen ); if( nbytes <= 0 ) { close( ifd ); FD_CLR( ifd, &fd_master ); if( nbytes == 0 ) printf( "connection hung up> %u\n", ifd ); else printf( "recvfrom() : %s\n", strerror( errno ) ); fflush( stdout ); } else { // build a "from identifier" for each of the recipients char msg[sizeof(buf) * 2]; sprintf( msg, "%s:%u> ", inet_ntoa( cli_addr.sin_addr ), ntohs( cli_addr.sin_port ) ); memcpy( msg + strlen( msg ), buf, nbytes ); nbytes += strlen( msg ); // send incoming data to all clients (excluding the originator) for( int ofd = 0; ofd <= fd_max; ++ofd ) { if( FD_ISSET( ofd, &fd_master ) ) if( ofd != listener && ofd != ifd ) if( send( ofd, msg, nbytes, 0 ) < 0 ) { printf( "send() %s\n", strerror( errno ) ); fflush( stdout ); } } } } } } return 0; } 标题中访问/获取S3密钥,而无需查询正文,但需要提取必填字段来自S3键。

答案 1 :(得分:0)

虽然不是最好或最通用的解决方案,但我确实找到了一种方法来实现这一点 -

我只是添加了一个在传递给聚合器之前被调用的额外处理器。处理器只是检查事件记录(因为我正在侦听来自S3的PUT事件,根据AWS文档,应该只有一条记录)用于S3密钥并在消息上设置标题。

然后,聚合器可以根据这些标头组合Exchange(只需 S3-Type S3-Account-Id S3-Id )。