-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.json
1 lines (1 loc) · 31.3 KB
/
content.json
1
{"meta":{"title":"AUTISMTHROW'S BLOG","subtitle":null,"description":null,"author":"AutismThrow","url":"http://yoursite.com","root":"/"},"pages":[{"title":"archive","date":"2019-05-14T03:04:47.000Z","updated":"2019-05-14T03:04:47.228Z","comments":true,"path":"archive/index.html","permalink":"http://yoursite.com/archive/index.html","excerpt":"","text":""},{"title":"about","date":"2019-05-14T02:26:43.000Z","updated":"2019-05-14T02:28:41.406Z","comments":true,"path":"about/index.html","permalink":"http://yoursite.com/about/index.html","excerpt":"","text":""},{"title":"categories","date":"2019-05-14T03:14:36.000Z","updated":"2019-06-23T15:44:49.770Z","comments":false,"path":"categories/index.html","permalink":"http://yoursite.com/categories/index.html","excerpt":"","text":""},{"title":"friends","date":"2019-05-14T03:10:21.000Z","updated":"2019-05-14T03:10:21.820Z","comments":true,"path":"friends/index.html","permalink":"http://yoursite.com/friends/index.html","excerpt":"","text":""},{"title":"projects","date":"2019-05-14T04:41:25.000Z","updated":"2019-05-14T04:41:25.946Z","comments":true,"path":"projects/index.html","permalink":"http://yoursite.com/projects/index.html","excerpt":"","text":""},{"title":"tags","date":"2019-05-14T03:14:14.000Z","updated":"2019-06-23T15:44:07.170Z","comments":false,"path":"tags/index.html","permalink":"http://yoursite.com/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"eureka client端搭建过程中无法启动","slug":"关于搭建eureka client过程中无法启动","date":"2019-06-23T15:20:46.888Z","updated":"2019-06-23T15:51:08.628Z","comments":true,"path":"2019/06/23/关于搭建eureka client过程中无法启动/","link":"","permalink":"http://yoursite.com/2019/06/23/关于搭建eureka client过程中无法启动/","excerpt":"eureka client端搭建过程中无法启动今天在尝试搭建eureka服务注册和服务发现过程中,server端搭建启动完成之后,client端一直无法启动 启动信息如下:","text":"eureka client端搭建过程中无法启动今天在尝试搭建eureka服务注册和服务发现过程中,server端搭建启动完成之后,client端一直无法启动 启动信息如下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051522019-06-23 23:24:37.266 INFO 8740 --- [ main] c.s.c.c.e.EurekaClientApplication : No active profile set, falling back to default profiles: default2019-06-23 23:24:37.281 INFO 8740 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@418c5a9c: startup date [Sun Jun 23 23:24:37 CST 2019]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@4cc451f22019-06-23 23:24:37.707 INFO 8740 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=2ccb9e2e-fe88-338d-849d-25bf57fe2dd62019-06-23 23:24:37.721 INFO 8740 --- [ main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring2019-06-23 23:24:37.772 INFO 8740 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$c6ccbb49] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)2019-06-23 23:24:37.817 WARN 8740 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.2019-06-23 23:24:37.817 INFO 8740 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.2019-06-23 23:24:37.821 WARN 8740 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.2019-06-23 23:24:37.821 INFO 8740 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.2019-06-23 23:24:38.819 INFO 8740 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup2019-06-23 23:24:38.829 INFO 8740 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'refreshScope' has been autodetected for JMX exposure2019-06-23 23:24:38.829 INFO 8740 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'configurationPropertiesRebinder' has been autodetected for JMX exposure2019-06-23 23:24:38.830 INFO 8740 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'environmentManager' has been autodetected for JMX exposure2019-06-23 23:24:38.833 INFO 8740 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'environmentManager': registering with JMX server as MBean [org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager]2019-06-23 23:24:38.845 INFO 8740 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'refreshScope': registering with JMX server as MBean [org.springframework.cloud.context.scope.refresh:name=refreshScope,type=RefreshScope]2019-06-23 23:24:38.861 INFO 8740 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'configurationPropertiesRebinder': registering with JMX server as MBean [org.springframework.cloud.context.properties:name=configurationPropertiesRebinder,context=418c5a9c,type=ConfigurationPropertiesRebinder]2019-06-23 23:24:38.870 INFO 8740 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 02019-06-23 23:24:38.878 INFO 8740 --- [ main] o.s.c.n.eureka.InstanceInfoFactory : Setting initial instance status as: STARTING2019-06-23 23:24:38.919 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Initializing Eureka in region us-east-12019-06-23 23:24:39.379 INFO 8740 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using JSON encoding codec LegacyJacksonJson2019-06-23 23:24:39.380 INFO 8740 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using JSON decoding codec LegacyJacksonJson2019-06-23 23:24:39.536 INFO 8740 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using XML encoding codec XStreamXml2019-06-23 23:24:39.536 INFO 8740 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using XML decoding codec XStreamXml2019-06-23 23:24:40.030 INFO 8740 --- [ main] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration2019-06-23 23:24:40.280 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Disable delta property : false2019-06-23 23:24:40.281 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Single vip registry refresh property : null2019-06-23 23:24:40.281 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Force full registry fetch : false2019-06-23 23:24:40.281 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Application is null : false2019-06-23 23:24:40.281 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Registered Applications size is zero : true2019-06-23 23:24:40.281 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Application version is -1: true2019-06-23 23:24:40.281 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Getting all instance registry info from the eureka server2019-06-23 23:24:40.458 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : The response status is 2002019-06-23 23:24:40.461 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Starting heartbeat executor: renew interval is: 302019-06-23 23:24:40.463 INFO 8740 --- [ main] c.n.discovery.InstanceInfoReplicator : InstanceInfoReplicator onDemand update allowed rate per min is 42019-06-23 23:24:40.467 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Discovery Client initialized at timestamp 1561303480465 with initial instances count: 22019-06-23 23:24:40.470 INFO 8740 --- [ main] o.s.c.n.e.s.EurekaServiceRegistry : Registering application eureka-client with eureka with status UP2019-06-23 23:24:40.471 INFO 8740 --- [ main] com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [timestamp=1561303480471, current=UP, previous=STARTING]2019-06-23 23:24:40.472 INFO 8740 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_EUREKA-CLIENT/DESKTOP-MO8NTNL:eureka-client:8080: registering service...2019-06-23 23:24:40.497 INFO 8740 --- [ main] c.s.c.c.e.EurekaClientApplication : Started EurekaClientApplication in 5.861 seconds (JVM running for 7.639)2019-06-23 23:24:40.508 INFO 8740 --- [ Thread-17] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@418c5a9c: startup date [Sun Jun 23 23:24:37 CST 2019]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@4cc451f22019-06-23 23:24:40.510 INFO 8740 --- [ Thread-17] o.s.c.n.e.s.EurekaServiceRegistry : Unregistering application eureka-client with eureka with status DOWN2019-06-23 23:24:40.511 WARN 8740 --- [ Thread-17] com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [timestamp=1561303480511, current=DOWN, previous=UP]2019-06-23 23:24:40.521 INFO 8740 --- [ Thread-17] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 02019-06-23 23:24:40.524 INFO 8740 --- [ Thread-17] com.netflix.discovery.DiscoveryClient : Shutting down DiscoveryClient ...2019-06-23 23:24:40.543 INFO 8740 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_EUREKA-CLIENT/DESKTOP-MO8NTNL:eureka-client:8080 - registration status: 2042019-06-23 23:24:40.543 INFO 8740 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_EUREKA-CLIENT/DESKTOP-MO8NTNL:eureka-client:8080: registering service...2019-06-23 23:24:40.558 INFO 8740 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_EUREKA-CLIENT/DESKTOP-MO8NTNL:eureka-client:8080 - registration status: 2042019-06-23 23:24:40.559 INFO 8740 --- [ Thread-17] com.netflix.discovery.DiscoveryClient : Unregistering ...2019-06-23 23:24:40.565 INFO 8740 --- [ Thread-17] com.netflix.discovery.DiscoveryClient : DiscoveryClient_EUREKA-CLIENT/DESKTOP-MO8NTNL:eureka-client:8080 - deregister status: 2002019-06-23 23:24:40.577 INFO 8740 --- [ Thread-17] com.netflix.discovery.DiscoveryClient : Completed shut down of DiscoveryClient2019-06-23 23:24:40.582 INFO 8740 --- [ Thread-17] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown2019-06-23 23:24:40.585 INFO 8740 --- [ Thread-17] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans 经过反复检查发现,是pom文件中忘了添加 spring-boot-starter-web 依赖,导致启动失败,添加依赖之后正常启动","categories":[],"tags":[{"name":"bugs","slug":"bugs","permalink":"http://yoursite.com/tags/bugs/"},{"name":"eureka","slug":"eureka","permalink":"http://yoursite.com/tags/eureka/"},{"name":"error","slug":"error","permalink":"http://yoursite.com/tags/error/"}]},{"title":"JVM原理","slug":"JVM原理","date":"2019-05-31T05:22:55.041Z","updated":"2019-05-31T05:57:50.365Z","comments":true,"path":"2019/05/31/JVM原理/","link":"","permalink":"http://yoursite.com/2019/05/31/JVM原理/","excerpt":"一、JVM运行时数据区","text":"一、JVM运行时数据区 1.java 虚拟机栈:虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接,方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 2.java 堆:Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 3.方法区:方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据 4.运行时常量池:运行时常量池(Runtime Constant Pool)是方法区的一部分。用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。 5.程序计数器:程序计数器(program counter register)是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器。 二、JVM垃圾回收算法1.标记-清除:最基础的收集算法,算法分为”标记“和”清除“两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。缺点有: 1.效率问题,标记和清除过程的效率都不高。 2.空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多 2.复制算法:为了解决效率问题,“复制”算法出现了。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。IBM的专门研究表明,新生代中的对象98%是朝生夕死的。所以将内存分为一块比较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中的一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次性的拷贝到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor的空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8:1:1. 3.标记-整理:标记过程与”标记-清除“算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。 4.分代收集:这种算法根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用”标记-清理“或”标记-整理“算法来进行回收。 三、JVM垃圾收集器垃圾收集器组合 上图中展示了7种不同的垃圾收集器和它们所处的位置 新生代收集器:Serial、ParNew、Parallel Scavenge 老年代收集器:Serial Old、Parallel Old、CMS 整堆:G1 两个收集器之间有连线表明他们可以搭配使用 1.Serial 收集器Serial收集器是最基本、历史最悠久的单线程收集器。但他的”单线程“的意义并不仅仅是说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是他在进行垃圾收集时,必须暂停其他所有的工作线程(Sun将这件事情称之为”Stop The World“)直到它收集结束。 2.ParNew 收集器ParNew收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为包括Serial 收集器的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial 收集器完全一样,实际上也两种收集器也共用了相当多的代码。 它作为老年代的收集器,却无法与JDK中已经存在的新生代收集器Paralle Scavenge配合工作,所以在JDK1.5中使用CMS来收集老年代的时候,新生代只能选择ParNew或Serial收集器中的一个。 3.Parallel Scavenge 收集器Parallel Scavenge 收集器也是一个新生代收集器,他也是使用复制算法的收集器,又是并行的多线程收集器。 Parallel Scavenge 收集器的特点使他的关注点与其他收集器不同,CMS等收集器关注点尽可能地缩短垃圾收集时用户现成的停顿时间,而Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量(Throughput)。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,及吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),虚拟机总共运行了100分钟,其中垃圾收集花掉1分支,那吞吐量就是99%。 4.Serial Old 收集器Serial Old时Serial收集器的老年代版本,它同样是一个单线程收集器,使用”标记-整理“算法。这个收集器的主要意义也是被Client模式下的虚拟机使用。如果在Server模式下,它主要还有两大用途:一个实在JDK1.5及之前的版本中与Parallel Scavenge收集器搭配使用,另外一个就是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure的时候使用。 5.Parallel Old 收集器Parallel Old 是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理“算法。这个收集器是在JDK1.6中才开始提供的,在此之前,新生代的Parallel Scavenge收集器一直处于比较尴尬的状态。原因是,如果新生代选择了Parallel Scavenge收集器,老年代除了Serial Old(PS markSweep)收集器外别无选择(Parallel Scavenge收集器无法与CMS收集器配合工作)。由于单线程的老年代Serial Old收集器在服务端应用性能上的”拖累”,即便使用了Parallel Scavenge收集器也未必能在整体引用上获得吞吐量最大化的效果,又因为老年代收集中无法充分利用服务器多CPU的处理能力,在老年代很大而且硬件比较高级的环境中,这种组合的吞吐量甚至还不一定有ParNew加CMS的组合“给力”。 直到Parallel Old收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的应用组合,在注重吞吐量及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器。 6.CMS 收集器CMS(Concurrent Mark Sweep)收集器是以重以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用都集中在互联网站或B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间对端,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。 从名字(包含“Mark Sweep”)上就可以看出CMS收集器是基于“标记-清除”算法实现的,他的运作过程相对于前面几种收集器来说要更复杂一些,整个过程分为4个步骤,包括: 初始标记(CMS initial mark) 并发标记(CMS concurrent mark) 重新标记(CMS remark) 并发清除(CMS concurrnet sweep) 其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。 CMS是一款优秀的收集器,他的最主要有点在名字上已经体现出来了:并发收集、低停顿。但是还远达不到完美的成都,他有以下三个显著的缺点: CMS收集器对CPU资源非常敏感 CMS收集器无法处理浮动垃圾(CMS并发清理阶段会产生一定的垃圾,这部分垃圾只能在下次GC的时候处理,称为浮动垃圾) CMS是基于“标记-清除”算法实现的,这意味收集结束时会产生大量空间碎片。空间碎片过多会给大对象分配带来麻烦。CMS收集器提供了一个-XX:+UseCMSCompactAtFullCollection开关参数用于Full GC之后整理碎片,但空间碎片整理是需要停顿的。 7.G1G1收集器将java堆均分成大小相同的区域(region,1M-32M,最多2000个,最大支持堆内存64G)。一个或多个不连续的区域共同组成eden、survivor或old区,但大小不再固定,这为内存应用提供了极大地弹性。G1垃圾收集过程与CMS类似。G1在堆内存中并发地对所有对象进行标记,决定对象的可达性。经过全局标记,G1了解哪些区域几乎是空的,然后优先收集这些区域,这就是GarbageFirst的命名由来。G1将垃圾收集和内存整理活动专注于那些几乎全是垃圾的区域,并建立停顿预测模型来决定每次GC时回收哪些区域,以满足用户设定的停顿时间。 G1收集器是基于“标记-整理”算法实现的收集器,也就是它不会产生空间碎片,这对长时间运行的应用系统来说非常重要。 它可以非常精确的控制停顿,既能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。","categories":[],"tags":[{"name":"jvm","slug":"jvm","permalink":"http://yoursite.com/tags/jvm/"}]},{"title":"kafka原理","slug":"kafka原理","date":"2019-05-30T14:17:50.465Z","updated":"2019-05-31T04:40:13.178Z","comments":true,"path":"2019/05/30/kafka原理/","link":"","permalink":"http://yoursite.com/2019/05/30/kafka原理/","excerpt":"kafka原理","text":"kafka原理 一、为什么需要消息系统 解耦: 允许你独立的拓展或修改两边的处理过程,只要确保他们遵守同样的接口约束 冗余: 消息队列把数据进行持久啊知道他们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的“插入-获取-删除”范式中,在把一个消息从消息队列中删除之前,需要捏处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。 扩展性: 因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可 灵活性&峰值处理能力: 在访问量剧增的情况下,应用仍然需要继续发挥作用,当时这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。 可恢复性: 系统的一部分组建失效时,不会影响到整个系统。效力对了降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。 顺序保证: 在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且保证数据会按照特定的顺序来处理。(kafka保证一个Partition内的消息的有序性) 缓冲: 有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。 异步通信: 很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后子啊需要的时候再去处理它们。 二、相关概念 producer: 消息生产者,发布消息到Kafka集群的终端或服务。 broker: kafka集群中包含的服务器。 topic: 每条发布到kafka集群的消息属于的类别,即Kafka是面向topic的。 partition: partition是物理上的概念,每个topic包含一个或多个partition。Kafka分配的单位是partition。 consumer: 从Kafka集群中消费消息的终端或服务 Consumer group: high-level consumer API中,每个consumer都属于一个consumer group,每条消息只能被consumer group中的一个consumer消费,但可以被多个consumer group消费。 replica: partition的副本,保障partition的高可用。 leader: replica中的一个角色,,producer和consumer只跟leader交互。 follower: replica中的一个角色,从leader中复制数据。 controller: Kafka集群中的一个服务器,用来进行leader election以及各种failover。 zokeeper: Kafka通过zookeeper来存储集群的meta信息。 三、producer发布消息3.1 写入方式producer采用push模式将消息发布到broker,每条消息都被append到partition中,属于顺序写入磁盘(顺序写磁盘效率比随即写内存要高,保障kafka吞吐率)。 3.2 消息路由producer发送消息到broker时,会根据分区算法选择将其存储到哪一个partition。其路由机制为: 1231. 指定了partition,则直接使用;2. 未指定partition但直到那个key,通过对key的value进行hash选出一个partition3. partition和key都为指定,使用轮询选出一个partition。 java客服端分区源码 12345678910111213141516171819202122232425262728293031323334353637383940414243444546//创建消息实例public ProducerRecord(String topic, Integer partition, Long timestamp, K key, V value) { if (topic == null) throw new IllegalArgumentException(\"Topic cannot be null\"); if (timestamp != null && timestamp < 0) throw new IllegalArgumentException(\"Invalid timestamp \" + timestamp); this.topic = topic; this.partition = partition; this.key = key; this.value = value; this.timestamp = timestamp;}//计算 patition,如果指定了 patition 则直接使用,否则使用 key 计算private int partition(ProducerRecord<K, V> record, byte[] serializedKey , byte[] serializedValue, Cluster cluster) { Integer partition = record.partition(); if (partition != null) { List<PartitionInfo> partitions = cluster.partitionsForTopic(record.topic()); int lastPartition = partitions.size() - 1; if (partition < 0 || partition > lastPartition) { throw new IllegalArgumentException(String.format(\"Invalid partition given with record: %d is not in the range [0...%d].\", partition, lastPartition)); } return partition; } return this.partitioner.partition(record.topic(), record.key(), serializedKey, record.value(), serializedValue, cluster);}// 使用 key 选取 patitionpublic int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) { List<PartitionInfo> partitions = cluster.partitionsForTopic(topic); int numPartitions = partitions.size(); if (keyBytes == null) { int nextValue = counter.getAndIncrement(); List<PartitionInfo> availablePartitions = cluster.availablePartitionsForTopic(topic); if (availablePartitions.size() > 0) { int part = DefaultPartitioner.toPositive(nextValue) % availablePartitions.size(); return availablePartitions.get(part).partition(); } else { return DefaultPartitioner.toPositive(nextValue) % numPartitions; } } else { //对 keyBytes 进行 hash 选出一个 patition return DefaultPartitioner.toPositive(Utils.murmur2(keyBytes)) % numPartitions; }} 3.3 写入流程 流程总结: 123451. producer 先从 zookeeper 的 "/brokers/.../state" 节点找到该 partition 的 leader2. producer 将消息发送给该 leader3. leader 将消息写入本地 log4. followers 从 leader pull 消息,写入本地 log 后 leader 发送 ACK5. leader 收到所有 ISR 中的 replica 的 ACK 后,增加 HW(high watermark,最后 commit 的 offset) 并向 producer 发送 ACK 3.4 发送消息发送消息主要有三种方式: fire-and-forget(发送并忘记): 不关注消息是否成功到达,大部分情况下没消息会成功送达至broker。但是还是会存在消息丢失的情况 1234567ProducerRecord<String, String> record = new ProducerRecord<String, String>(\"CustomerCountry\", \"Precision Products\", \"France\");try { producer.send(record);} catch (Exception e) { e.printStackTrace();} Synchronous send(同步发送): 调用send方法后返回一个Future对象,在调用get()方法会等待直到结果返回,根据返回的结果可以判断是都发送成功 1234567ProducerRecord<String, String> record = new ProducerRecord<String, String>(\"CustomerCountry\", \"Precision Products\", \"France\");try { producer.send(record).get();} catch (Exception e) { e.printStackTrace();} Aysnchronous send(异步发送): 我们调用send()方法,并指定一个回调函数,服务器在返回响应时调用该函数。 12345678910class DemoProducerCallback implements Callback { @Override public void onCompletion(RecordMetadata recordMetadata, Exception e) { if (e != null) { e.printStackTrace(); } }} producer.send(record, new DemoProducerCallback()); 要使用callback函数,先要实现Callback接口,该接口只有一个onCompletion方法。如果发送异常,onCompletion的参数Exception e会为非空 四、broker 保存消息4.1 存储方式物理上把topic分成一个或多个partition(对应server.properties中的num.partition=3 配置),每个partiton物理上对应一个文件下(该文件夹存储该partition的所有消息和索引文件)。 4.2 存储策略无论消息是否被消费,kafka都会保留所有消息。有两种策略可以删除旧数据: 121. 基于时间:log.retention.hours=1682. 基于大小:log.retention.bytes=1073741824 kafka读取特定消息的时间复杂度为O(1),即与文件大小无关,所以这里删除过期文件与提高Kafka性能无关。 4.3 topic 创建与删除4.3.1 topic创建创建图例: 流程说明: 123451. controller 在 ZooKeeper 的 /brokers/topics 节点上注册 watcher,当 topic 被创建,则 controller 会通过 watch 得到该 topic 的 partition/replica 分配。2. controller从 /brokers/ids 读取当前所有可用的 broker 列表,对于 set_p 中的每一个 partition: 2.1 从分配给该 partition 的所有 replica(称为AR)中任选一个可用的 broker 作为新的 leader,并将AR设置为新的 ISR 2.2 将新的 leader 和 ISR 写入 /brokers/topics/[topic]/partitions/[partition]/state3. controller 通过 RPC 向相关的 broker 发送 LeaderAndISRRequest。 4.3.2 topic删除删除图例: 流程说明: 121. controller 在 zooKeeper 的 /brokers/topics 节点上注册 watcher,当 topic 被删除,则 controller 会通过 watch 得到该 topic 的 partition/replica 分配。2. 若 delete.topic.enable=false,结束;否则 controller 注册在 /admin/delete_topics 上的 watch 被 fire,controller 通过回调向对应的 broker 发送 StopReplicaRequest。","categories":[],"tags":[{"name":"kafka","slug":"kafka","permalink":"http://yoursite.com/tags/kafka/"}]},{"title":"Hello World","slug":"hello-world","date":"2019-05-13T10:16:34.899Z","updated":"2019-05-31T03:36:54.740Z","comments":true,"path":"2019/05/13/hello-world/","link":"","permalink":"http://yoursite.com/2019/05/13/hello-world/","excerpt":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.","text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new \"My New Post\" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment","categories":[],"tags":[]}]}