Web サービスを呼び出すための Play 2.0 Scala docを見ると、慣用的なアプローチは Scala の非同期メカニズムを使用して Web サービスを呼び出すことです。たとえば、S3 から画像をダウンロードし、Facebook や Twitter (restfb と twitter4j) にアップロードするために Java ライブラリを使用している場合、これはリソース (どのリソース?) の非常に非効率的な使用になりますか、それとも大きな違いはありませんか? (またはまったく違いはありません)?
それが違いを生む場合、次の非同期のようなものを作成するにはどうすればよいですか? 簡単な方法はありますか、それともライブラリを最初から作成する必要がありますか?
この議論で重要な場合、これはherokuで実行されることに注意してください。
def tweetJpeg = Action(parse.urlFormEncoded) { request =>
val form = request.body
val folder = form("folder").head
val mediaType = form("type").head
val photo = form("photo").head
val path = folder + "/" + mediaType + "/" + photo
val config = Play.current.configuration;
val awsAccessKey = config.getString("awsAccessKey").get
val awsSecretKey = config.getString("awsSecretKey").get
val awsBucket = config.getString("awsBucket").get
val awsCred = new BasicAWSCredentials(awsAccessKey, awsSecretKey)
val amazonS3Client = new AmazonS3Client(awsCred)
val obj = amazonS3Client.getObject(awsBucket, path)
val stream = obj.getObjectContent()
val twitterKey = config.getString("twitterKey").get
val twitterSecret = config.getString("twitterSecret").get
val token = form("token").head
val secret = form("secret").head
val tweet = form("tweet").head
val cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey(twitterKey)
.setOAuthConsumerSecret(twitterSecret)
.setOAuthAccessToken(token)
.setOAuthAccessTokenSecret(secret)
val tf = new TwitterFactory(cb.build())
val twitter = tf.getInstance()
val status = new StatusUpdate(tweet)
status.media(photo, stream)
val twitResp = twitter.updateStatus(status)
Logger.info("Tweeted " + twitResp.getText())
Ok("Tweeted " + twitResp.getText())
}
def facebookJpeg = Action(parse.urlFormEncoded) { request =>
val form = request.body
val folder = form("folder").head
val mediaType = form("type").head
val photo = form("photo").head
val path = folder + "/" + mediaType + "/" + photo
val config = Play.current.configuration;
val awsAccessKey = config.getString("awsAccessKey").get
val awsSecretKey = config.getString("awsSecretKey").get
val awsBucket = config.getString("awsBucket").get
val awsCred = new BasicAWSCredentials(awsAccessKey, awsSecretKey)
val amazonS3Client = new AmazonS3Client(awsCred)
val obj = amazonS3Client.getObject(awsBucket, path)
val stream = obj.getObjectContent()
val token = form("token").head
val msg = form("msg").head
val facebookClient = new DefaultFacebookClient(token)
val fbClass = classOf[FacebookType]
val param = com.restfb.Parameter.`with`("message", msg)
val attachment = com.restfb.BinaryAttachment`with`(photo + ".png", stream)
val fbResp = facebookClient.publish("me/photos", fbClass, attachment, param)
Logger.info("Posted " + fbResp.toString())
Ok("Posted " + fbResp.toString())
}
私の推測の試み:
- はい、非同期で行う方が良いです。すべてを同期的に行うと、スレッドが拘束されます。スレッドはメモリを大量に消費するため、サーバーは非常に多くしか使用できません。待機しているものが多いほど、サーバーが応答できるリクエストは少なくなります。
- いいえ、それは大きな問題ではありません。node.js (および Rails? Django?) では、スレッドが 1 つしかなく、Web サーバー全体がブロックされるため、これは大きな問題です。JVM サーバーはマルチスレッド化されているため、引き続き新しい要求を処理できます。
- 後で全体を簡単にラップしたり、より細かく実行したりできますが、同じメソッドを呼び出しているため、実際には何も得られません。つまり、あるスレッドから別のスレッドへの待機をシフトしているだけです。
- これらの Java ライブラリが非同期メソッドを提供している場合は、将来それらをラップして、非同期の真の利点を得ることができます<-どうすればよいですか? . そうでなければ、あなたはゼロから書くことを見ています。
- heroku での実行が重要かどうかはよくわかりません。1つのdyno == 1つの同時リクエストですか?