Another empty Typesafe Console - akka

I have a Java Akka application and have now added the needed configuration to integrate it with the Typesafe Console and monitor the system. My system contains several remote nodes and it runs fine but the Typesafe Console doesn't get/show anything.
The common.conf I'm using is the following:
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote.netty.tcp.port = 0
remote.log-remote-lifecycle-events = off
loggers = ["akka.event.slf4j.Slf4jLogger", "com.typesafe.atmos.trace.Slf4jTraceContextLogger"]
loglevel = "INFO"
remote {
transport-failure-detector {
heartbeat-interval = 3 s
threshold = 10.0
max-sample-size = 100
min-std-deviation = 200 ms
acceptable-heartbeat-pause = 5 s
}
watch-failure-detector {
heartbeat-interval = 3 s
threshold = 12.0
max-sample-size = 200
min-std-deviation = 200 ms
acceptable-heartbeat-pause = 7 s
unreachable-nodes-reaper-interval = 3 s
expected-response-after = 6 s
}
}
}
atmos {
trace {
enabled = true
node = ${HOSTNAME}
traceable {
"*" = on
}
sampling {
"*" = 1
}
}
}
I find a bit fishy that the configuration of atmos does not require any references to where the Typesafe Console is running.
The application.conf I'm using is the following:
MapReduceSystem {
include "common"
akka {
actor {
deployment {
/mapActor {
router = round-robin
nr-of-instances = ${MAPREDUCE_NUMBER_OF_JOBS}
target.nodes = ["akka.tcp://MapReduceSystem#olympus:2552", "akka.tcp://MapReduceNode#zeus:2552", "akka.tcp://MapReduceNode#hera:2552"]
}
/reduceActor {
remote = "akka.tcp://MapReduceSystem#olympus:2552"
router = round-robin
nr-of-instances = 1
}
/masterActor {
remote = "akka.tcp://MapReduceSystem#olympus:2552"
nr-of-instances = 1
}
}
}
remote.netty.tcp.port = 2552
remote.enabled-transports = ["akka.remote.netty.tcp"]
remote.netty.tcp.hostname = "olympus"
}
}
MapReduceNode {
include "common"
akka {
remote.netty.tcp.port = 2552
remote.enabled-transports = ["akka.remote.netty.tcp"]
remote.netty.tcp.hostname = ${HOSTNAME}
}
}
UPDATE:
atmos log shows only this:
azg#olympus:~/code/hpcmom/hpcmom-mapreduce$ sudo $TYPESAFE_CONSOLE_ROOT/bin/typesafe-console atmos
2013-11-20 15:10:46,922 INFO [akka.event.slf4j.Slf4jEventHandler] [] [] : Slf4jEventHandler started
2013-11-20 15:10:46,954 INFO [U] [ActorSystem(query)] [query-akka.actor.default-dispatcher-2] : *** No license available. Defaulting to in-memory persistence. ***
2013-11-20 15:10:47,169 INFO [akka.event.slf4j.Slf4jEventHandler] [] [] : Slf4jEventHandler started
2013-11-20 15:10:47,199 INFO [akka.event.slf4j.Slf4jEventHandler] [] [] : Slf4jEventHandler started
2013-11-20 15:10:47,508 INFO [akka://query/user/IO-HTTP/listener-0] [akka://query/user/IO-HTTP/listener-0] [query-akka.actor.default-dispatcher-12] : Bound to olympus/192.168.92.21:8660

Since you import the common config in the MapReduceSystem context Atmos will not be able to find the atmos configuration section. It expects the atmos configuration at the root level.
Try adding the atmos section directly to the application.conf file instead.

Related

Cannot make gRPC postman request to nestjs server

I've set up a nestjs server that handles gRPC requests. In order to do some ad-hoc debugging, I'm trying to use postman. However, whenever I try to send a request, postman returns the following error: Received RST_STREAM with code 2 triggered by internal client error: Protocol error.
This is my app.controller.ts file:
import { Metadata, ServerUnaryCall } from '#grpc/grpc-js';
import { Controller } from '#nestjs/common';
import { GrpcMethod } from '#nestjs/microservices';
import { BaseLoggingService } from './common/baseLogging.service';
import { CreateLogRequest, CreateLogResponse } from './generated/logs';
#Controller()
export class AppController {
constructor(private baseLoggingService: BaseLoggingService) {}
#GrpcMethod('LogService', 'CreateLog')
async createLog(
req: CreateLogRequest,
metadata: Metadata,
call: ServerUnaryCall<CreateLogRequest, CreateLogResponse>,
): Promise<CreateLogResponse> {
return await this.baseLoggingService.createLog(req);
}
}
The interfaces CreateLogRequest and CreateLogResponse are generated by protobuf-ts/plugin, and are based on the following .proto file:
/**
* Definitions of shared interfaces
**/
syntax = "proto3";
package logs;
enum LogLevel {
INFO = 0;
WARN = 1;
ERROR = 2;
DEBUG = 3;
}
message LogContext {
string sessionId = 1;
string requestId = 2;
string hostname = 3;
string podName = 4;
string grpcMethodName = 5;
uint32 durationMs = 6;
}
message ErrorData {
string name = 1;
string notificationCode = 2;
string stack = 3;
}
message CreateLogRequest {
LogLevel level = 1;
string service = 2;
int32 timestamp = 3;
string message = 4;
LogContext context = 5;
ErrorData errorData = 6;
}
message CreateLogResponse {
LogLevel level = 1;
string service = 2;
int32 code = 3;
}
service LogService {
rpc CreateLog (CreateLogRequest) returns (CreateLogResponse) {}
}
The server instance is running on a remote machine, so I am using ssh-tunneling to send the requests. Here is the postman request and response. There is no authentication in place.
I used server logs and the controller's createLog function does not get triggered at all when making the request. I even tried using grpcurl, which fails again, albeit for a differently inexplicable reason:
grpcurl -plaintext -d '{
"context": {
"durationMs": 4100079420,
"grpcMethodName": "magna ut commodo",
"hostname": "exercitation dolor",
"podName": "ad Duis non",
"requestId": "do",
"sessionId": "nostrud"
},
"errorData": {
"name": "nostrud enim Lorem consectetur",
"notificationCode": "in anim",
"stack": "incididunt"
},
"level": 0,
"message": "eu qui dolore laborum eiusmod",
"service": "sunt",
"timestamp": -499959849
}' localhost:6666 LogService/CreateLog
Failed to dial target host "localhost:6666": context deadline exceeded

Akka Cluster starding not able to register to Coordinator

I am trying to create an Akka Sharding Cluster. I want to use proxy only mode on one of the nodes just to route the message to the shard regions. I am getting the following Warning:
[WARN] [02/11/2019 17:04:17.819] [ClusterSystem-akka.actor.default-dispatcher-21] [akka.tcp://ClusterSystem#127.0.0.1:2555/system/sharding/ShardnameProxy] Trying to register to coordinator at [Some(ActorSelection[Anchor(akka.tcp://ClusterSystem#127.0.0.1:2551/), Path(/system/sharding/ShardnameCoordinator/singleton/coordinator)])], but no acknowledgement. Total [1] buffered messages.
**Main.java: ** Starts the cluster using the configuration from application.conf(code added latter)
object Main {
val shardName = "Shardname"
val role = "Master"
var shardingProbeLocalRegin: Option[ActorRef] = None
def main(args: Array[String]): Unit = {
val conf = ConfigFactory.load()
val system = ActorSystem("ClusterSystem",conf.getConfig("main"))
ClusterSharding(system).start(shardName,Test.props,ClusterShardingSettings(system),ShardDetails.extractEntityId,ShardDetails.extractShardId)
}
}
Test.java : Entity for the Sharding Cluster
object Test {
def props: Props = Props(classOf[Test])
class Test extends Actor {
val log = Logger.getLogger(getClass.getName)
override def receive = {
case msg: String =>
log.info("Message from " + sender().path.toString + " Message is " + msg)
sender() ! "Done"
}
}
}
MessageProducer.java(Proxy Only Mode) Message Producer sends a message to the Shard every second.
object MessageProducer {
var shardingProbeLocalRegin: Option[ActorRef] = None
object DoSharding
def prop:Props = Props(classOf[MessageProducer])
var numeric : Long = 0
def main(args: Array[String]): Unit = {
val conf = ConfigFactory.load
val system = ActorSystem("ClusterSystem",conf.getConfig("messgaeProducer"))
ClusterSharding(system).startProxy(Main.shardName,None,extractEntityId,extractShardId)
shardingProbeLocalRegin = Some(ClusterSharding(system).shardRegion(Main.shardName))
val actor = system.actorOf(Props[MessageProducer],"message")
}
}
class RemoteAddressExtensionImpl(system: ExtendedActorSystem) extends Extension {
def address = system.provider.getDefaultAddress
}
object RemoteAddressExtension extends ExtensionKey[RemoteAddressExtensionImpl]
class MessageProducer extends Actor{
val log = Logger.getLogger(getClass.getName)
override def preStart(): Unit = {
println("Starting "+self.path.address)
context.system.scheduler.schedule(10 seconds,1 second ,self,DoSharding)
}
override def receive = {
case DoSharding =>
log.info("sending message" + MessageProducer.numeric)
MessageProducer.shardingProbeLocalRegin.foreach(_ ! "" + (MessageProducer.numeric))
MessageProducer.numeric += 1
}
}
**application.conf: ** Configuration File
main {
akka {
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = on
netty.tcp {
hostname = "127.0.0.1"
port = 2551
}
}
cluster {
seed-nodes = [
"akka.tcp://ClusterSystem#127.0.0.1:2551"
]
sharding.state-store-mode = ddata
auto-down-unreachable-after = 1s
}
akka.extensions = ["akka.cluster.metrics.ClusterMetricsExtension", "akka.cluster.ddata.DistributedData"]
}
}
messgaeProducer {
akka {
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = on
netty.tcp {
hostname = "192.168.2.96"
port = 2554
}
}
cluster {
seed-nodes = [
"akka.tcp://ClusterSystem#127.0.0.1:2551"
//, "akka.tcp://ClusterSystem#127.0.0.1:2552"
]
sharding.state-store-mode = ddata
auto-down-unreachable-after = 1s
}
akka.extensions = ["akka.cluster.metrics.ClusterMetricsExtension", "akka.cluster.ddata.DistributedData"]
}
}
Am I doing anything wrong? Is there any other way to apply for this approach. My main aim is to avoid Single Point of failure for my cluster. If any node goes down then it should not affect any other state. Can anyone help me with this?
Is it solved?
If not, please check your akka.cluster configuration.
You have to set config like this. It works to me
for proxy
akka.cluster {
roles = ["Proxy"]
sharding {
role = "Master"
}
}
for master
akka.cluster {
roles = ["Master"]
sharding {
role = "Master"
}
}

How to make Play Framework WS use my SSLContext

I'm using Play 2.3.7 with Scala 2.11.4, Java 7. I want to use Play WS to connect to an HTTPS endpoint, that requires client to present its certificate. To do it I create my own SSLContext:
val sslContext = {
val keyStore = KeyStore.getInstance("pkcs12")
keyStore.load(new FileInputStream(clientKey), clientKeyPass.to[Array])
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
kmf.init(keyStore, clientKeyPass.to[Array])
val trustStore = KeyStore.getInstance("jks")
trustStore.load(new FileInputStream(trustStoreFile), trustStorePass.to[Array])
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
tmf.init(trustStore)
val ctx = SSLContext.getInstance("TLSv1.2")
ctx.init(kmf.getKeyManagers, tmf.getTrustManagers, new SecureRandom())
ctx
}
I know, that the SSLContext is valid, because I can use it with URLConnection successfully:
def urlConnection = Action {
val conn = new URL(url).openConnection()
conn.asInstanceOf[HttpsURLConnection].setSSLSocketFactory(sslContext.getSocketFactory)
conn.connect()
Ok(scala.io.Source.fromInputStream(conn.getInputStream).getLines().mkString("\n"))
}
But when I try one of two ways below I get java.nio.channels.ClosedChannelException.
def ning = Action.async {
val builder = new AsyncHttpClientConfig.Builder()
builder.setSSLContext(sslContext)
val client = new NingWSClient(builder.build())
client.url(url).get() map { _ => Ok("ok") }
}
def asyncHttpClient = Action {
val builder = new AsyncHttpClientConfig.Builder()
builder.setSSLContext(sslContext)
val httpClient = new AsyncHttpClient(builder.build())
httpClient.prepareGet(url).execute().get(10, TimeUnit.SECONDS)
Ok("ok")
}
I also get the same exception when I go after suggestion of Will Sargent and use NingAsyncHttpClientConfigBuilder with parsed config (note, that config references exactly the same values, the hand-crafted sslContext does).
def ningFromConfig = Action.async {
val config = play.api.Configuration(ConfigFactory.parseString(
s"""
|ws.ssl {
| keyManager = {
| stores = [
| { type: "PKCS12", path: "$clientKey", password: "$clientKeyPass" }
| ]
| }
| trustManager = {
| stores = [
| { type: "JKS", path: "$trustStoreFile", password: "$trustStorePass" },
| ]
| }
|}
|# Without this one I get InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
|ws.ssl.disabledKeyAlgorithms="RSA keySize < 1024"
""".stripMargin))
val parser = new DefaultWSConfigParser(config, play.api.Play.application.classloader)
val builder = new NingAsyncHttpClientConfigBuilder(parser.parse())
val client = new NingWSClient(builder.build())
client.url(url).get() map { _ => Ok("ok") }
}
How to make it work with Play WS?
You should use a client certificate from application.conf as defined in https://www.playframework.com/documentation/2.3.x/KeyStores and https://www.playframework.com/documentation/2.3.x/ExampleSSLConfig -- if you need to use a custom configuration, you should use the parser directly:
https://github.com/playframework/playframework/blob/2.3.x/framework/src/play-ws/src/test/scala/play/api/libs/ws/DefaultWSConfigParserSpec.scala#L14
to create a config, then the Ning builder:
https://github.com/playframework/playframework/blob/2.3.x/framework/src/play-ws/src/test/scala/play/api/libs/ws/ning/NingAsyncHttpClientConfigBuilderSpec.scala#L33
which will give you the AHCConfig object that you can pass in. There's examples in the "Using WSClient" section of https://www.playframework.com/documentation/2.3.x/ScalaWS.

akka cluster singleton proxy can not identify actor on none leader node

I was trying to build a two-node akka cluster,and both of the nodes are configured as seed node. At each node I create actor and locate it by these ways below:
akka {
//loglevel = "DEBUG"
log-config-on-start = on
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 0
}
}
cluster {
seed-nodes = [
"akka.tcp://ClusterSystem#127.0.0.1:2551",
"akka.tcp://ClusterSystem#127.0.0.1:2552"
]
roles = [
"transport"
]
auto-down = on
}
}
final String SINGLETON_GROUP = "client";
getContext().system().actorOf(
ClusterSingletonManager.defaultProps(
Props.create(ClientActor.class, channelActive.getCtx()),
loginMessage.getId(),
PoisonPill.getInstance(),
"transport"
), SINGLETON_GROUP
);
private ActorRef getActor(String id) {
ActorRef remoteActor = getContext().system().actorOf(
ClusterSingletonProxy.defaultProps("user/" + SINGLETON_GROUP + "/" + id,
"transport"));
return remoteActor;
}
what I expected is that I can create an actor at any node, and locate it everywhere as long as I got its singletonPath.
However, the result is : the getActor() only works at "leader" node, and can not identify at other nodes.
If I got wrong understanding about clusterSingleton ?

Run JavaExec task in background and then terminate when build completes

I'm trying to figure out how to launch a JavaExec task that spawns a Jetty server without blocking subsequent tasks. Also, I will need to terminate this server after the build completes. Any idea how I can do this?
I know the thread is from 2011, but I still stumbled across the problem. So here's a solution working with Gradle 2.14:
import java.util.concurrent.Callable
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class RunAsyncTask extends DefaultTask {
String taskToExecute = '<YourTask>'
#TaskAction
def startAsync() {
ExecutorService es = Executors.newSingleThreadExecutor()
es.submit({taskToExecute.execute()} as Callable)
}
}
task runRegistry(type: RunAsyncTask, dependsOn: build){
taskToExecute = '<NameOfYourTaskHere>'
}
I updated solution from #chrishuen because you cannot call execute on task anymore. Here is my working build.gradle
import java.time.LocalDateTime
import java.util.concurrent.Callable
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
group 'sk.bsmk'
version '1.0-SNAPSHOT'
apply plugin: 'java'
task wrapper(type: Wrapper) {
gradleVersion = '3.4'
}
class RunAsyncTask extends DefaultTask {
#TaskAction
def startAsync() {
ExecutorService es = Executors.newSingleThreadExecutor()
es.submit({
project.javaexec {
classpath = project.sourceSets.main.runtimeClasspath
main = "Main"
}
} as Callable)
}
}
task helloAsync(type: RunAsyncTask, dependsOn: compileJava) {
doLast {
println LocalDateTime.now().toString() + 'sleeping'
sleep(2 * 1000)
}
}
Hope this snippet will give you some insight on how it can be done.
You can used build listener closures to run code on build start/finish. However, for some reason, gradle.buildStarted closure does not work in milestone-3, so I have replaced it with gradle.taskGraph.whenReady which does the trick.
Then you can call the runJetty task using Task#execute() (Note, this API is not official and may disappear), and additionally, run it from an ExecutorService to get some asynchronous behaviour.
import java.util.concurrent.*
task myTask << {
println "Do usual tasks here"
}
task runJetty << {
print "Pretend we are running Jetty ..."
while(!stopJetty){
Thread.sleep(100)
}
println "Jetty Stopped."
}
stopJetty = false
es = Executors.newSingleThreadExecutor()
jettyFuture = null
//gradle.buildStarted { ... }
gradle.taskGraph.whenReady { g ->
jettyFuture = es.submit({ runJetty.execute() } as Callable)
}
gradle.buildFinished {
println "Stopping Jetty ... "
stopJetty = true
//This is optional. Could be useful when debugging.
try{
jettyFuture?.get()
}catch(ExecutionException e){
println "Error during Jetty execution: "
e.printStackTrace()
}
}
You can't do it with JavaExec; you'll have to write your own task.
Based on previous answers, here is my take:
abstract class RunAsyncTask extends DefaultTask {
#Input
abstract Property<FileCollection> getClasspath()
#Input
abstract Property<String> getMain()
#Input
abstract ListProperty<String> getArgs()
#TaskAction
def startAsync() {
// do get all the parameters before going asynch, otherwise it sometimes blocks
def cp = classpath.get().asPath
def m = main.get()
def a = args.get()
ExecutorService es = Executors.newSingleThreadExecutor()
es.submit({
def command = ["java", "-cp", cp, m] + a
ProcessBuilder builder = new ProcessBuilder(command.toList())
builder.redirectErrorStream(true)
builder.directory(project.projectDir)
Process process = builder.start()
InputStream stdout = process.getInputStream()
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout))
def line
while ((line = reader.readLine()) != null) {
println line
}
} as Callable)
}
}
task startServer(type: RunAsyncTask) {
classpath = ...
main = '...'
args = [...]
doLast {
// sleep 3 seconds to give the server time to startup
Thread.sleep(3000)
}
}