Scala Akka容错方法
我正在尝试scala+Akka,我正在尝试找出容错性。我有一个actor,它接收来自主管的消息并将数据插入数据库。主管在参与者遇到故障时重新启动该参与者 我正在更改postRestart()中的连接字符串,以防数据库出现连接问题。现在,只要一个数据库存在连接问题,参与者就会重新启动并开始将数据插入另一个数据库 这是一个足够好的方法吗?推荐的方法是什么 主管:Scala Akka容错方法,scala,akka,Scala,Akka,我正在尝试scala+Akka,我正在尝试找出容错性。我有一个actor,它接收来自主管的消息并将数据插入数据库。主管在参与者遇到故障时重新启动该参与者 我正在更改postRestart()中的连接字符串,以防数据库出现连接问题。现在,只要一个数据库存在连接问题,参与者就会重新启动并开始将数据插入另一个数据库 这是一个足够好的方法吗?推荐的方法是什么 主管: class SocialSupervisor extends Actor { override val supervisorSt
class SocialSupervisor extends Actor {
override val supervisorStrategy=OneForOneStrategy(loggingEnabled = false){
case (e:Exception)=>Restart
}
val post_ref=context.actorOf(Props[Post])
def receive={
case Get_Feed(feed)=>{
//get data from feed
post_ref!Post_Message(posted_by,post)
}
}
}
演员:
class Post extends Actor{
val config1=ConfigFactory.load()
var config=config1.getConfig("MyApp.db")
override def postRestart(reason: Throwable) {
config=config1.getConfig("MyApp.backup_db")
super.postRestart(reason)
}
def insert_data(commented_by:String,comment:String){
val connection_string=config.getString("url")
val username=config.getString("username")
val password=config.getString("password")
//DB operations
}
def receive={
case Post_Message(posted_by,message)=>{
insert_data(posted_by, message)
}
}
}
我认为您可以对代码进行一些改进,使其更具“容错性” 模块化 您可能应该将您的
insert_data
函数与Actor的其余部分分开,以便它可以独立于任何Actor系统
进行使用和测试。您的参与者应该只有很少的代码,并且receive
方法基本上应该是外部函数的分派器:
object Post {
def insert_data(conn : Connection)(commented_by : String, comment : String) = {
...
}
}
您甚至可以进一步删除连接
依赖项。从参与者的角度来看,插入只不过是一个函数,它接收PostMessage
,并返回有效行更新的数量:
object Post {
//returns an Int because Statement.executeUpdate returns an Int
type DBInserter : Post_Message => Int
现在,您可以像以前一样插入到数据库连接中:
def insertIntoLiveDB(connFactory : () => Connection) : DBInserter =
(postMessage : Post_Message) => {
val sqlStr = s"INSERT INTO .."
connFactory().createStatement() executeUpdate sqlStr
}
}
或者编写一个函数,该函数从不为测试目的进行插入:
//does no inserting
val neverInsert : DBInserter = (postMessage : Post_Message) => 0
}
现在,您的演员几乎没有逻辑:
class Post(inserter : Post.DBInserter) extends Actor {
def receive = {
case pm : Post_Message => inserter(pm)
}
}
容错性
到目前为止,应用程序中“错误”的最大来源是网络,在您的案例中,通过连接数据库来体现。我们需要一些方法,以便在出现故障时自动刷新连接。我们可以使用factory函数来执行此操作:
def basicConnFactory(timeoutInSecs : Int = 10) = {
//setup initial connection, not specified in question
var conn : Connection = ???
() => {
if(conn isValid timeoutInSecs)
conn
else {
conn = ??? //setup backup connection
conn
}
}
}
现在,每次插入时都会测试连接的有效性,如果出现问题,则会重新建立连接。然后可以使用此工厂创建参与者:
import Post.queryLiveDB
val post_ref =
context actorOf (Props[Post], insertIntoLiveDB(basicConnFactory()))
随着您的生产要求越来越严格,您可以要求工厂使用