分享

Flume-ng生产环境实践(一)Flume-ng生产环境编译

本帖最后由 坎蒂丝_Swan 于 2015-1-12 14:16 编辑
问题导读
1.Flume-ng生产环境如何搭建?
2.flume-ng分布式日志是用来干什么的?











1.首先在系统上安装jdk1.6+和mvn3.X:
  1. $ java -version
  2.           java version "1.6.0_31"
  3. Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)
  4. Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)
  5. $ mvn -version
  6. Apache Maven 3.0.3 (r1075438; 2011-02-28 09:31:09-0800)
  7. Maven home: /usr/share/maven
  8. Java version: 1.6.0_31, vendor: Apple Inc.
  9. Java home: /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
  10. Default locale: en_US, platform encoding: MacRoman
  11. OS name: "mac os x", version: "10.7.3", arch: "x86_64", family: "mac"
复制代码


2.下载source code:
   
  1. $ svn co https://svn.apache.org/viewvc/flume/trunk/ flume
复制代码

3.编译发布:
  1. $ cd flume
  2. $ mvn clean install -DskipTests
复制代码
如果不跳过测试的话,会出现编译验证失败,由于测试过程中,在flume-ng-core项目下生成event.txt测试文件。需要删除才可以编译通过。详情了解地址:
  1. https://issues.apache.org/jira/browse/FLUME-1372
  2. $ cp flume-ng-dist/target/flume-ng-dist-1.3.0-SNAPSHOT-dist.tar.gz . $ tar -zxvf apache-flume-1.3.0-SNAPSHOT-dist.tar.gz $ cd flume-1.3.0-SNAPSHOT
  3. $ cp conf/flume-conf.properties.template conf/flume.conf
  4. $ cp conf/flume-env.sh.template conf/flume-env.sh
复制代码

通过配置即可以开始启动flume-ng这个分布式日志收集系统了。
编译过程可能发现内存溢出问题。
windows下修改mvn.bat
增加这一行即可:
set MAVEN_OPTS= -Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m
linux下修改/etc/profile
  1. export MAVEN_OPTS="-Xms2048m -Xmx3072m -XX:MaxPermSize=1024m"
  2. source /etc/profile
复制代码

编译过程发现
flume-ng-core下scripts/saveVersion.sh无权限执行的时候,给这个脚本赋权就好了
  1. chmod 755 scripts/saveVersion.sh
复制代码
编译过程可能发生
Failed to execute goal org.apache.rat:apache-rat-plugin:0.7:check (test.
rat) on project flume-ng-core: Too many unapproved licenses: 1 -> [Help 1]
删除flume-ng-core的\src\test\resources\event.txt即可
4.线上测试:
     a.单机测试
          flume-ng启动agent的命令为:
  1. $ bin/flume-ng agent -n $agent_name -c conf -f conf/flume-conf.properties.template
复制代码

添加如下配置文件
  1. example.conf
  2. # example.conf: A single-node Flume configuration
  3. # Name the components on this agent
  4. agent1.sources = source1
  5. agent1.sinks = sink1
  6. agent1.channels = channel1
  7. # Describe/configure source1
  8. agent1.sources.source1.type = netcat
  9. agent1.sources.source1.bind = localhost
  10. agent1.sources.source1.port = 44444
  11. # Describe sink1
  12. agent1.sinks.sink1.type = logger
  13. # Use a channel which buffers events in memory
  14. agent1.channels.channel1.type = memory
  15. agent1.channels.channel1.capacity = 1000
  16. agent1.channels.channel1.transactionCapactiy = 100
  17. # Bind the source and sink to the channel
  18. agent1.sources.source1.channels = channel1
  19. agent1.sinks.sink1.channel = channel1
复制代码
以上配置信息描述的是:

该配置文件中 配置了一个代理agent1
在代理agent中配置了一个source(源)一个sink(接收器)和一个channel(通道),分别为:source1,sink1,channel1
source1的类型定义为netcat,对应该类型参数为bind和port 分别为localhost和44444
sink1的类型定义为logger,直接输出到日志文件中
channel的类型定义为内存方式,设置其参数capactiy和transactionCapacity分别为1000和100
指定source1和sink1的channel为channel1

现在我们可以启动看看我们的flume-ng是否成功。

在flume-ng的home目录下
  1. $ bin/flume-ng agent --conf-file example.conf --name agent1 -Dflume.root.logger=INFO,console --conf = conf
复制代码
启动之后日志信息如下:
  1. 2012-07-30 15:42:30,708 (main) [INFO - org.apache.flume.lifecycle.LifecycleSupervisor.start(LifecycleSupervisor.java:67)] Starting lifecycle supervisor 1
  2. 2012-07-30 15:42:30,713 (main) [INFO - org.apache.flume.node.FlumeNode.start(FlumeNode.java:54)] Flume node starting - agent1
  3. 2012-07-30 15:42:30,715 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.start(DefaultLogicalNodeManager.java:187)] Node manager starting
  4. 2012-07-30 15:42:30,716 (lifecycleSupervisor-1-2) [INFO - org.apache.flume.conf.file.AbstractFileConfigurationProvider.start(AbstractFileConfigurationProvider.java:67)] Configuration provider starting
  5. 2012-07-30 15:42:30,718 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.lifecycle.LifecycleSupervisor.start(LifecycleSupervisor.java:67)] Starting lifecycle supervisor 11
  6. 2012-07-30 15:42:30,720 (conf-file-poller-0) [INFO - org.apache.flume.conf.file.AbstractFileConfigurationProvider$FileWatcherRunnable.run(AbstractFileConfigurationProvider.java:195)] Reloading configuration file:example.conf
  7. 2012-07-30 15:42:30,726 (conf-file-poller-0) [INFO - org.apache.flume.conf.FlumeConfiguration$AgentConfiguration.addProperty(FlumeConfiguration.java:988)] Processing:sink1
  8. 2012-07-30 15:42:30,726 (conf-file-poller-0) [INFO - org.apache.flume.conf.FlumeConfiguration$AgentConfiguration.addProperty(FlumeConfiguration.java:988)] Processing:sink1
  9. 2012-07-30 15:42:30,726 (conf-file-poller-0) [INFO - org.apache.flume.conf.FlumeConfiguration$AgentConfiguration.addProperty(FlumeConfiguration.java:902)] Added sinks: sink1 Agent: agent1
  10. 2012-07-30 15:42:30,747 (conf-file-poller-0) [INFO - org.apache.flume.conf.FlumeConfiguration.validateConfiguration(FlumeConfiguration.java:122)] Post-validation flume configuration contains configuration  for agents: [agent1]
  11. 2012-07-30 15:42:30,747 (conf-file-poller-0) [INFO - org.apache.flume.conf.properties.PropertiesFileConfigurationProvider.loadChannels(PropertiesFileConfigurationProvider.java:249)] Creating channels
  12. 2012-07-30 15:42:30,808 (conf-file-poller-0) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.<init>(MonitoredCounterGroup.java:68)] Monitoried counter group for type: CHANNEL, name: channel1, registered successfully.
  13. 2012-07-30 15:42:30,808 (conf-file-poller-0) [INFO - org.apache.flume.conf.properties.PropertiesFileConfigurationProvider.loadChannels(PropertiesFileConfigurationProvider.java:273)] created channel channel1
  14. 2012-07-30 15:42:30,828 (conf-file-poller-0) [INFO - org.apache.flume.sink.DefaultSinkFactory.create(DefaultSinkFactory.java:70)] Creating instance of sink: sink1, type: logger
  15. 2012-07-30 15:42:30,832 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:92)] Starting new configuration:{ sourceRunners:{source1=EventDrivenSourceRunner: { source:org.apache.flume.source.NetcatSource@18f1d7e }} sinkRunners:{sink1=SinkRunner: { policy:org.apache.flume.sink.DefaultSinkProcessor@d9660d counterGroup:{ name:null counters:{} } }} channels:{channel1=org.apache.flume.channel.MemoryChannel@bb0d0d} }
  16. 2012-07-30 15:42:30,832 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:99)] Starting Channel channel1
  17. 2012-07-30 15:42:30,835 (lifecycleSupervisor-1-0) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.start(MonitoredCounterGroup.java:82)] Component type: CHANNEL, name: channel1 started
  18. 2012-07-30 15:42:30,835 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:114)] Waiting for channel: channel1 to start. Sleeping for 500 ms
  19. 2012-07-30 15:42:31,338 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:127)] Starting Sink sink1
  20. 2012-07-30 15:42:31,338 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:138)] Starting Source source1
  21. 2012-07-30 15:42:31,339 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.source.NetcatSource.start(NetcatSource.java:147)] Source starting
  22. 2012-07-30 15:42:31,358 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.source.NetcatSource.start(NetcatSource.java:161)] Created serverSocket:sun.nio.ch.ServerSocketChannelImpl[/127.0.0.1:44444]
复制代码

我们打开另外一个console:执行 telnet localhost 44444
  1. Trying 127.0.0.1...
  2. Connected to localhost.localdomain (127.0.0.1).
  3. Escape character is '^]'.
  4. haha
  5. OK
复制代码

在日志控制台,我们看到如下信息
  1. 2012-07-30 15:42:40,780 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:70)] Event: { headers:{} body: 68 61 68 61 0D                                  haha. }
复制代码

说明我们的flume-ng运行良好。可以继续下一步操作…………


b.flume-ng 测试过程中event丢失部分body数据
          经过测试发现,当source端单event的body数据大于16字节后,输出到目标只剩下16字节。进过多源代码的分析,发现,源代码中进行了截取。
在LoggerSink.java中:
  1. if (event != null) {
  2.         if (logger.isInfoEnabled()) {
  3.           logger.info("Event: " + EventHelper.dumpEvent(event));
  4.         }
  5. }
复制代码

我们去看EventHelper.java的dumpEvent方法:

  1. private static final int DEFAULT_MAX_BYTES = 16;
  2. public static String dumpEvent(Event event) {
  3.     return dumpEvent(event, DEFAULT_MAX_BYTES);
  4. }
  5. public static String dumpEvent(Event event, int maxBytes) {
  6.     StringBuilder buffer = new StringBuilder();
  7.     if (event == null || event.getBody() == null) {
  8.       buffer.append("null");
  9.     } else if (event.getBody().length == 0) {
  10.       // do nothing... in this case, HexDump.dump() will throw an exception
  11.     } else {
  12.       byte[] body = event.getBody();
  13.       byte[] data = Arrays.copyOf(body, Math.min(body.length, maxBytes));
  14.       ByteArrayOutputStream out = new ByteArrayOutputStream();
  15.       try {
  16.         HexDump.dump(data, 0, out, 0);
  17.         String hexDump = new String(out.toByteArray());
  18.         // remove offset since it's not relevant for such a small dataset
  19.         if(hexDump.startsWith(HEXDUMP_OFFSET)) {
  20.           hexDump = hexDump.substring(HEXDUMP_OFFSET.length());
  21.         }
  22.         buffer.append(hexDump);
  23.       } catch (Exception e) {
  24.        if(LOGGER.isInfoEnabled()) {
  25.          LOGGER.info("Exception while dumping event", e);
  26.        }
  27.         buffer.append("...Exception while dumping: ").append(e.getMessage());
  28.       }
  29.       String result = buffer.toString();
  30.       if(result.endsWith(EOL) && buffer.length() > EOL.length()) {
  31.         buffer.delete(buffer.length() - EOL.length(), buffer.length()).toString();
  32.       }
  33.     }
  34.     return "{ headers:" + event.getHeaders() + " body:" + buffer + " }";
  35.   }
复制代码

不难看出,在event处理过程中,发生了数据截取操作。

     c.flume-ng avro2log demo配置详解(多机器)

flume-ng启动agent的命令为:
$ bin/flume-ng agent -n $agent_name -c conf -f conf/flume-conf.properties.template
添加如下配置文件
  1. avro2log.conf
  2. # avro2log.conf: A single-node Flume configuration
  3. # excute next command in flumeng home dir
  4. # bin/flume-ng agent --conf conf  --conf-file conf/avro2log.conf --name agent1 -Dflume.root.logger=INFO,console
  5. # Name the components on this agent
  6. agent1.sources = source1
  7. agent1.sinks = sink1
  8. agent1.channels = channel1
  9. # Describe/configure source1
  10. agent1.sources.source1.type = avro
  11. agent1.sources.source1.bind = 192.168.1.101
  12. agent1.sources.source1.port = 44444
  13. # Describe sink1
  14. agent1.sinks.sink1.type = logger
  15. # Use a channel which buffers events in memory
  16. agent1.channels.channel1.type = memory
  17. agent1.channels.channel1.capacity = 1000
  18. agent1.channels.channel1.transactionCapactiy = 100
  19. # Bind the source and sink to the channel
  20. agent1.sources.source1.channels = channel1
  21. agent1.sinks.sink1.channel = channel1
复制代码

现在我们可以启动看看我们的flume-ng是否成功。

在flume-ng的home目录下
$ bin/flume-ng agent --conf-file avro2log.conf --name agent1 -Dflume.root.logger=INFO,console --conf = conf
启动之后日志信息如下:
  1. 2012-08-08 14:53:17,522 (main) [INFO - org.apache.flume.lifecycle.LifecycleSupervisor.start(LifecycleSupervisor.java:67)] Starting lifecycle supervisor 1
  2. 2012-08-08 14:53:17,527 (main) [INFO - org.apache.flume.node.FlumeNode.start(FlumeNode.java:54)] Flume node starting - agent1
  3. 2012-08-08 14:53:17,530 (lifecycleSupervisor-1-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.start(DefaultLogicalNodeManager.java:187)] Node manager starting
  4. 2012-08-08 14:53:17,533 (lifecycleSupervisor-1-0) [INFO - org.apache.flume.lifecycle.LifecycleSupervisor.start(LifecycleSupervisor.java:67)] Starting lifecycle supervisor 10
  5. 2012-08-08 14:53:17,531 (lifecycleSupervisor-1-2) [INFO - org.apache.flume.conf.file.AbstractFileConfigurationProvider.start(AbstractFileConfigurationProvider.java:67)] Configuration provider starting
  6. 2012-08-08 14:53:17,534 (conf-file-poller-0) [INFO - org.apache.flume.conf.file.AbstractFileConfigurationProvider$FileWatcherRunnable.run(AbstractFileConfigurationProvider.java:195)] Reloading configuration file:conf/avro2log.conf
  7. 2012-08-08 14:53:17,540 (conf-file-poller-0) [INFO - org.apache.flume.conf.FlumeConfiguration$AgentConfiguration.addProperty(FlumeConfiguration.java:988)] Processing:sink1
  8. 2012-08-08 14:53:17,541 (conf-file-poller-0) [INFO - org.apache.flume.conf.FlumeConfiguration$AgentConfiguration.addProperty(FlumeConfiguration.java:988)] Processing:sink1
  9. 2012-08-08 14:53:17,541 (conf-file-poller-0) [INFO - org.apache.flume.conf.FlumeConfiguration$AgentConfiguration.addProperty(FlumeConfiguration.java:902)] Added sinks: sink1 Agent: agent1
  10. 2012-08-08 14:53:17,562 (conf-file-poller-0) [INFO - org.apache.flume.conf.FlumeConfiguration.validateConfiguration(FlumeConfiguration.java:122)] Post-validation flume configuration contains configuration  for agents: [agent1]
  11. 2012-08-08 14:53:17,562 (conf-file-poller-0) [INFO - org.apache.flume.conf.properties.PropertiesFileConfigurationProvider.loadChannels(PropertiesFileConfigurationProvider.java:249)] Creating channels
  12. 2012-08-08 14:53:17,622 (conf-file-poller-0) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.<init>(MonitoredCounterGroup.java:68)] Monitoried counter group for type: CHANNEL, name: channel1, registered successfully.
  13. 2012-08-08 14:53:17,622 (conf-file-poller-0) [INFO - org.apache.flume.conf.properties.PropertiesFileConfigurationProvider.loadChannels(PropertiesFileConfigurationProvider.java:273)] created channel channel1
  14. 2012-08-08 14:53:17,634 (conf-file-poller-0) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.<init>(MonitoredCounterGroup.java:68)] Monitoried counter group for type: SOURCE, name: source1, registered successfully.
  15. 2012-08-08 14:53:17,646 (conf-file-poller-0) [INFO - org.apache.flume.sink.DefaultSinkFactory.create(DefaultSinkFactory.java:70)] Creating instance of sink: sink1, type: logger
  16. 2012-08-08 14:53:17,650 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:92)] Starting new configuration:{ sourceRunners:{source1=EventDrivenSourceRunner: { source:Avro source source1: { bindAddress: localhost, port: 44444 } }} sinkRunners:{sink1=SinkRunner: { policy:org.apache.flume.sink.DefaultSinkProcessor@18f1d7e counterGroup:{ name:null counters:{} } }} channels:{channel1=org.apache.flume.channel.MemoryChannel@d9660d} }
  17. 2012-08-08 14:53:17,652 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:99)] Starting Channel channel1
  18. 2012-08-08 14:53:17,653 (lifecycleSupervisor-1-0) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.start(MonitoredCounterGroup.java:82)] Component type: CHANNEL, name: channel1 started
  19. 2012-08-08 14:53:17,653 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:114)] Waiting for channel: channel1 to start. Sleeping for 500 ms
  20. 2012-08-08 14:53:18,156 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:127)] Starting Sink sink1
  21. 2012-08-08 14:53:18,156 (conf-file-poller-0) [INFO - org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents(DefaultLogicalNodeManager.java:138)] Starting Source source1
  22. 2012-08-08 14:53:18,157 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.source.AvroSource.start(AvroSource.java:138)] Starting Avro source source1: { bindAddress: localhost, port: 44444 }...
  23. 2012-08-08 14:53:18,565 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.start(MonitoredCounterGroup.java:82)] Component type: SOURCE, name: source1 started
  24. 2012-08-08 14:53:18,565 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.source.AvroSource.start(AvroSource.java:155)] Avro source source1 started.
复制代码

打开另外一个机器(192.168.1.102)consloe:

在目录/data/flumetmp下创建文件a
执行echo 11111111 >>a
我们再打开另外一个机器(192.168.1.102):执行
bin/flume-ng avro-client --conf conf -H 192.168.1.101 -p 44444 -F /data/flumetmp/a
显示:
+ exec /opt/soft/jdk/bin/java -Xmx20m -cp '/data/software/flumeng/conf:/data/software/flumeng/lib/*' -Djava.library.path= org.apache.flume.client.avro.AvroCLIClient -H 192.168.1.101 -p 44444 -F /data/flumetmp/a

在日志控制台,我们看到如下信息
  1. 2012-08-08 14:53:18,565 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.start(MonitoredCounterGroup.java:82)] Component type: SOURCE, name: source1 started
  2. 2012-08-08 14:53:18,565 (lifecycleSupervisor-1-1) [INFO - org.apache.flume.source.AvroSource.start(AvroSource.java:155)] Avro source source1 started.
  3. 2012-08-08 15:27:30,298 (New I/O server boss #1 ([id: 0x0050a649, /192.168.1.101:44444])) [INFO - org.apache.avro.ipc.NettyServer$NettyServerAvroHandler.handleUpstream(NettyServer.java:141)] [id: 0x01c208b0, /192.168.1.102:55565 => /192.168.1.101:44444] OPEN
  4. 2012-08-08 15:27:30,304 (New I/O server worker #1-1) [INFO - org.apache.avro.ipc.NettyServer$NettyServerAvroHandler.handleUpstream(NettyServer.java:141)] [id: 0x01c208b0, /192.168.1.102:55565 => /192.168.1.101:44444] BOUND: /192.168.1.101:44444
  5. 2012-08-08 15:27:30,304 (New I/O server worker #1-1) [INFO - org.apache.avro.ipc.NettyServer$NettyServerAvroHandler.handleUpstream(NettyServer.java:141)] [id: 0x01c208b0, /192.168.1.102:55565 => /192.168.1.101:44444] CONNECTED: /192.168.1.102:55565
  6. 2012-08-08 15:27:30,749 (New I/O server worker #1-1) [INFO - org.apache.avro.ipc.NettyServer$NettyServerAvroHandler.handleUpstream(NettyServer.java:141)] [id: 0x01c208b0, /192.168.1.102:55565 :> /192.168.1.101:44444] DISCONNECTED
  7. 2012-08-08 15:27:30,749 (New I/O server worker #1-1) [INFO - org.apache.avro.ipc.NettyServer$NettyServerAvroHandler.handleUpstream(NettyServer.java:141)] [id: 0x01c208b0, /192.168.1.102:55565 :> /192.168.1.101:44444] UNBOUND
  8. 2012-08-08 15:27:30,749 (New I/O server worker #1-1) [INFO - org.apache.avro.ipc.NettyServer$NettyServerAvroHandler.handleUpstream(NettyServer.java:141)] [id: 0x01c208b0, /192.168.1.102:55565 :> /192.168.1.101:44444] CLOSED
  9. 2012-08-08 15:27:33,227 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:70)] Event: { headers:{} body: 31 31 31 31 31 31                               111111 }
复制代码

avro source执行成功!

         



Flume-ng生产环境实践(一)Flume-ng生产环境编译
Flume-ng生产环境实践(二)flume-ng 测试过程中event丢失部分body数据
Flume-ng生产环境实践(三)实现文件sink,按照固定格式目录输出
Flume-ng生产环境实践(四)实现log格式化interceptor


欢迎加入about云群90371779322273151432264021 ,云计算爱好者群,亦可关注about云腾讯认证空间||关注本站微信

已有(5)人评论

跳转到指定楼层
stark_summer 发表于 2015-1-12 13:52:20
回复

使用道具 举报

355815741 发表于 2015-1-12 22:22:42
学习了,谢谢分享~
回复

使用道具 举报

hb1984 发表于 2015-1-15 13:30:42
谢谢楼主分享。         
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条