部署jar拓扑时storm缺少资源文件夹

0vvn1miw  于 2021-06-21  发布在  Storm
关注(0)|答案(1)|浏览(520)

我正在尝试部署一个使用multilang bolt(用python编写)的拓扑:

builder.setBolt("avro-parser", new AvroBolt(), 3).shuffleGrouping("main-kafka-spout");
builder.setBolt("nlp-analyzer", new NLPBolt("/python/analyzer/audio_parser.py"), 2).shuffleGrouping("avro-parser");

我可以毫无问题地提交拓扑,但在检查日志文件时发现以下错误:

java.lang.RuntimeException: Error when launching multilang subprocess

    at org.apache.storm.utils.ShellProcess.launch(ShellProcess.java:89) ~[storm-core-1.0.1.jar:1.0.1]
    at org.apache.storm.task.ShellBolt.prepare(ShellBolt.java:131) ~[storm-core-1.0.1.jar:1.0.1]
    at org.apache.storm.daemon.executor$fn__7953$fn__7966.invoke(executor.clj:792) ~[storm-core-1.0.1.jar:1.0.1]
    at org.apache.storm.util$async_loop$fn__625.invoke(util.clj:482) [storm-core-1.0.1.jar:1.0.1]
    at clojure.lang.AFn.run(AFn.java:22) [clojure-1.7.0.jar:?]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_91]
Caused by: java.io.IOException: Cannot run program "/usr/bin/python" (in directory "/var/lib/storm/supervisor/stormdist/sintonea-topology-main-22-1472285031/resources"): error=2, No such file or directory
    at java.lang.ProcessBuilder.start(Unknown Source) ~[?:1.8.0_91]
    at org.apache.storm.utils.ShellProcess.launch(ShellProcess.java:82) ~[storm-core-1.0.1.jar:1.0.1]
    ... 5 more
Caused by: java.io.IOException: error=2, No such file or directory
    at java.lang.UNIXProcess.forkAndExec(Native Method) ~[?:1.8.0_91]
    at java.lang.UNIXProcess.<init>(Unknown Source) ~[?:1.8.0_91]
    at java.lang.ProcessImpl.start(Unknown Source) ~[?:1.8.0_91]
    at java.lang.ProcessBuilder.start(Unknown Source) ~[?:1.8.0_91]
    at org.apache.storm.utils.ShellProcess

当然,我注意到在指定的日志跟踪中没有“resources”文件夹:
/var/lib/storm/supervisor/stormdist/sintonea-topology-main-22-1472285031/资源
如果在该目录中执行“ls”命令,您将看到:

stormcode.ser  stormconf.ser  stormjar.jar

为什么storm不在该目录中创建资源文件夹?
src/main/resources中有两个resources文件夹:
架构:包含avro架构文件
python:包含python代码
这些文件夹被复制到根目录的jar中,而不是/resources文件夹。
这怎么可能?我有一个avrobolt,它以这种方式使用模式,并且没有任何问题(使用dummybolt而不是multilang-bolt进行测试):

_schema = parser.parse(getClass().getResourceAsStream("/schema/caller_request.avsc"));

编辑
我已将资源文件夹移到
basedirectory.value/“多语言”
读完后:
http://storm.apache.org/releases/current/creating-a-new-storm-project.html
现在,资源文件夹已创建并复制,但仍存在相同的问题:

Serializer Exception:
/usr/bin/python: can't open file '/resources/python/analyzer/audio_parser.py': [Errno 2] No such file or directory

编辑2
我找到了一个解决方法(在不同级别创建两个资源文件夹):
在src的父目录中创建multilang/resources(一级以上)。将python文件夹复制到:{base directory}/multilang/resources/python/*.py中
保持文件夹src/main/schema:{base directory}/src/main/resources/schema/caller\u request.avsc完好无损。
并将此添加到my build.sbt:

unmanagedResourceDirectories in Compile += { baseDirectory.value / "multilang" }
unmanagedClasspath in Compile += baseDirectory.value / "multilang"

并将我的shell bot设置为(忽略path中的“resources”或“/”):

NLPBolt nlpBolt = new NLPBolt("python/analyzer/audio_parser.py");

以及:

_schema = parser.parse(getClass().getResourceAsStream("/schema/caller_request.avsc"));

这似乎管用,但我不喜欢这个解决办法。有什么想法吗?
编辑3
顺便说一下,这个代码:

import storm

# from nltk.stem.snowball import SnowballStemmer

from es_tagger import SpanishTagger

config = utils.load_json('python/analyzer/data/config.json')

class AudioParserBolt(storm.BasicBolt):

产生以下错误:

Serializer Exception:
Traceback (most recent call last):
  File "python/analyzer/audio_parser.py", line 27, in <module>
    class AudioParserBolt(storm.BasicBolt):
AttributeError: 'module' object has no attribute 'BasicBolt'
7cwmlq89

7cwmlq891#

所以,基本上我就是这么做的:
创建文件夹${basedir}/multilang/resources-->在其中复制python代码。
从${basedir}/src/main/resources中删除python代码,只保留avro方案。
添加到build.sbt文件:
compile中的unmanagedresourcedirectories+={basedirectory.value/“multilang”}compile中的unmanagedclasspath+=basedirectory.value/“multilang”
从下载storm.pyhttps://github.com/apache/storm/blob/master/storm-multilang/python/src/main/resources/resources/storm.py 并将其复制/粘贴到${basedir}/multilang/resources/python文件夹中。
在python代码中,注解或删除任何print指令(在解析元组时引发java异常,因为print写入标准输出)。
如果您的python进程有点慢(我的进程是nlp进程,第一次设置需要一点时间),请告诉您的拓扑结构再等等:
config.put(config.topology\u subprocess\u timeout\u secs,);
还有很多尝试和错误=)
任何时候需要在python代码中使用外部文件(如配置文件)时,都可以这样调用它(父目录将是我们之前创建的multilang/resources):
config=utils.load\u json('python/analyzer/data/config.json')

相关问题