-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path2017060101.html
More file actions
1 lines (1 loc) · 46.7 KB
/
Copy path2017060101.html
File metadata and controls
1 lines (1 loc) · 46.7 KB
1
<!DOCTYPE html><html class="theme-next mist use-motion" lang="zh-Hans"><head><meta name="generator" content="Hexo 3.9.0"><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><meta name="theme-color" content="#222"><script src="/lib/pace/pace.min.js?v=1.0.2"></script><link href="/lib/pace/pace-theme-minimal.min.css?v=1.0.2" rel="stylesheet"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"><link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css"><link href="/css/main.css?v=5.1.3" rel="stylesheet" type="text/css"><link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-240x240-playpi.png?v=5.1.3"><link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-playpi.png?v=5.1.3"><link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-playpi.png?v=5.1.3"><link rel="mask-icon" href="/images/logo-playpi.svg?v=5.1.3" color="#222"><meta name="keywords" content="Kafka,OffsetOutOfRangeException,Spark,SparkStreaming,Zookeeper"><link rel="alternate" href="/atom.xml" title="虾丸派" type="application/atom+xml"><meta name="description" content="在使用 Kafka 的过程中,某一天项目中莫名其妙出现了一个异常信息:kafka.common.OffsetOutOfRangeException项目的业务场景是使用 SparkStreaming 消费 Kafka 数据,进一步进行 ETL 处理 ,没有复杂的逻辑。平时一切正常运行,某一天我想在测试环境测试一下更新的逻辑代码,就出现了这个问题,导致整个进程任务失败。本文记录分析问题、解决问题的过程"><meta name="keywords" content="Kafka,OffsetOutOfRangeException,Spark,SparkStreaming,Zookeeper"><meta property="og:type" content="article"><meta property="og:title" content="记录一个 Kafka 错误:OffsetOutOfRangeException"><meta property="og:url" content="https://www.playpi.org/2017060101.html"><meta property="og:site_name" content="虾丸派"><meta property="og:description" content="在使用 Kafka 的过程中,某一天项目中莫名其妙出现了一个异常信息:kafka.common.OffsetOutOfRangeException项目的业务场景是使用 SparkStreaming 消费 Kafka 数据,进一步进行 ETL 处理 ,没有复杂的逻辑。平时一切正常运行,某一天我想在测试环境测试一下更新的逻辑代码,就出现了这个问题,导致整个进程任务失败。本文记录分析问题、解决问题的过程"><meta property="og:locale" content="zh-Hans"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728180827.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728180912.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728180936.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181003.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181036.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181046.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181432.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181441.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190729204654.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181607.png"><meta property="og:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728190054.png"><meta property="og:updated_time" content="2019-07-27T18:21:19.000Z"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="记录一个 Kafka 错误:OffsetOutOfRangeException"><meta name="twitter:description" content="在使用 Kafka 的过程中,某一天项目中莫名其妙出现了一个异常信息:kafka.common.OffsetOutOfRangeException项目的业务场景是使用 SparkStreaming 消费 Kafka 数据,进一步进行 ETL 处理 ,没有复杂的逻辑。平时一切正常运行,某一天我想在测试环境测试一下更新的逻辑代码,就出现了这个问题,导致整个进程任务失败。本文记录分析问题、解决问题的过程"><meta name="twitter:image" content="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728180827.png"><script type="text/javascript" id="hexo.configurations">var NexT=window.NexT||{},CONFIG={root:"/",scheme:"Mist",version:"5.1.3",sidebar:{position:"left",display:"hide",offset:12,b2t:!1,scrollpercent:!0,onmobile:!1},fancybox:!0,tabs:!0,motion:{enable:!0,async:!1,transition:{post_block:"fadeIn",post_header:"slideDownIn",post_body:"slideDownIn",coll_header:"slideLeftIn",sidebar:"slideUpIn"}},duoshuo:{userId:"0",author:"博主"},algolia:{applicationID:"",apiKey:"",indexName:"",hits:{per_page:10},labels:{input_placeholder:"Search for Posts",hits_empty:"We didn't find any results for the search: ${query}",hits_stats:"${hits} results found in ${time} ms"}}}</script><link rel="canonical" href="https://www.playpi.org/2017060101.html"><title>记录一个 Kafka 错误:OffsetOutOfRangeException | 虾丸派</title></head><body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans"><div class="container sidebar-position-left page-post-detail"><div class="headband"></div><header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="header-inner"><div class="site-brand-wrapper"><div class="site-meta"><div class="custom-logo-site-title"><a href="/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">虾丸派</span> <span class="logo-line-after"><i></i></span></a></div><h1 class="site-subtitle" itemprop="description">烂笔头</h1></div><div class="site-nav-toggle"><button><span class="btn-bar"></span> <span class="btn-bar"></span> <span class="btn-bar"></span></button></div></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i><br>首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i><br>标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i><br>分类</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i><br>归档</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i><br>关于</a></li><li class="menu-item menu-item-books"><a href="/books/" rel="section"><i class="menu-item-icon fa fa-fw fa-book"></i><br>书籍</a></li><li class="menu-item menu-item-guide"><a href="/guide/" rel="section"><i class="menu-item-icon fa fa-fw fa-location-arrow"></i><br>指南</a></li><li class="menu-item menu-item-search"><a href="javascript:;" class="popup-trigger"><i class="menu-item-icon fa fa-search fa-fw"></i><br>搜索</a></li></ul><div class="site-search"><div class="popup search-popup local-search-popup"><div class="local-search-header clearfix"><span class="search-icon"><i class="fa fa-search"></i> </span><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span><div class="local-search-input-wrapper"><input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input"></div></div><div id="local-search-result"></div></div></div></nav></div></header><main id="main" class="main"><div class="main-inner"><div class="content-wrap"><div id="content" class="content"><div id="posts" class="posts-expand"><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="https://www.playpi.org/2017060101.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="虾丸派"><meta itemprop="description" content="记录知识 | 分享技术"><meta itemprop="image" content="/images/favicon-1536x1536-playpi.png"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="虾丸派"></span><header class="post-header"><h2 class="post-title" itemprop="name headline">记录一个 Kafka 错误:OffsetOutOfRangeException</h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-06-01T02:21:19+08:00">2017-06-01 </time></span><span class="post-category"><span class="post-meta-divider">|</span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/big-data-technical-knowledge/" itemprop="url" rel="index"><span itemprop="name">大数据技术知识</span> </a></span></span><span id="busuanzi_container_page_pv" style="display:none"><span class="post-meta-divider">|</span> 阅读次数 <span id="busuanzi_value_page_pv"></span></span><div class="post-wordcount"><span class="post-meta-item-text">字数统计</span> <span title="字数统计">3,219字 </span><span class="post-meta-divider">|</span> <span class="post-meta-item-text">阅读时长 ≈</span> <span title="阅读时长">13分钟</span></div></div></header><div class="post-body" itemprop="articleBody"><p>在使用 <code>Kafka</code> 的过程中,某一天项目中莫名其妙出现了一个异常信息:<br><code>kafka.common.OffsetOutOfRangeException</code><br>项目的业务场景是使用 <code>SparkStreaming</code> 消费 <code>Kafka</code> 数据,进一步进行 <strong>ETL 处理 </strong>,没有复杂的逻辑。平时一切正常运行,某一天我想在测试环境测试一下更新的逻辑代码,就出现了这个问题,导致整个进程任务失败。本文记录分析问题、解决问题的过程,运行环境基于 <code>Kafka v0.8.2.1</code>,<code>Spark v1.6.2</code>、<code>spark-streaming v2.10</code>,其它版本的内容会与这个版本存在部分不一致的地方,我会特殊说明。</p><a id="more"></a><h1 id="问题出现"><a href="# 问题出现" class="headerlink" title="问题出现"></a>问题出现</h1><p>某一天我修改了项目的代码,在本地连接测试环境,开始测试,出现以下异常信息:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">Caused by: kafka.common.OffsetOutOfRangeException</span><br><span class="line"> at sun.reflect.NativeConstructorAccessorImpl.newInstance0 (Native Method)</span><br><span class="line"> at sun.reflect.NativeConstructorAccessorImpl.newInstance (NativeConstructorAccessorImpl.java:62)</span><br><span class="line"> at sun.reflect.DelegatingConstructorAccessorImpl.newInstance (DelegatingConstructorAccessorImpl.java:45)</span><br><span class="line"> at java.lang.reflect.Constructor.newInstance (Constructor.java:423)</span><br><span class="line"> at java.lang.Class.newInstance (Class.java:442)</span><br><span class="line"> at kafka.common.ErrorMapping$.exceptionFor (ErrorMapping.scala:86)</span><br><span class="line"> at org.apache.spark.streaming.kafka.KafkaRDD$KafkaRDDIterator.handleFetchErr (KafkaRDD.scala:184)</span><br><span class="line"> at org.apache.spark.streaming.kafka.KafkaRDD$KafkaRDDIterator.fetchBatch (KafkaRDD.scala:193)</span><br><span class="line"> at org.apache.spark.streaming.kafka.KafkaRDD$KafkaRDDIterator.getNext (KafkaRDD.scala:208)</span><br><span class="line"> at org.apache.spark.util.NextIterator.hasNext (NextIterator.scala:73)</span><br><span class="line"> at scala.collection.convert.Wrappers$IteratorWrapper.hasNext (Wrappers.scala:29)</span><br><span class="line"> at com.datastory.banyan.v3.consumer.BaseRhinoDirectConsumerV3$1.call (BaseRhinoDirectConsumerV3.java:81)</span><br><span class="line"> at com.datastory.banyan.v3.consumer.BaseRhinoDirectConsumerV3$1.call (BaseRhinoDirectConsumerV3.java:72)</span><br><span class="line"> at org.apache.spark.api.java.JavaRDDLike$$anonfun$foreachPartition$1.apply (JavaRDDLike.scala:225)</span><br><span class="line"> at org.apache.spark.api.java.JavaRDDLike$$anonfun$foreachPartition$1.apply (JavaRDDLike.scala:225)</span><br><span class="line"> at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply (RDD.scala:920)</span><br><span class="line"> at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply (RDD.scala:920)</span><br><span class="line"> at org.apache.spark.SparkContext$$anonfun$runJob$5.apply (SparkContext.scala:1858)</span><br><span class="line"> at org.apache.spark.SparkContext$$anonfun$runJob$5.apply (SparkContext.scala:1858)</span><br><span class="line"> at org.apache.spark.scheduler.ResultTask.runTask (ResultTask.scala:66)</span><br><span class="line"> at org.apache.spark.scheduler.Task.run (Task.scala:89)</span><br><span class="line"> at org.apache.spark.executor.Executor$TaskRunner.run (Executor.scala:227)</span><br><span class="line"> ... 3 more</span><br></pre></td></tr></table></figure><p>项目中的异常信息本来有很多行,但是关键的就是这部分内容,关键异常信息截图如下。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728180827.png" alt="异常信息截图" title="异常信息截图"></p><p>重点就看 <code>Caused by: kafka.common.OffsetOutOfRangeException</code> 这一句即可,可以明显看出问题所在:<strong> 下标越界 </strong>,下一步开始分析问题、解决问题。</p><h1 id="问题分析解决"><a href="# 问题分析解决" class="headerlink" title="问题分析解决"></a>问题分析解决</h1><h2 id="分析"><a href="# 分析" class="headerlink" title="分析"></a> 分析</h2><p>原因既然是 <strong>下标越界 </strong>,就要先搞清楚 <code>Kafka</code> 在什么场景下会出现这个异常。</p><p>通过查看源代码得知,这是 <code>Kafka topic</code> 的 <code>offset</code> 下标越界异常,对应我这个场景,就是 <code>Spark</code> 任务在消费 <code>Kafka topic</code> 的数据时,指定的下标不在 <strong>有效数据 </strong>范围之内。</p><p>有点看不明白?的确,此处有必要插入一些基本知识点。<strong> 消费者 </strong>客户端在消费处理 <code>Kafka topic</code> 的数据时,会有一个 <strong>偏移量 </strong>【取值是数字】记录已经消费数据的位置,也可以说是下标,称之为 <code>offset</code>,并同步更新到 <code>Zookeeper</code> 中。[^1] 如果 <strong>消费者 </strong>客户端在消费中途出问题而停止,等下一次消费时会从上一次中断的 <strong>偏移量 </strong>位置开始继续消费数据,[^2] 这样就可以避免重复消费数据,节约资源。</p><p>以上注解 1、注解 2:</p><p>[^1]: 注意,<code>Kafka v0.9.0.x</code> 以及之后的版本不再是这个策略,不再使用 <code>Zookeeper</code> 存储,改成存储到 <code>kafka</code> 的 <code>broker</code> 节点上面,更方便管理。</p><p>[^2]: 注意,这里的消费策略是通过参数 <code>auto.offset.reset</code> 设置的,从上一次中断的位置继续消费数据只是消费策略选择之一,取值 <code>smallest</code>。另外,<code>Kafka v0.7.x</code> 以及之前的版本这个参数曾经的名称为:<code>autooffset.reset</code>。这个参数的取值在 <code>v.0.9.0.x</code> 以及之后的版本也更名为:<code>earliest</code>、<code>latest</code>、<code>none</code>。</p><p>接着回到正题,如果发生 <strong>下标越界 </strong>现象,说明 <code>Zookeeper</code> 中保存 <strong>消费者 </strong>的 <code>offset</code> 的值小于 <code>topic</code> 中存在的最早的 <code>message</code> 的 <code>offset</code> 值,即 <code>zookeeper_offset < 最早_offset</code>。</p><p>这就导致 <strong>消费者 </strong>程序运行时需要消费的数据在 <code>Kafka topic</code> 中并不存在,进而引发异常的发生。表面上是因为消费的 <code>Zookeeper</code> 缓存信息不正确,实际上是因为 <code>Kafka</code> 的数据过期被清除了,下面我将使用 <code>Kafka</code> 自带的命令来一一验证。</p><h2 id="验证"><a href="# 验证" class="headerlink" title="验证"></a>验证</h2><p>先查看 <strong>消费者 </strong>的消费进度信息,指定 <code>Zookeeper</code> 主机、消费 <code>group</code> 组名、<code>topic</code> 名称,使用命令:<code>bin/kafka-consumer-offset-checker.sh --zookeeper zkhost:2181 --group consumer_group_name --topic topic_name</code>。</p><p>查看消费进度,可以看到 <code>offset</code> 是 0,表示从头开始消费,<code>logSize</code> 是 10044740,表示 <code>Kafka topic</code> 已经生产了这么多数据。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728180912.png" alt="查看消费进度" title="查看消费进度"></p><p>从上图可以看出 <code>topic</code> 的 <strong>消费者 </strong>只有 1 个消费组分区,为了保险起见,再验证一下这个 <code>topic</code> 的分区数是怎样的,使用命令:<code>bin/kafka-topics.sh --describe --zookeeper zkhost:2181 --topic topic_name</code>。</p><p>查看分区数,可以看到只有 1 个分区,编号为 0 。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728180936.png" alt="查看分区数" title="查看分区数"></p><p>综上截图,可以得出总结,<strong> 消费者 </strong>程序是从下标 0 开始消费数据,也就是从头开始,而 <code>topic</code> 的数据已经生产了 1000 多万。那么,读者就会怀疑,这种情况下怎么可能会 <strong>下标越界 </strong>呢,0 就是开始的位置,还怎么越界。除非 <code>topic</code> 当前的数据量为 0,而不是 1000 多万。</p><p>我思考了一下,上述的结论是基于 <code>Zookeeper</code> 的缓存信息得到的,如果 <code>Kafka topic</code> 里面真的有数据存在,的确不可能下标越界。但是,此处还会有另外一种情况,如果 <code>Kafka</code> 里面的数据已经过期了【<code>Kafka</code> 有相关的参数可以设置过期策略】,那就会找不到数据,则报错 <strong>下标越界 </strong>。</p><p>再结合我的业务场景,由于我的 <strong>消费者 </strong>程序给消费组重新定义了名字【使用 <code>group.id</code> 参数】,所以会从头消费【<code>offset</code> 为 0】,但是测试环境的 <code>Kafka topic</code> 里面的数据极有可能是很久之前的,从创建 <code>topic</code> 开始到现在累积了 1000 多万数据,大量数据由于过期策略已经被清除了,现在肯定找不到。</p><p>接下来去查看 <code>Kafka broker</code> 服务的相关配置:过期策略、数据存储位置,在 <code>kafka broker</code> 的安装目录查看 <code>conf/server.properties</code> 配置文件,验证我的猜测。</p><p>首先查看名称为 <code>log.retention.*</code> 的相关参数,看看设置的值是什么:</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181003.png" alt="查看 Kafka 过期策略" title="查看 Kafka 过期策略"></p><p>可以看到,相关参数设置的值是 <code>log.retention.hours=48</code>,也就是说数据的有效期是 48 小时,过期会自动清理,而 <code>log.retention.bytes=-1</code> 表示不限制数据空间大小,即不会因为数据占用空间太大而删除。</p><p>那么,<code>Kafka topic</code> 里面的数据是不是真的不在了呢,让我一探究竟,继续从配置文件中查看数据存储目录,参数名称为:<code>log.dirs</code> 。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181036.png" alt="查看 Kafka 数据存储位置" title="查看 Kafka 数据存储位置"></p><p>可以看到,数据与索引存储在 <code>/kafka-logs</code> 目录,进入目录,找到指定的 <code>topic</code>、<code>partition</code> 对应的目录,我这里是 <code>/kafka-logs/topic_name-partition_number</code>。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181046.png" alt="查看 Kafka 数据文件" title="查看 Kafka 数据文件"></p><p>可以从上图看到目录里面有 2 个文件,分别是数据文件:<code>00000000000010044740.log</code>、索引文件:<code>00000000000010044740.index</code>。通过查看文件空间大小,发现数据文件的大小的是 0B,什么意思呢,表示没有数据,看来数据已经全部过期而且都被清理掉了。</p><p>至此,验证了我全部的分析猜测,下面可以简单复现一下这个异常现象。</p><h2 id="重现异常"><a href="# 重现异常" class="headerlink" title="重现异常"></a>重现异常</h2><p>1、修改配置文件,把过期时间设置为 3 分钟:<code>log.retention.minutes=3</code>,然后重启 <code>Kafka</code> 服务。<br>2、使用 <code>Kafka producer</code> 生产一批数据,100 条,并等待 3 分钟,数据由于过期会被清理。<br>3、启动 <code>SparkStreaming</code> 消费程序处理数据,出现异常。<br>4、使用 <code>Kafka</code> 命令查看 <strong>消费者 </strong>消费进度信息,<code>offset</code> 是 0,<code>logSize</code> 是 100 。<br>5、去 <code>Zookeeper</code> 里面查看 <code>zk_offset</code> 的值,是 0 。</p><p>复现异常,现象完全一致,至此问题原因找到。</p><p>总结一下:我这里的 <code>Kafka topic</code> 已经生产了 1000 多万的数据,但是旧数据由于过期被清理,而且全部被清理掉了。然而 <code>Zookeeper</code> 中的 <code>Kafka topic</code> 信息仍旧保留,<strong> 消费者 </strong>程序从头消费的时候,实际上已经获取不到 <code>Kafka topic</code> 的真实数据,所以一定会有异常。</p><h2 id="解决"><a href="# 解决" class="headerlink" title="解决"></a>解决</h2><p>那怎么办呢,如果 <code>Kafka topic</code> 继续生产数据,我的 <strong>消费者 </strong>程序怎么才能消费到新数据呢?</p><p>其实还是有办法的,最简单的就是不要使用新的消费组名【<code>group.id</code> 参数指定】,如果能继续使用以前的消费组名,并且以前已经把数据消费处理完了,那么它的 <code>offset</code> 也就是最大的值。此时如果继续消费数据,是从最大的 <strong>偏移量 </strong>位置开始消费的,即只会消费最新生产的数据,不会有 <strong>下标越界 </strong>的异常出现。</p><p>但是,如果非要使用新的消费组名称,并且也想从最新生产的数据开始消费【从头再重复消费 1000 多万数据太浪费资源】,有没有办法呢。当然也有,可以手动在 <code>Zookeeper</code> 查询一下消费者的 <strong>偏移量 </strong>,主要查看当前消费组对某个 <code>Kafka topic</code> 的消费 <strong>偏移量 </strong>,然后根据实际情况重置即可。</p><p>先登录 <code>Zookeeper</code> 服务,在指定目录查看消费者的 <strong>偏移量 </strong>,需要指定消费组名称、<code>topic</code> 名称,使用命令:<code>get /consumers/consumer_group_name/offsets/topic_name/0</code> 。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181432.png" alt="查看消费分区偏移量" title="查看消费分区偏移量"></p><p>可以看到当前取值是 0,接着重置消费者的 <strong>偏移量 </strong>,使用命令:<br><code>set /consumers/consumer_group_name/offsets/topic_name/0 10044740</code> 。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181441.png" alt="重置消费分区偏移量" title="重置消费分区偏移量"></p><p>我把它重置为最大值,接下来再测试消费程序就会从最新生产的数据开始消费。</p><p>好了,接下来就成功运行了。</p><h1 id="总结备注"><a href="# 总结备注" class="headerlink" title="总结备注"></a>总结备注</h1><h2 id="不同版本之间的参数差异"><a href="# 不同版本之间的参数差异" class="headerlink" title="不同版本之间的参数差异"></a> 不同版本之间的参数差异</h2><p>本文是基于低版本的 <code>Kafka</code> 进行分析问题的:<code>v0.8.2.1</code>,关于里面的参数信息可以参考官网:<br><a href="https://kafka.apache.org/082/documentation.html#consumerconfigs" target="_blank" rel="noopener">Kafka-v0.8.2-configuration</a> 。</p><p>其中,<code>auto.offset.reset</code> 这个参数【<code>v0.7.x</code> 之前参数名称为 <code>autooffset.reset</code>】的解释说明如图。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190729204654.png" alt="低版本 auto.offset.reset 参数说明" title="低版本 auto.offset.reset 参数说明"></p><p>原文如下:</p><blockquote><p>What to do when there is no initial offset in ZooKeeper or if an offset is out of range:</p><ul><li><code>smallest</code> : automatically reset the offset to the smallest offset</li><li><code>largest</code> : automatically reset the offset to the largest offset</li><li><code>anything else</code>: throw exception to the consumer</li></ul></blockquote><p>参数含义的总结归纳:</p><ul><li><code>smallest</code>:当各分区下有已提交的 <code>offset</code> 时,从提交的 <code>offset</code> 开始消费;无提交的 <code>offset</code> 时,从头开始消费</li><li><code>largest</code>:当各分区下有已提交的 <code>offset</code> 时,从提交的 <code>offset</code> 开始消费;无提交的 <code>offset</code> 时,从该分区下新产生的数据开始消费</li><li><code>anything else</code>:<code>topic</code> 各分区都存在已提交的 <code>offset</code> 时,从 <code>offset</code> 后开始消费;只要有一个分区不存在已提交的 <code>offset</code>,则抛出异常信息</li></ul><p>关于 <code>v0.7.x</code> 版本的参数信息参考官网:<br><a href="https://kafka.apache.org/07/documentation/#configuration" target="_blank" rel="noopener">Kafka-v0.7.x-configuration</a> 。</p><p>其中,<code>autooffset.reset</code> 这个参数名称和以后的都不一样,解释说明如图。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728181607.png" alt="低版本 autooffset.reset 参数说明" title="低版本 autooffset.reset 参数说明"></p><p>原文如下:</p><blockquote><ul><li><code>smallest</code>: automatically reset the offset to the smallest offset available on the broker.</li><li><code>largest</code> : automatically reset the offset to the largest offset available on the broker.</li><li><code>anything else</code>: throw an exception to the consumer.</li></ul></blockquote><p>至于高版本的配置信息,也可以参考官网:<br><a href="https://kafka.apache.org/090/documentation.html#consumerconfigs" target="_blank" rel="noopener">Kafka-v0.9.0.x-configuration</a> 。</p><p>其中,<code>auto.offset.reset</code> 这个参数的解释说明如图,自从 <code>v0.9.0.x</code> 版本之后,它的取值已经变化。</p><p><img src="https://raw.githubusercontent.com/iplaypi/img-playpi/master/img/2017/20190728190054.png" alt="高版本 auto.offset.reset 参数说明" title="高版本 auto.offset.reset 参数说明"></p><p>原文如下:</p><blockquote><p>What to do when there is no initial offset in Kafka or if the current offset does not exist any more on the server (e.g. because that data has been deleted):</p><ul><li><code>earliest</code>: automatically reset the offset to the earliest offset.</li><li><code>latest</code>: automatically reset the offset to the latest offset.</li><li><code>none</code>: throw exception to the consumer if no previous offset is found for the consumer’s group.</li><li><code>anything else</code>: throw exception to the consumer.</li></ul></blockquote><h2 id="消费者信息存储位置"><a href="# 消费者信息存储位置" class="headerlink" title="消费者信息存储位置"></a>消费者信息存储位置</h2><p><strong>消费者 </strong>信息存储位置的问题,新版本【v0.9.x 以及之后】不存储在 <code>Zookeeper</code> 了,转而存到 <code>Kafka</code> 的 <code>broker</code> 节点。如果有 <strong>消费者 </strong>启动,那么这个 <strong>消费者 </strong>的组名和它要消费的那个 <code>topic</code> 的 <code>offset</code> 信息就会被记录在 <code>broker</code> 节点上。</p><h2 id="关于偏移量的另一个常见异常"><a href="# 关于偏移量的另一个常见异常" class="headerlink" title="关于偏移量的另一个常见异常"></a>关于偏移量的另一个常见异常</h2><p>关于偏移量 <code>offset</code> 的问题,还有一个常见异常:<code>numRecords must not be negative</code>,它主要是由删除 <code>Kafka topic</code> 后又新建同名的 <code>topic</code> 引起的。根本原因在于删除 <code>topic</code> 后没有把 <code>Zookeeper</code> 中的 <strong>消费者 </strong>的信息也一同删除,导致遗留的 <strong>消费者 </strong>的信息在新建同名后 <code>topic</code> 被作为当前 <code>topic</code> 的 <strong>消费者 </strong>的信息,如果此时启动一个消费程序,在计算 <code>numRecords</code> 的时候会出现负数的情况【0 减去 old_offset】,接着就会抛出这个异常。</p></div><div><div id="wechat_subscriber" style="display:block;padding:10px 0;margin:20px auto;width:100%;text-align:center"><img id="wechat_subscriber_qcode" src="/images/wechat-qr-personal.jpg" alt="虾丸派 wechat" style="width:200px;max-width:100%"><div>扫一扫添加博主,进技术交流群,共同学习进步</div></div></div><div><div style="padding:10px 0;margin:20px auto;width:90%;text-align:center"><div>永不止步</div><button id="rewardButton" disable="enable" onclick='var qr=document.getElementById("QR");"none"===qr.style.display?qr.style.display="block":qr.style.display="none"'><span>打赏</span></button><div id="QR" style="display:none"><div id="wechat" style="display:inline-block"><img id="wechat_qr" src="/images/wechat-pay-playpi.png" alt="虾丸派 微信支付"><p>微信支付</p></div></div></div></div><div><ul class="post-copyright"><li class="post-copyright-author"><strong>本文作者:</strong> 虾丸派</li><li class="post-copyright-link"><strong>本文链接:</strong> <a href="https://www.playpi.org/2017060101.html" title="记录一个 Kafka 错误:OffsetOutOfRangeException">https://www.playpi.org/2017060101.html</a></li><li class="post-copyright-license"><strong>版权声明: </strong>本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/" rel="external nofollow" target="_blank">CC BY-NC-SA 3.0</a> 许可协议。转载请注明出处!</li></ul></div><footer class="post-footer"><div class="post-tags"><a href="/tags/Spark/" rel="tag"><i class="fa fa-tag"></i> Spark</a> <a href="/tags/Kafka/" rel="tag"><i class="fa fa-tag"></i> Kafka</a> <a href="/tags/SparkStreaming/" rel="tag"><i class="fa fa-tag"></i> SparkStreaming</a> <a href="/tags/Zookeeper/" rel="tag"><i class="fa fa-tag"></i> Zookeeper</a> <a href="/tags/OffsetOutOfRangeException/" rel="tag"><i class="fa fa-tag"></i> OffsetOutOfRangeException</a></div><div class="post-nav"><div class="post-nav-next post-nav-item"><a href="/2017052101.html" rel="next" title="在 Windows 平台遇到 Hadoop 异常:UnsatisfiedLinkError"><i class="fa fa-chevron-left"></i> 在 Windows 平台遇到 Hadoop 异常:UnsatisfiedLinkError</a></div><span class="post-nav-divider"></span><div class="post-nav-prev post-nav-item"><a href="/2017061401.html" rel="prev" title="在 Elasticsearch 中一个字段支持的最大字符数">在 Elasticsearch 中一个字段支持的最大字符数 <i class="fa fa-chevron-right"></i></a></div></div></footer></div></article><div class="post-spread"></div></div></div><div class="comments" id="comments"><div id="vcomments"></div></div></div><div class="sidebar-toggle"><div class="sidebar-toggle-line-wrap"><span class="sidebar-toggle-line sidebar-toggle-line-first"></span> <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span> <span class="sidebar-toggle-line sidebar-toggle-line-last"></span></div></div><aside id="sidebar" class="sidebar"><div class="sidebar-inner"><ul class="sidebar-nav motion-element"><li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">文章目录</li><li class="sidebar-nav-overview" data-target="site-overview-wrap">站点概览</li></ul><section class="site-overview-wrap sidebar-panel"><div class="site-overview"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"><img class="site-author-image" itemprop="image" src="/images/favicon-1536x1536-playpi.png" alt="虾丸派"><p class="site-author-name" itemprop="name">虾丸派</p><p class="site-description motion-element" itemprop="description">记录知识 | 分享技术</p></div><nav class="site-state motion-element"><div class="site-state-item site-state-posts"><a href="/archives/"><span class="site-state-item-count">144</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"><a href="/categories/index.html"><span class="site-state-item-count">13</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"><a href="/tags/index.html"><span class="site-state-item-count">294</span> <span class="site-state-item-name">标签</span></a></div></nav><div class="feed-link motion-element"><a href="/atom.xml" rel="alternate"><i class="fa fa-rss"></i> RSS</a></div><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="https://github.com/iplaypi" target="_blank" title="GitHub"><i class="fa fa-fw fa-github"></i>GitHub</a> </span><span class="links-of-author-item"><a href="https://weibo.com/u/3086148515" target="_blank" title="微博"><i class="fa fa-fw fa-weibo"></i>微博</a> </span><span class="links-of-author-item"><a href="mailto:playpi@qq.com" target="_blank" title="E-Mail"><i class="fa fa-fw fa-envelope"></i>E-Mail</a></span></div><div class="cc-license motion-element" itemprop="license"><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" target="_blank" rel="external nofollow"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a></div><div class="links-of-blogroll motion-element links-of-blogroll-inline"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-link"></i> 友情链接</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"><a href="https://github.com/iplaypi" title="GitHub" target="_blank" rel="external nofollow">GitHub</a></li><li class="links-of-blogroll-item"><a href="https://weibo.com/u/3086148515" title="Weibo" target="_blank" rel="external nofollow">Weibo</a></li><li class="links-of-blogroll-item"><a href="https://www.playpi.org" title="虾丸派" target="_blank" rel="external nofollow">虾丸派</a></li><li class="links-of-blogroll-item"><a href="https://www.playpi.org" title="playpi" target="_blank" rel="external nofollow">playpi</a></li><li class="links-of-blogroll-item"><a href="https://www.liaoxuefeng.com" title="廖雪峰" target="_blank" rel="external nofollow">廖雪峰</a></li><li class="links-of-blogroll-item"><a href="http://www.ruanyifeng.com" title="阮一峰" target="_blank" rel="external nofollow">阮一峰</a></li><li class="links-of-blogroll-item"><a href="https://travis-ci.org/iplaypi/iplaypi.github.io" title="travis-ci" target="_blank" rel="external nofollow">travis-ci</a></li><li class="links-of-blogroll-item"><a href="https://www.vultr.com/?ref=7861302-4F" title="Vultr" target="_blank" rel="external nofollow">Vultr</a></li></ul></div></div></section><section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active"><div class="post-toc"><div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#问题出现"><span class="nav-number">1.</span> <span class="nav-text">问题出现</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#问题分析解决"><span class="nav-number">2.</span> <span class="nav-text">问题分析解决</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#分析"><span class="nav-number">2.1.</span> <span class="nav-text">分析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#验证"><span class="nav-number">2.2.</span> <span class="nav-text">验证</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#重现异常"><span class="nav-number">2.3.</span> <span class="nav-text">重现异常</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#解决"><span class="nav-number">2.4.</span> <span class="nav-text">解决</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#总结备注"><span class="nav-number">3.</span> <span class="nav-text">总结备注</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#不同版本之间的参数差异"><span class="nav-number">3.1.</span> <span class="nav-text">不同版本之间的参数差异</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#消费者信息存储位置"><span class="nav-number">3.2.</span> <span class="nav-text">消费者信息存储位置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#关于偏移量的另一个常见异常"><span class="nav-number">3.3.</span> <span class="nav-text">关于偏移量的另一个常见异常</span></a></li></ol></li></ol></div></div></section></div></aside></div></main><footer id="footer" class="footer"><div class="footer-inner"><div class="copyright">© 2016–<span itemprop="copyrightYear">2021</span> <span class="post-meta-divider">|</span> <span class="with-love"><i class="fa fa-heart"></i> </span><span class="author" itemprop="copyrightHolder">虾丸派</span> <span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-area-chart"></i> </span><span class="post-meta-item-text">全站字数统计</span> <span title="全站字数统计">326.3k 字</span></div><div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io" rel="external nofollow">Hexo</a> 强力驱动</div><span class="post-meta-divider">|</span><div class="theme-info">主题 <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next" rel="external nofollow">NexT.Mist</a><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span id="busuanzi_container_site_pv" style="display:none"><span class="post-meta-divider">|</span> 总访问量 <span id="busuanzi_value_site_pv"></span> 次 </span><span id="busuanzi_container_site_uv" style="display:none"><span class="post-meta-divider">|</span> 总访客 <span id="busuanzi_value_site_uv"></span> 人</span></div><div class="busuanzi-count"><script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></div></footer><div class="back-to-top"><i class="fa fa-arrow-up"></i> <span id="scrollpercent"><span>0</span>%</span></div></div><script type="text/javascript">"[object Function]"!==Object.prototype.toString.call(window.Promise)&&(window.Promise=null)</script><script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script><script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script><script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script><script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script><script type="text/javascript" src="/js/src/utils.js?v=5.1.3"></script><script type="text/javascript" src="/js/src/motion.js?v=5.1.3"></script><script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.3"></script><script type="text/javascript" src="/js/src/post-details.js?v=5.1.3"></script><script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.3"></script><script src="//unpkg.com/valine@1.3.7/dist/Valine.min.js"></script><script type="text/javascript">new Valine({av:AV,el:"#comments",verify:!1,notify:!1,app_id:"FC5Jijeg1meo2K2OzPYWK327-gzGzoHsz",app_key:"6A1ReY8tjhPutK00F01YbJSq",placeholder:"没有问题吗?"})</script><script type="text/javascript">var isfetched=!1,isXml=!0,search_path="search.xml";0===search_path.length?search_path="search.xml":/json$/i.test(search_path)&&(isXml=!1);var path="/"+search_path,onPopupClose=function(t){$(".popup").hide(),$("#local-search-input").val(""),$(".search-result-list").remove(),$("#no-result").remove(),$(".local-search-pop-overlay").remove(),$("body").css("overflow","")};function proceedsearch(){$("body").append('<div class="search-popup-overlay local-search-pop-overlay"></div>').css("overflow","hidden"),$(".search-popup-overlay").click(onPopupClose),$(".popup").toggle();var t=$("#local-search-input");t.attr("autocapitalize","none"),t.attr("autocorrect","off"),t.focus()}var searchFunc=function(t,e,s){"use strict";$("body").append('<div class="search-popup-overlay local-search-pop-overlay"><div id="search-loading-icon"><i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i></div></div>').css("overflow","hidden"),$("#search-loading-icon").css("margin","20% auto 0 auto").css("text-align","center"),$.ajax({url:t,dataType:isXml?"xml":"json",async:!0,success:function(t){isfetched=!0,$(".popup").detach().appendTo(".header-inner");var o=isXml?$("entry",t).map(function(){return{title:$("title",this).text(),content:$("content",this).text(),url:$("url",this).text()}}).get():t,n=document.getElementById(e),r=document.getElementById(s),t=function(){var m=n.value.trim().toLowerCase(),x=m.split(/[\s\-]+/);1<x.length&&x.push(m);var e,w=[];0<m.length&&o.forEach(function(t){var e=!1,o=0,h=0,n=t.title.trim(),r=n.toLowerCase(),s=t.content.trim().replace(/<[^>]+>/g,""),a=s.toLowerCase(),i=decodeURIComponent(t.url),c=[],l=[];if(""!=n&&(x.forEach(function(t){function e(t,e,o){var n=t.length;if(0===n)return[];var r,s=0,a=[];for(o||(e=e.toLowerCase(),t=t.toLowerCase());-1<(r=e.indexOf(t,s));)a.push({position:r,word:t}),s=r+n;return a}c=c.concat(e(t,r,!1)),l=l.concat(e(t,a,!1))}),(0<c.length||0<l.length)&&(e=!0,o=c.length+l.length)),e){function p(t,e,o,n){for(var r=n[n.length-1],s=r.position,a=r.word,i=[],c=0;s+a.length<=o&&0!=n.length;){a===m&&c++,i.push({position:s,length:a.length});var l=s+a.length;for(n.pop();0!=n.length&&(s=(r=n[n.length-1]).position,a=r.word,s<l);)n.pop()}return h+=c,{hits:i,start:e,end:o,searchTextCount:c}}[c,l].forEach(function(t){t.sort(function(t,e){return e.position!==t.position?e.position-t.position:t.word.length-e.word.length})});t=[];0!=c.length&&t.push(p(0,0,n.length,c));for(var u=[];0!=l.length;){var f=l[l.length-1],d=f.position,g=f.word,v=d-20,f=d+80;v<0&&(v=0),(f=f<d+g.length?d+g.length:f)>s.length&&(f=s.length),u.push(p(0,v,f,l))}u.sort(function(t,e){return t.searchTextCount!==e.searchTextCount?e.searchTextCount-t.searchTextCount:t.hits.length!==e.hits.length?e.hits.length-t.hits.length:t.start-e.start});e=parseInt("1");function $(o,t){var n="",r=t.start;return t.hits.forEach(function(t){n+=o.substring(r,t.position);var e=t.position+t.length;n+='<b class="search-keyword">'+o.substring(t.position,e)+"</b>",r=e}),n+=o.substring(r,t.end)}0<=e&&(u=u.slice(0,e));var C="";0!=t.length?C+="<li><a href='"+i+"' class='search-result-title'>"+$(n,t[0])+"</a>":C+="<li><a href='"+i+"' class='search-result-title'>"+n+"</a>",u.forEach(function(t){C+="<a href='"+i+'\'><p class="search-result">'+$(s,t)+"...</p></a>"}),C+="</li>",w.push({item:C,searchTextCount:h,hitCount:o,id:w.length})}}),1===x.length&&""===x[0]?r.innerHTML='<div id="no-result"><i class="fa fa-search fa-5x" /></div>':0===w.length?r.innerHTML='<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>':(w.sort(function(t,e){return t.searchTextCount!==e.searchTextCount?e.searchTextCount-t.searchTextCount:t.hitCount!==e.hitCount?e.hitCount-t.hitCount:e.id-t.id}),e='<ul class="search-result-list">',w.forEach(function(t){e+=t.item}),e+="</ul>",r.innerHTML=e)};n.addEventListener("input",t),$(".local-search-pop-overlay").remove(),$("body").css("overflow",""),proceedsearch()}})};$(".popup-trigger").click(function(t){t.stopPropagation(),!1===isfetched?searchFunc(path,"local-search-input","local-search-result"):proceedsearch()}),$(".popup-btn-close").click(onPopupClose),$(".popup").click(function(t){t.stopPropagation()}),$(document).on("keyup",function(t){27===t.which&&$(".search-popup").is(":visible")&&onPopupClose()})</script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}()</script><script type="text/javascript" src="/js/src/js.cookie.js?v=5.1.3"></script><script type="text/javascript" src="/js/src/scroll-cookie.js?v=5.1.3"></script><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({pluginRootPath:"live2dw/",pluginJsPath:"lib/",pluginModelPath:"assets/",tagMode:!1,debug:!1,model:{scale:1,jsonPath:"/live2dw/assets/hijiki.model.json"},display:{position:"left",width:100,height:200,hOffset:0,vOffset:-20},mobile:{show:!1,motion:!0,scale:.3},log:!1})</script></body></html>