4

私のサーバー アプリケーションでは、Scalatra、json4s、および Akka を使用しています。

受信するリクエストのほとんどは POST であり、固定の応答でクライアントにすぐに返されます。実際の応答は、クライアントのサーバー ソケットに非同期で送信されます。これを行うにgetRemoteAddrは、http リクエストから行う必要があります。私は次のコードを試しています:

case class MyJsonParams(foo:String, bar:Int)

class MyServices extends ScalatraServlet {
  implicit val formats = DefaultFormats

  post("/test") {
    withJsonFuture[MyJsonParams]{ params =>
      // code that calls request.getRemoteAddr goes here
      // sometimes request is null and I get an exception
      println(request)
    }
  }

  def withJsonFuture[A](closure: A => Unit)(implicit mf: Manifest[A]) = {
    contentType = "text/json"
    val params:A = parse(request.body).extract[A]
    future{
      closure(params)
    }      
    Ok("""{"result":"OK"}""")
  }    
}

関数の意図は、withJsonFuture私のルート処理からいくつかの定型文を移動することです。

これは時々機能し ( の null 以外の値を出力しますrequest)、時々requestnull です。これは非常に不可解です。request私は自分の将来を「閉鎖」しなければならないと思っています。ただし、他に要求が行われていないときに、制御されたテスト シナリオでもエラーが発生します。私は不変であると想像requestします(多分私は間違っていますか?)

この問題を解決するために、コードを次のように変更しました。

case class MyJsonParams(foo:String, bar:Int)

class MyServices extends ScalatraServlet {
  implicit val formats = DefaultFormats

  post("/test") {
    withJsonFuture[MyJsonParams]{ (addr, params) =>
      println(addr)
    }
  }

  def withJsonFuture[A](closure: (String, A) => Unit)(implicit mf: Manifest[A]) = {
    contentType = "text/json"
    val addr = request.getRemoteAddr()
    val params:A = parse(request.body).extract[A]
    future{
      closure(addr, params)
    }      
    Ok("""{"result":"OK"}""")
  }    
}

これはうまくいくようです。ただし、将来的にエラーを引き起こす可能性のある、同時実行性に関連する悪いプログラミング手法がまだ含まれているかどうかは本当にわかりません (「将来」は、最も一般的な意味で意味されます = その先にあるもの :)。

4

4 に答える 4

4

Scalatraはわかりませんが、request自分で定義していないという値にアクセスしているのは怪しいです。私の推測では、これは拡張の一部として提供されるものですScalatraServlet。その場合は、リクエストの開始時に (Scalatra によって) 設定され、最後に無効化される可変状態である可能性があります。それが起こっている場合は、ブロックの前のrequestように別の valに割り当ててから、未来と閉鎖の内部としてそれにアクセスするのと同じように、回避策は問題ありません。val myRequest = requestfuturemyRequest

于 2013-07-03T14:53:28.650 に答える