I'm testing finagle and got over the current situation:
Server:
import com.twitter.finagle.{Http, Service}
import com.twitter.finagle.http
import com.twitter.util.{Await, Future}
class Server(name: String, port: Int) {
val service = new Service[http.Request, http.Response] {
def apply(req: http.Request): Future[http.Response] = {
println(s"Request on server $name")
Future.value(
http.Response(req.version, http.Status.Ok)
)
}
}
val server = Http.serve(s":$port", service)
}
object Server1 extends App {
val server = new Server("1", 9001).server
Await.ready(server)
}
object Server2 extends App {
val server = new Server("2", 9002).server
Await.ready(server)
}
Client:
import com.twitter.finagle.{Http, Service}
import com.twitter.finagle.http
import com.twitter.util.{Await, Future}
object Client extends App {
val client: Service[http.Request, http.Response] =
Http.client
.methodBuilder("localhost:9001,localhost:9002")
.newService("client")
while(true) {
val request = http.Request(http.Method.Get, "/")
request.host = "www.scala-lang.org"
val response: Future[http.Response] = client(request)
println(Await.result(response))
Thread.sleep(50)
}
}
Finagle version:
libraryDependencies ++= Seq(
"com.twitter" %% "finagle-core" % "20.4.1",
"com.twitter" %% "finagle-http" % "20.4.1",
"com.twitter" %% "finagle-serversets" % "20.4.1"
)
I couldn't find a way to make the client not die in this situation and try to reconnect to the server when it is up again
Not sure if this exactly meets requirement, going by documentation 2 configurations seems applicable. By adding RetryBudget and FailureAccrualPolicy should make it close to your requirement. Hope following code will provide an idea.
val budget = RetryBudget(
ttl = 10.seconds,
minRetriesPerSec = 5,
percentCanRetry = 0.1
)
val client: Service[http.Request, http.Response] = Http.client
.methodBuilder("localhost:9001,localhost:9002")
.withRetryBudget(budget)
.withRetryBackoff(Backoff.exponentialJittered(2.seconds, 32.seconds))
.configured(Param(() => FailureAccrualPolicy.successRate(
requiredSuccessRate = 0.95,
window = 100,
markDeadFor = Backoff.const(10.seconds))))
.newService("client")