我正在尝试对akka
库的版本进行着色并将其与我的应用程序捆绑在一起(以便能够在spray-can
版CDH 5.7
版本上运行Spark 1.6
服务器})。着色过程messes up akka
's default configuration,在为着色akka
手动提供reference.conf
akka
的单独版本后,它仍然看起来像2个版本混合以某种方式。
已知阴影akka
版本会导致问题吗?我究竟做错了什么?
我的Scala
/ Spark
应用程序当前正在Spark 1.6.1
独立运行。该应用程序使用spray 1.3.3
运行spray-can
http服务器,这需要akka 2.3.9
(Spark 1.6.1
独立包含兼容的akka 2.3.11
。)
我正在尝试将应用程序迁移到运行Spark
CDH 5.7
版本Spark 1.6
的基于Cloudera
的新Spark 1.6
群集。问题是CDH 5.7
中的akka 2.2.3
与spray 1.3.3
捆绑在一起,这不足以让akka 2.3.9
正常运作。
根据this post中的建议,我决定对akka
进行着色并将其与我的应用程序捆绑在一起。虽然这次我偶然发现了一个新问题 - reference.conf
在sbt-assembly
文件中定义了默认配置,该文件应该位于应用程序的类路径中。由于akka
的着色功能中的known issue,阴影akka
库似乎需要单独配置。
所以,我最终使用以下阴影规则着色ShadeRule.rename("akka.**" -> "akka_2_3_9_shade.@1")
.inLibrary("com.typesafe.akka" % "akka-actor_2.10" % "2.3.9")
.inAll
:
reference.conf
并在我的项目中包含一个额外的akka
文件,该文件与reference.conf
的原始Spark
相同,但所有出现的都是" akka&#34 ;替换为" akka_2_3_9_shade"。
现在,似乎akka
- 提供的akka
以某种方式与阴影Exception in thread "main" java.lang.IllegalArgumentException: Cannot instantiate MailboxType [akka.dispatch.UnboundedMailbox], defined in [akka.actor.default-mailbox], make sure it has a public constructor with [akka.actor.ActorSystem.Settings, com.typesafe.config.Config] parameters
at akka_2_3_9_shade.dispatch.Mailboxes$$anonfun$1.applyOrElse(Mailboxes.scala:197)
at akka_2_3_9_shade.dispatch.Mailboxes$$anonfun$1.applyOrElse(Mailboxes.scala:195)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:33)
at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:185)
at scala.util.Try$.apply(Try.scala:161)
at scala.util.Failure.recover(Try.scala:185)
at akka_2_3_9_shade.dispatch.Mailboxes.lookupConfiguration(Mailboxes.scala:195)
at akka_2_3_9_shade.dispatch.Mailboxes.lookup(Mailboxes.scala:78)
at akka_2_3_9_shade.actor.LocalActorRefProvider.akka$actor$LocalActorRefProvider$$defaultMailbox$lzycompute(ActorRefProvider.scala:561)
at akka_2_3_9_shade.actor.LocalActorRefProvider.akka$actor$LocalActorRefProvider$$defaultMailbox(ActorRefProvider.scala:561)
at akka_2_3_9_shade.actor.LocalActorRefProvider$$anon$1.<init>(ActorRefProvider.scala:568)
at akka_2_3_9_shade.actor.LocalActorRefProvider.rootGuardian$lzycompute(ActorRefProvider.scala:564)
at akka_2_3_9_shade.actor.LocalActorRefProvider.rootGuardian(ActorRefProvider.scala:563)
at akka_2_3_9_shade.actor.LocalActorRefProvider.init(ActorRefProvider.scala:618)
at akka_2_3_9_shade.actor.ActorSystemImpl.liftedTree2$1(ActorSystem.scala:619)
at akka_2_3_9_shade.actor.ActorSystemImpl._start$lzycompute(ActorSystem.scala:616)
at akka_2_3_9_shade.actor.ActorSystemImpl._start(ActorSystem.scala:616)
at akka_2_3_9_shade.actor.ActorSystemImpl.start(ActorSystem.scala:633)
at akka_2_3_9_shade.actor.ActorSystem$.apply(ActorSystem.scala:142)
at akka_2_3_9_shade.actor.ActorSystem$.apply(ActorSystem.scala:109)
at akka_2_3_9_shade.actor.ActorSystem$.apply(ActorSystem.scala:100)
at MyApp.api.Boot$delayedInit$body.apply(Boot.scala:45)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
at scala.App$class.main(App.scala:71)
at MyApp.api.Boot$.main(Boot.scala:28)
at MyApp.api.Boot.main(Boot.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:731)
at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:181)
at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:206)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:121)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassCastException: interface akka_2_3_9_shade.dispatch.MailboxType is not assignable from class akka.dispatch.UnboundedMailbox
at akka_2_3_9_shade.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:69)
at akka_2_3_9_shade.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:66)
at scala.util.Try$.apply(Try.scala:161)
at akka_2_3_9_shade.actor.ReflectiveDynamicAccess.getClassFor(DynamicAccess.scala:66)
at akka_2_3_9_shade.actor.ReflectiveDynamicAccess.CreateInstanceFor(DynamicAccess.scala:84)
... 34 more
混淆,因为我收到以下错误:
Boot.scala
我的应用程序[45] implicit val system = ActorSystem()
...
[48] val service = system.actorOf(Props[MyAppApiActor], "MyApp.Api")
...
[52] val port = config.getInt("MyApp.server.port")
[53] IO(Http) ? Http.Bind(service, interface = "0.0.0.0", port = port)
文件中的相关代码如下:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript">
function validateForm(){
var firstname=document.getElementById("fname").value;
firstname.trim();
var lastname=document.getElementById("lname").value;
lastname.trim();
var emailid=document.getElementById("email").value;
emailid.trim();
var conatctnumber=document.getElementById("cont").value;
cont.trim();
//alert(firstname+lastname+emailid+conatctnumber);
if(firstname_validation(firstname)){
if(lastname_validation(lastname)){
if(emailid_validation(emailid)){
if(contactnumber_validation(contactnumber)){
return true;
}
else{
return false;
}
}
}
}
}
function firstname_validation(firstname){
var letters = /^[A-Za-z]+$/;
if(firstname.match(letters))
{
return true;
}
else
{
alert('firstname must have alphabet characters only');
fname.focus();
return false;
}
}
function lastname_validation(lastname){
var letters = /^[A-Za-z]+$/;
if(lastname.match(letters))
{
return true;
}
else
{
alert('lastname must have alphabet characters only');
lastname.focus();
return false;
}
}
function emailid_validation(emailid){
var mailformat=/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if(emailid.match(mailformat)){
return ture;
}
else{
alert("Enter correct email address");
emailid.focus();
return false;
}
}
function contactnumber_validation(contactnumber){
var letters="/^\d{10}$/";
if(contactnumber.match(letters)){
return true;
}
else{
alert("enter valid contact number");
contactnumber.focus();
return false;
}
}
</script>
</head>
<body>
<form name="myform" action="UserServlet" method="post" >
<input style="display: none;" type = "text" name="userid" value="<c:out value="${update.userid} "> </c:out>"><br>
First Name:<br>
<input type = "text" id="fname" name="firstname" value="<c:out value="${update.firstname} "></c:out>" maxlength="40" required><br>
Last Name:<br>
<input type = "text" id="lname" name="lastname" value="<c:out value="${update.lastname} "></c:out>" maxlength="40" required><br>
EmailId:<br>
<input type="text" id="email" name="emaild" value="<c:out value="${update.emailid} "></c:out>" maxlength="50" required><br>
Contact Number:<br>
<input type="text" id="cont" name="contactnumber" value="<c:out value="${update.contactnumber}"></c:out>" maxlength="10" required><br>
<input type="button" value="submit" onClick="return validateForm()">
</form>
</body>
</html>
答案 0 :(得分:6)
好的,所以最终我设法解决了这个问题。
使用定义为字符串文字的键从配置文件中加载akka
个(部分)配置设置。例如,您可以在akka/actor/ActorSystem.scala
中找到很多这样的内容。
似乎sbt-assembly
不会更改字符串文字中对着色库/包名称的引用。
此外,某些配置键 会被sbt-assembly
的阴影更改。我还没有花时间在akka
的源代码中找到它们的定义位置和方式,但是在ActorSystem
初始化代码中抛出了以下异常,证明确实如此:
ConfigException$Missing: No configuration setting found for key 'akka_2_3_9_shade'
所以,解决方案包括自定义配置文件(例如调用它akka_spray_shade.conf
),并在其中复制以下配置部分:
akka
原始reference.conf
的内容,但配置值中的akka
前缀更改为akka_2_3_9_shade
。 (这是硬编码字符串文字配置键所必需的)akka
原始reference.conf
的内容,但配置值中的akka
前缀更改为akka_2_3_9_shade
并拥有根配置密钥已更改从akka
更改为akka_2_3_9_shade
。 (这是由sbt-assembly
)spray
原始reference.conf
的内容,但配置值中的akka
前缀更改为akka_2_3_9_shade
。 (这是确保spray
始终引用带阴影的akka
)现在,在应用程序的ActorSystem
代码Boot.scala
初始化期间,必须提供显式此自定义配置文件:
val akkaShadeConfig = ConfigFactory.load("akka_spray_shade")
implicit val system = ActorSystem("custom-actor-system-name", akkaShadeConfig)
答案 1 :(得分:1)
接受答案的一小部分。
没有必要将此配置放在自定义命名的文件中,如akka_spray_shade.conf
。在没有明确指定自定义配置的情况下,可以在application.conf
创建期间默认加载ActorSystem
配置:ActorSystem("custom-actor-system-name")
实际上意味着ActorSystem("custom-actor-system-name", ConfigFactory.load("application"))
。
答案 2 :(得分:0)
我也为此挣扎了很长时间。事实证明,sbt-assembly
中的默认合并策略排除了所有 reference.conf
文件。将此添加到 build.sbt
为我解决了这个问题:
assemblyMergeStrategy in assembly := {
case PathList("reference.conf") => MergeStrategy.concat
}