在我写这篇文章的时候,Play Framework的版本是v2.6.0-M4.由于Netty冲突,框架的v2.5版本难以使用gRPC(请参阅此stackoverflow答案).
我开始研究gRPC和protobufs.已经从Play Framework 2.5> 2.6.0-M4移植了一个项目,以期实际发布.目前我对gRPC的整合有一些疑问.我想知道如何让gRPC服务器与Play Framework很好地协同工作.我知道v2.6切换到Akka HTTP服务器而不是Netty,而我grpc-netty在sbt中使用依赖,所以也许我必须再次将项目切换到Netty(这里是如何).
出于测试目的,我创建了一个快速而脏的GrpcServer.scala类,它启动了一个带有GrpcServer监听的线程.我设法用gRPC 添加ScalaPB并生成/编译我的protobufs.它非常适合与小型测试NodeJS应用程序通信,但我必须独立于主项目启动此服务器应用程序:
private def start(): Unit = {
server = ServerBuilder.forPort(GrpcServer.port).addService(GreeterGrpc.bindService(new GreeterImpl, executionContext)).build.start
GrpcServer.logger.info("Server started, listening on " + GrpcServer.port)
sys.addShutdownHook {
System.err.println("*** shutting down gRPC server")
self.stop()
System.err.println("*** server shut down")
}
}
Run Code Online (Sandbox Code Playgroud)
现在,对于Play Framework v2.6中的真正集成,我正在寻找建议.这是我可以做的一些事情:
有关清洁集成的任何提示/想法都很有帮助,因为除了以前的2.5版本中存在问题之外,没有太多关于Play Framework和gRPC的信息.
问题标题可能不那么有用,因为我正在尝试实现各种功能.我想根据他发送的标题授权调用者,并将此信息传播给gRPC方法处理程序.问题在于授权过程的异步性质.我最终得到了这个:
case class AsyncContextawareInterceptor[A](
f: Metadata ? Future[Either[Status, (Context.Key[A], A)]]
)(implicit val system: ActorSystem)
extends ServerInterceptor
with AnyLogging {
import system.dispatcher
sealed trait Msg
case object HalfClose extends Msg
case object Cancel extends Msg
case object Complete extends Msg
case object Ready extends Msg
case class Message[T](msg: T) extends Msg
override def interceptCall[ReqT, RespT](call: ServerCall[ReqT, RespT],
headers: Metadata,
next: ServerCallHandler[ReqT, RespT]): ServerCall.Listener[ReqT] =
new ServerCall.Listener[ReqT] {
private val stash = new java.util.concurrent.ConcurrentLinkedQueue[Msg]()
private var interceptor: Option[ServerCall.Listener[ReqT]] = None
private def …Run Code Online (Sandbox Code Playgroud) 我正在使用ScalaPB来编译我的Scala案例类,以便序列化我的protobuf消息.
我有一个.proto包含以下消息的文件:
message WrapperMessage {
oneof msg {
Login login = 1;
Register register = 2;
}
}
message Login {
required string email = 1;
required string password = 2;
}
message Register {
required string email = 1;
required string password = 2;
optional string firstName = 3;
optional string lastName = 4;
}
Run Code Online (Sandbox Code Playgroud)
我怎么创建我WrapperMessage知道我想在Login里面放一条消息msg?
val login = Login(email = "test@example.com", password = "testpass")
val wrapperMessage = WrapperMessage(???)
val wrapperMessageBytes …Run Code Online (Sandbox Code Playgroud) 我想从测试目录中的 protobuf 文件生成代码。
project/test/protobuf/myproto.proto
Run Code Online (Sandbox Code Playgroud)
这是行不通的。
PB.targets in Test := Seq(
scalapb.gen() -> (sourceManaged in Test).value
)
Run Code Online (Sandbox Code Playgroud)
看起来 scalapb 只在 main/protobuf 目录中生成 protos 文件。
我在 scala/java 中找不到服务器端访问 grpc 请求上下文的任何示例(使用 scalapb / grpc.io)。我可以在golang中找到很多例子。我发现了一些 akka grpc 但我使用的是 scalapb 和 grpc.io
如果有人知道 github 中使用它的存储库或者可以布局访问它所需的步骤,那将非常感谢您
我的sbt中有多个子项目,一个是服务器(基于playframework),另一个是clientside(scala.js),第三个是protobuf(scalapb)形式的两者之间的通信.
现在,这是我的build.sbt:
lazy val generalSettings = Seq(
organization := "tld.awesomeness",
version := "0.0.1",
scalaVersion := "2.12.1"
)
val CrossDependencies = new
{
val scalaTest = "org.scalatest" %% "scalatest" % "3.0.1" % "test"
val scalactic = "org.scalactic" %% "scalactic" % "3.0.1"
val scalaTags = "com.lihaoyi" %% "scalatags" % "0.6.2"
}
lazy val proto = (project in file("modules/proto"))
.settings(generalSettings: _*)
.settings(
PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
),
// If you need scalapb/scalapb.proto or anything from …Run Code Online (Sandbox Code Playgroud) 我如何告诉ScalaPB它应该.proto从Internet上获取依赖项,例如
google/api/annotations.proto来自https://github.com/googleapis/googleapis/tree/master/google/api
背景:
目的是通过gRPC从Scala中读取etcd v3 API。
我.proto从他们的项目中选择了etcd的特定文件,并放置在我的文件下面。有用。但是,依赖关系开始深入运行,必须有更好的方法。
https://github.com/googleapis/googleapis/tree/master/google/api
我希望向 sbt 添加一个自定义源生成器,并将它与 Scala 协议缓冲区生成器 scalapb 一起使用。每个都是独立工作的。但是,当两者结合时,项目在清理后第一次无法编译。如果我再次运行编译,它会成功。
name := "Foo root project"
scalaVersion in ThisBuild:= "2.12.1"
sourceGenerators in Compile += Def.task {
val file = (sourceManaged in Compile).value / "demo" / "Test.scala"
IO.write(file, """object Test extends App { println("Hi") }""")
Seq(file)
}.taskValue
PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
)
Run Code Online (Sandbox Code Playgroud)
错误信息:
[error] source file '/ ... /target/scala-2.12/src_managed/main/demo/Test.scala' could not be found
[error] one error found
[error] (compile:compileIncremental) Compilation failed
Run Code Online (Sandbox Code Playgroud)
要重现此错误,您至少需要在 src/main/protobuf 中有一个 proto 文件。
让我感到困惑的是两个源生成器,我的自定义任务和 scalapb 会发生冲突。他们不应该都写入 …
我想将 ByteArray 转换为字符串,然后将字符串转换为 ByteArray,但是在转换时值发生了变化。有人帮助解决这个问题。
人.proto:
syntax = "proto3";
message Person{
string name = 1;
int32 age = 2;
}
Run Code Online (Sandbox Code Playgroud)
sbt 编译后,它给出案例类 Person (编译时由 google protobuf 创建)
我的主课:
val newPerson = Person(
name = "John Cena",
age = 44 //output
)
println(newPerson.toByteArray) //[B@50da041d
val l = newPerson.toByteArray.toString
println(l) //[B@7709e969
val l1 = l.getBytes
println(l1) //[B@f44b405
Run Code Online (Sandbox Code Playgroud)
为什么价值观改变了?如何正确转换??