我在调用 Web 服务的 Play 2.0 Scala 文档中看到惯用方法是使用 Scala 的异步机制来调用 Web 服务。因此,如果我使用 Java 库从 S3 下载图像并上传到 Facebook 和 Twitter(restfb 和 twitter4j),这是否会导致资源使用效率极低(什么资源?)还是没有太大区别(或根本没有区别)?
如果它有所作为,我将如何制作类似以下异步的东西?有没有一种快速的方法,或者我必须从头开始编写库?
请注意,如果这在本次讨论中很重要,它将在 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?)这是一个大问题,因为只有一个线程,所以它阻塞了你的整个 Web 服务器。JVM 服务器是多线程的,因此您仍然可以为新请求提供服务。
- 您可以在将来轻松地包装整个事情,或者更细化地做,但这并不能真正为您带来任何好处,因为您调用的是相同的方法,所以您只是将等待从一个线程转移到另一个线程。
- 如果那些 Java 库提供异步方法,您可以在将来包装它们以获得异步的真正好处<-怎么办?. 否则,是的,您正在从头开始写作。
- 真的不知道在heroku上运行是否重要。一个测功机 == 一个同时请求吗?