热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Flumeng+Kafka+storm的学习笔记

Flume-ngFlume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。     Flume的文档可以看http:flume.apache.orgFlumeUser

Flume-ng

Flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。

 

     Flume的文档可以看http://flume.apache.org/FlumeUserGuide.html 官方的英文文档 介绍的比较全面。

       不过这里写写自己的见解

Flume-ng+Kafka+storm的学习笔记Flume-ng+Kafka+storm的学习笔记

 

这个是flume的架构图

 从上图可以看到几个名词:

Agent: 一个Agent包含Source、Channel、Sink和其他的组件。Flume就是一个或多个Agent构成的。

      Source:数据源。简单的说就是agent获取数据的入口 。

       Channel:管道。数据流通和存储的通道。一个source必须至少和一个channel关联。

       Sink:用来接收channel传输的数据并将之传送到指定的地方。传送成功后数据从channel中删除。

 

Flume具有高可扩展性 可随意组合:

 

 Flume-ng+Kafka+storm的学习笔记Flume-ng+Kafka+storm的学习笔记

注意 source是接收源 sink是发送源

Flume-ng+Kafka+storm的学习笔记

Flume-ng+Kafka+storm的学习笔记Flume-ng+Kafka+storm的学习笔记Flume-ng+Kafka+storm的学习笔记

 

 

上图是一个source将数据发给3个channel 其中的sink2将数据发给JMS ,sink3将数据发给另一个source。

总的来说flume的扩展性非常高 根据需要可随意组合。

现在在说说一个概念叫Event:

       Event是flume的数据传输的基本单元。Flume本质上是将数据作为一个event从源头传到结尾。是由可选的Headers和载有数据的一个byte array构成。

  代码结构:

 

 

[java] view plaincopyprint?
 
  1. /** 
  2.  * Basic representation of a data object inFlume. 
  3.  * Provides access to data as it flows throughthe system. 
  4.  */  
  5. public interface Event{  
  6.   /** 
  7.    * Returns a map of name-valuepairs describing the data stored in the body. 
  8.    */  
  9.   public Map getHeaders();  
  10.   /** 
  11.    * Set the event headers 
  12.    * @param headersMap of headers to replace the current headers. 
  13.    */  
  14.   public void setHeaders(Map headers);  
  15.   /** 
  16.    * Returns the raw byte array of the datacontained in this event. 
  17.    */  
  18.   public byte[] getBody();  
  19.   /** 
  20.    * Sets the raw byte array of the datacontained in this event. 
  21.    * @param body Thedata. 
  22.    */  
  23.   public void setBody(byte[] body);  
  24. }  



 

这个是网上找的flume channel ,source,sink的汇总

链接是http://abloz.com/2013/02/26/flume-channel-source-sink-summary.html

Component

Type

Description

Implementation Class

Channel

memory

In-memory, fast, non-durable event transport

MemoryChannel

Channel

file

A channel for reading, writing, mapping, and manipulating a file

FileChannel

Channel

jdbc

JDBC-based, durable event transport (Derby-based)

JDBCChannel

Channel

recoverablememory

A durable channel implementation that uses the local file system for its storage

RecoverableMemoryChannel

Channel

org.apache.flume.channel.PseudoTxnMemoryChannel

Mainly for testing purposes. Not meant for production use.

PseudoTxnMemoryChannel

Channel

(custom type as FQCN)

Your own Channel impl.

(custom FQCN)

Source

avro

Avro Netty RPC event source

AvroSource

Source

exec

Execute a long-lived Unix process and read from stdout

ExecSource

Source

netcat

Netcat style TCP event source

NetcatSource

Source

seq

Monotonically incrementing sequence generator event source

SequenceGeneratorSource

Source

org.apache.flume.source.StressSource

Mainly for testing purposes. Not meant for production use. Serves as a continuous source of events where each event has the same payload. The payload consists of some number of bytes (specified bysize property, defaults to 500) where each byte has the signed value Byte.MAX_VALUE (0x7F, or 127).

org.apache.flume.source.StressSource

Source

syslogtcp

SyslogTcpSource

Source

syslogudp

SyslogUDPSource

Source

org.apache.flume.source.avroLegacy.AvroLegacySource

AvroLegacySource

Source

org.apache.flume.source.thriftLegacy.ThriftLegacySource

ThriftLegacySource

Source

org.apache.flume.source.scribe.ScribeSource

ScribeSource

Source

(custom type as FQCN)

Your own Source impl.

(custom FQCN)

Sink

hdfs

Writes all events received to HDFS (with support for rolling, bucketing, HDFS-200 append, and more)

HDFSEventSink

Sink

org.apache.flume.sink.hbase.HBaseSink

A simple sink that reads events from a channel and writes them to HBase.

org.apache.flume.sink.hbase.HBaseSink

Sink

org.apache.flume.sink.hbase.AsyncHBaseSink

org.apache.flume.sink.hbase.AsyncHBaseSink

Sink

logger

Log events at INFO level via configured logging subsystem (log4j by default)

LoggerSink

Sink

avro

Sink that invokes a pre-defined Avro protocol method for all events it receives (when paired with an avro source, forms tiered collection)

AvroSink

Sink

file_roll

RollingFileSink

Sink

irc

IRCSink

Sink

null

/dev/null for Flume – blackhole all events received

NullSink

Sink

(custom type as FQCN)

Your own Sink impl.

(custom FQCN)

ChannelSelector

replicating

ReplicatingChannelSelector

ChannelSelector

multiplexing

MultiplexingChannelSelector

ChannelSelector

(custom type)

Your own ChannelSelector impl.

(custom FQCN)

SinkProcessor

default

DefaultSinkProcessor

SinkProcessor

failover

FailoverSinkProcessor

SinkProcessor

load_balance

Provides the ability to load-balance flow over multiple sinks.

LoadBalancingSinkProcessor

SinkProcessor

(custom type as FQCN)

Your own SinkProcessor impl.

(custom FQCN)

Interceptor$Builder

host

HostInterceptor$Builder

Interceptor$Builder

timestamp

TimestampInterceptor

TimestampInterceptor$Builder

Interceptor$Builder

static

StaticInterceptor$Builder

Interceptor$Builder

regex_filter

RegexFilteringInterceptor$Builder

Interceptor$Builder

(custom type as FQCN)

Your own Interceptor$Builder impl.

(custom FQCN)

EventSerializer$Builder

text

BodyTextEventSerializer$Builder

EventSerializer$Builder

avro_event

FlumeEventAvroEventSerializer$Builder

EventSerializer

org.apache.flume.sink.hbase.SimpleHbaseEventSerializer

SimpleHbaseEventSerializer

EventSerializer

org.apache.flume.sink.hbase.SimpleAsyncHbaseEventSerializer

SimpleAsyncHbaseEventSerializer

EventSerializer

org.apache.flume.sink.hbase.RegexHbaseEventSerializer

RegexHbaseEventSerializer

HbaseEventSerializer

Custom implementation of serializer for HBaseSink.
(custom type as FQCN)

Your own HbaseEventSerializer impl.

(custom FQCN)

AsyncHbaseEventSerializer

Custom implementation of serializer for AsyncHbase sink.
(custom type as FQCN)

Your own AsyncHbaseEventSerializer impl.

(custom FQCN)

EventSerializer$Builder

Custom implementation of serializer for all sinks except for HBaseSink and AsyncHBaseSink.
(custom type as FQCN)

Your own EventSerializer$Builder impl.

 

下面介绍下kafka以及kafka和flume的整合

Kafka:

       从这个链接抄了些内容下来http://dongxicheng.org/search-engine/kafka/

  Kafka是Linkedin于2010年12月份开源的消息系统,它主要用于处理活跃的流式数据。活跃的流式数据在web网站应用中非常常见,这些数据包括网站的pv、用户访问了什么内容,搜索了什么内容等。 这些数据通常以日志的形式记录下来,然后每隔一段时间进行一次统计处理。

传统的日志分析系统提供了一种离线处理日志信息的可扩展方案,但若要进行实时处理,通常会有较大延迟。而现有的消(队列)系统能够很好的处理实时或者近似实时的应用,但未处理的数据通常不会写到磁盘上,这对于Hadoop之类(一小时或者一天只处理一部分数据)的离线应用而言,可能存在问题。Kafka正是为了解决以上问题而设计的,它能够很好地离线和在线应用。

2、  设计目标

(1)数据在磁盘上存取代价为O(1)。一般数据在磁盘上是使用BTree存储的,存取代价为O(lgn)。

(2)高吞吐率。即使在普通的节点上每秒钟也能处理成百上千的message。

(3)显式分布式,即所有的producer、broker和consumer都会有多个,均为分布式的。

(4)支持数据并行加载到Hadoop中。

3、  KafKa部署结构

Flume-ng+Kafka+storm的学习笔记Flume-ng+Kafka+storm的学习笔记

 

kafka是显式分布式架构,producer、broker(Kafka)和consumer都可以有多个。Kafka的作用类似于缓存,即活跃的数据和离线处理系统之间的缓存。几个基本概念:

(1)message(消息)是通信的基本单位,每个producer可以向一个topic(主题)发布一些消息。如果consumer订阅了这个主题,那么新发布的消息就会广播给这些consumer。

(2)Kafka是显式分布式的,多个producer、consumer和broker可以运行在一个大的集群上,作为一个逻辑整体对外提供服务。对于consumer,多个consumer可以组成一个group,这个message只能传输给某个group中的某一个consumer.

 

  数据从producer推送到broker,接着consumer在从broker上拉取数据。Zookeeper是一个分布式服务框架 用来解决分布式应用中的数据管理问题等。

 在kafka中 有几个重要概念producer生产者 consumer 消费者 topic 主题。

我们来实际开发一个简单的生产者消费者的例子。

生产者:

   

[java] view plaincopyprint?
 
  1. public classProducerTest {  
  2.        
  3.       public static void main(String[] args) {  
  4.             Properties props = newProperties();  
  5.                 props.setProperty("metadata.broker.list","xx.xx.xx.xx:9092");  
  6.              props.setProperty("serializer.class","kafka.serializer.StringEncoder");  
  7.               props.put("request.required.acks","1");  
  8.               ProducerConfigconfig = new ProducerConfig(props);  
  9.              Producer producer = newProducer(config);  
  10.              KeyedMessage data = newKeyedMessage("kafka","test-kafka");  
  11.               try {  
  12.                 producer.send(data);  
  13.                  } catch (Exception e) {  
  14.                   e.printStackTrace();  
  15.                  }  
  16.              producer.close();   
  17.       }  
  18.     }  

 

 

上面的代码中的xx.xx.xx.xx是kafka server的地址.

上面代码的意思就是向主题 kafka中同步(不配置的话 默认是同步发射)发送了一个信息 是test-kafka.

下面来看看消费者:

      

[java] view plaincopyprint?
 
  1.  public classConsumerTest extends Thread {   
  2.     private finalConsumerConnector consumer;   
  3.     private final String topic;   
  4.    
  5.     public static voidmain(String[] args) {   
  6.         ConsumerTest consumerThread = newConsumerTest("kafka");   
  7.         consumerThread.start();   
  8.     }   
  9.     publicConsumerTest(String topic) {   
  10.         consumer =kafka.consumer.Consumer   
  11.                 .createJavaConsumerConnector(createConsumerConfig());   
  12.         this.topic =topic;   
  13.     }   
  14.    
  15.     private staticConsumerConfig createConsumerConfig() {   
  16.         Properties props = newProperties();   
  17.         props.put("zookeeper.connect","xx.xx.xx.xx:2181");   
  18.         props.put("group.id", "0");   
  19.         props.put("zookeeper.session.timeout.ms","10000");   
  20. //       props.put("zookeeper.sync.time.ms", "200");   
  21. //       props.put("auto.commit.interval.ms", "1000");   
  22.    
  23.         return newConsumerConfig(props);   
  24.    
  25.     }   
  26.    
  27.     public void run(){   
  28.          
  29.         Map topickMap = new HashMap();  
  30.         topickMap.put(topic, 1);  
  31.          Mapbyte[],byte[]>>>  streamMap =consumer.createMessageStreams(topickMap);  
  32.          KafkaStream<byte[],byte[]>stream = streamMap.get(topic).get(0);  
  33.          ConsumerIterator<byte[],byte[]> it =stream.iterator();  
  34.          System.out.println("--------------------------");  
  35.          while(it.hasNext()){  
  36.             //  
  37.              System.out.println("(consumer)--> " +new String(it.next().message()));  
  38.          }  
  39.          
  40.     }   
  41. }  

 

 

上面的代码就是负责接收生产者发送过来的消息 测试的时候先开启消费者 然后再运行生产者即可看到效果。

接下来 我们将flume 和kafka进行整合:

 在flume的source数据源接收到数据后 通过管道 到达sink,我们需要写一个kafkaSink 来将sink从channel接收的数据作为kafka的生产者 将数据 发送给消费者。

 具体代码:

     

[java] view plaincopyprint?
 
  1.  public class KafkaSink extends AbstractSinkimplementsConfigurable {  
  2.        
  3.       private static final Log logger = LogFactory.getLog(KafkaSink.class);  
  4.        
  5.       private Stringtopic;  
  6.       private Producerproducer;  
  7.        
  8.    
  9.       @Override  
  10.       public Status process()throwsEventDeliveryException {  
  11.             
  12.             Channel channel =getChannel();  
  13.          Transaction tx =channel.getTransaction();  
  14.          try {  
  15.                  tx.begin();  
  16.                  Event e = channel.take();  
  17.                  if(e ==null) {  
  18.                          tx.rollback();  
  19.                          return Status.BACKOFF;  
  20.                  }  
  21.                  KeyedMessage data = new KeyedMessage(topic,newString(e.getBody()));  
  22.                  producer.send(data);  
  23.                  logger.info("Message: {}"+new String( e.getBody()));  
  24.                  tx.commit();  
  25.                  return Status.READY;  
  26.          } catch(Exceptione) {  
  27.            logger.error("KafkaSinkException:{}",e);  
  28.                  tx.rollback();  
  29.                  return Status.BACKOFF;  
  30.          } finally {  
  31.                  tx.close();  
  32.          }  
  33.       }  
  34.    
  35.       @Override  
  36.       public void configure(Context context) {  
  37.            topic = "kafka";  
  38.             Properties props = newProperties();  
  39.                 props.setProperty("metadata.broker.list","xx.xx.xx.xx:9092");  
  40.              props.setProperty("serializer.class","kafka.serializer.StringEncoder");  
  41. //           props.setProperty("producer.type", "async");  
  42. //           props.setProperty("batch.num.messages", "1");  
  43.               props.put("request.required.acks","1");  
  44.               ProducerConfigconfig = new ProducerConfig(props);  
  45.               producer = newProducer(config);  
  46.       }  
  47. }  
  48.    

 

 

将此文件打成jar包 传到flume的lib下面 如果你也用的是maven的话 需要用到assembly 将依赖的jar包一起打包进去。

      在flume的配置是如下:

 

[plain] view plaincopyprint?
 
  1.       agent1.sources = source1  
  2. agent1.sinks = sink1  
  3. agent1.channels =channel1  
  4.    
  5. # Describe/configuresource1  
  6. agent1.sources.source1.type= avro  
  7. agent1.sources.source1.bind= localhost  
  8. agent1.sources.source1.port= 44444  
  9. # Describe sink1  
  10. agent1.sinks.sink1.type= xx.xx.xx.KafkaSink(这是类的路径地址)  
  11.    
  12. # Use a channel whichbuffers events in memory  
  13. agent1.channels.channel1.type= memory  
  14. agent1.channels.channel1.capacity= 1000  
  15. agent1.channels.channel1.transactiOnCapactiy= 100  
  16.    
  17. # Bind the source andsink to the channel  
  18. agent1.sources.source1.channels= channel1  
  19. agent1.sinks.sink1.channel= channel1  



 

 

测试的话是avro的方式传送数据的 可以这样测试

bin/flume-ng avro-client--conf conf -H localhost -p 44444 -F/data/flumetmp/a

/data/flumetmp/a 这个为文件的地址.

测试的时候在本地 一定要把上面写的消费者程序打开 以便接收数据测试是否成功。

接下来我们介绍下storm然后将kafka的消费者和storm进行整合:

Storm:

   Storm是一个分布式的实时消息处理系统。

 Storm各个组件之间的关系:

Flume-ng+Kafka+storm的学习笔记Flume-ng+Kafka+storm的学习笔记

 

Storm集群主要由一个主节点和一群工作节点(worker node)组成,通过 Zookeeper进行协调。

 主节点:主节点通常运行一个后台程序 —— Nimbus,用于响应分布在集群中的节点,分配任务和监测故障。

工作节点: Supervisor,负责接受nimbus分配的任务,启动和停止属于自己管理的worker进程。Nimbus和Supervisor之间的协调由zookeeper完成。

 Worker:处理逻辑的进程,在其中运行着多个Task,每个task 是一组spout/blots的组合。

 

Topology:是storm的实时应用程序,从启动开始一直运行,只要有tuple过来 就会触发执行。拓扑:storm的消息流动很像一个拓扑结构。

2. stream是storm的核心概念,一个stream是一个持续的tuple序列,这些tuple被以分布式并行的方式创建和处理。

3. spouts是一个stream的源头,spouts负责从外部系统读取数据,并组装成tuple发射出去,tuple被发射后就开始再topology中传播。

4. bolt是storm中处理 数据的核心,storm中所有的数据处理都是在bolt中完成的

这里就简单介绍一些概念 具体的可以看些详细的教程。

 

我们接下来开始整合storm和kafka。

从上面的介绍得知storm的spout是负责从外部读取数据的 所以我们需要开发一个KafkaSpout 来作为kafka的消费者和storm的数据接收源。可以看看这个https://github.com/HolmesNL/kafka-spout。我在下面只写一个简单的可供测试。

具体代码:

 

[java] view plaincopyprint?
 
  1. public class KafkaSpout implements IRichSpout {  
  2.    
  3.       private static final Log logger = LogFactory.getLog(KafkaSpout.class);  
  4.       /** 
  5.        * 
  6.        */  
  7.       private static final long serialVersionUID = -5569857211173547938L;  
  8.       SpoutOutputCollector collector;  
  9.       private ConsumerConnectorconsumer;  
  10.       private Stringtopic;  
  11.    
  12.       public KafkaSpout(String topic) {  
  13.            this.topic = topic;  
  14.       }  
  15.    
  16.       @Override  
  17.       public void open(Map conf, TopologyContext context,  
  18.                  SpoutOutputCollector collector) {  
  19.            this.collector = collector;  
  20.             
  21.       }  
  22.    
  23.       private static ConsumerConfig createConsumerConfig() {  
  24.            Properties props = newProperties();  
  25.            props.put("zookeeper.connect","xx.xx.xx.xx:2181");  
  26.            props.put("group.id","0");  
  27.            props.put("zookeeper.session.timeout.ms","10000");  
  28.            //props.put("zookeeper.sync.time.ms", "200");  
  29.            //props.put("auto.commit.interval.ms", "1000");  
  30.    
  31.            return new ConsumerConfig(props);  
  32.       }  
  33.    
  34.       @Override  
  35.       public void close() {  
  36.            // TODOAuto-generated method stub  
  37.    
  38.       }  
  39.    
  40.       @Override  
  41.       public void activate() {  
  42.            this.consumer = Consumer.createJavaConsumerConnector(createConsumerConfig());  
  43.            Map topickMap = newHashMap();  
  44.            topickMap.put(topic,new Integer(1));  
  45.            Mapbyte[],byte[]>>>streamMap =consumer.createMessageStreams(topickMap);  
  46.            KafkaStream<byte[],byte[]>stream = streamMap.get(topic).get(0);  
  47.            ConsumerIterator<byte[],byte[]> it =stream.iterator();  
  48.            while (it.hasNext()) {  
  49.                  String value = newString(it.next().message());  
  50.                  System.out.println("(consumer)-->" + value);  
  51.                  collector.emit(new Values(value), value);  
  52.            }  
  53.    
  54.       }  
  55.    
  56.       @Override  
  57.       public void deactivate() {  
  58.            // TODOAuto-generated method stub  
  59.    
  60.       }  
  61.    
  62.       private boolean isComplete;  
  63.    
  64.       @Override  
  65.       public void nextTuple() {  
  66.    
  67.       }  
  68.    
  69.       @Override  
  70.       public void ack(Object msgId) {  
  71.            // TODOAuto-generated method stub  
  72.    
  73.       }  
  74.    
  75.       @Override  
  76.       public void fail(Object msgId) {  
  77.            // TODOAuto-generated method stub  
  78.    
  79.       }  
  80.    
  81.       @Override  
  82.       public void declareOutputFields(OutputFieldsDeclarer declarer) {  
  83.            declarer.declare(new Fields("KafkaSpout"));  
  84.    
  85.       }  
  86.    
  87.       @Override  
  88.       public Map getComponentConfiguration() {  
  89.            // TODOAuto-generated method stub  
  90.            return null;  
  91.       }  
  92.    
  93. }  
  94.    
  95. public class FileBlots implementsIRichBolt{  
  96.        
  97.       OutputCollector collector;  
  98.        
  99.       public void prepare(Map stormConf, TopologyContext context,  
  100.                  OutputCollector collector) {  
  101.            this.collector = collector;  
  102.             
  103.       }  
  104.    
  105.       public void execute(Tuple input) {  
  106.            String line = input.getString(0);  
  107.            for(String str : line.split("\\s+")){  
  108.            List a = newArrayList();  
  109.            a.add(input);   
  110.            this.collector.emit(a,newValues(str));  
  111.            }  
  112.            this.collector.ack(input);  
  113.       }  
  114.    
  115.       public void cleanup() {  
  116.             
  117.       }  
  118.    
  119.       public void declareOutputFields(OutputFieldsDeclarer declarer) {  
  120.            declarer.declare(new Fields("words"));  
  121.             
  122.       }  
  123.    
  124.       public Map getComponentConfiguration() {  
  125.            // TODOAuto-generated method stub  
  126.            return null;  
  127.       }  
  128.    
  129. }  
  130. public class WordsCounterBlots implementsIRichBolt{  
  131.        
  132.       OutputCollector collector;  
  133.       Map counter;  
  134.        
  135.       public void prepare(Map stormConf, TopologyContext context,  
  136.                  OutputCollector collector) {  
  137.            this.collector = collector;  
  138.            this.counter =new HashMap();  
  139.             
  140.       }  
  141.    
  142.       public void execute(Tuple input) {  
  143.            String word = input.getString(0);  
  144.            Integer integer = this.counter.get(word);  
  145.            if(integer !=null){  
  146.                  integer +=1;  
  147.                  this.counter.put(word, integer);  
  148.            }else{  
  149.                  this.counter.put(word, 1);  
  150.            }  
  151.            System.out.println("execute");  
  152.            Jedis jedis = JedisUtils.getJedis();  
  153.            jedis.incrBy(word, 1);  
  154.            System.out.println("=============================================");  
  155.            this.collector.ack(input);  
  156.       }  
  157.    
  158.       public void cleanup() {  
  159.            for(Entry entry :this.counter.entrySet()){  
  160.                       System.out.println("------:"+entry.getKey()+"=="+entry.getValue());  
  161.            }  
  162.             
  163.       }  
  164.    
  165.       public void declareOutputFields(OutputFieldsDeclarer declarer) {  
  166.             
  167.             
  168.       }  
  169.    
  170.       public Map getComponentConfiguration() {  
  171.            // TODOAuto-generated method stub  
  172.            return null;  
  173.       }  
  174.    
  175. }  



 

Topology测试:

 

[java] view plaincopyprint?
 
  1. public class KafkaTopology {  
  2.    
  3.       public static void main(String[] args) {  
  4.            try {  
  5.                  JedisUtils.initialPool("xx.xx.xx.xx", 6379);  
  6.            } catch (Exception e) {  
  7.                  e.printStackTrace();  
  8.            }  
  9.             
  10.            TopologyBuilder builder = newTopologyBuilder();           builder.setSpout("kafka",new KafkaSpout("kafka"));  
  11.            builder.setBolt("file-blots",new FileBlots()).shuffleGrouping("kafka");  
  12.            builder.setBolt("words-counter",new WordsCounterBlots(),2).fieldsGrouping("file-blots",new Fields("words"));  
  13.            Config config = new Config();  
  14.            config.setDebug(true);  
  15.                  LocalCluster local = newLocalCluster();  
  16.                  local.submitTopology("counter", config, builder.createTopology());  
  17.       }  
  18. }  



 

 

至此flume + kafka+storm的整合就写完了。注意 这个是 初始学习阶段做的测试 不可正式用于线上环境,在写本文之时 已经离测试过去了一段时间 所以可能会有些错误 请见谅。


推荐阅读
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
author-avatar
yhonmen
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有