我是PostgreSQL的新手。在尝试Akka Persistence时,我想使用它。我正在使用以下命令通过Docker运行PostgreSQL:
docker run --name postgres -p 5432:5432 -e POSTGRES_USER=test -e POSTGRES_PASSWORD=test -e POSTGRES_DB=testing postgres:11
这是我得到的输出:
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".
Data page checksums are disabled.
fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
Success. You can now start the database server using:
pg_ctl -D /var/lib/postgresql/data -l logfile start
WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
waiting for server to start....2018-11-01 12:34:27.923 UTC [44] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2018-11-01 12:34:27.961 UTC [45] LOG: database system was shut down at 2018-11-01 12:34:27 UTC
2018-11-01 12:34:27.981 UTC [44] LOG: database system is ready to accept connections
done
server started
CREATE DATABASE
/usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
waiting for server to shut down....2018-11-01 12:34:28.293 UTC [44] LOG: received fast shutdown request
2018-11-01 12:34:28.294 UTC [44] LOG: aborting any active transactions
2018-11-01 12:34:28.296 UTC [44] LOG: background worker "logical replication launcher" (PID 51) exited with exit code 1
2018-11-01 12:34:28.297 UTC [46] LOG: shutting down
2018-11-01 12:34:28.336 UTC [44] LOG: database system is shut down
done
server stopped
PostgreSQL init process complete; ready for start up.
2018-11-01 12:34:28.404 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2018-11-01 12:34:28.404 UTC [1] LOG: listening on IPv6 address "::", port 5432
2018-11-01 12:34:28.422 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2018-11-01 12:34:28.454 UTC [62] LOG: database system was shut down at 2018-11-01 12:34:28 UTC
2018-11-01 12:34:28.464 UTC [1] LOG: database system is ready to accept connections
以下文件是用于Akka Persistence的类:
MyActor.java
public class MyActor extends AbstractPersistentActor {
private ExampleState state = new ExampleState();
private int snapshotInterval = 1000;
public int getNumEvents() {
return state.size();
}
@Override
public String persistenceId() {
return "my-persistent-actor";
}
@Override
public Receive createReceiveRecover() {
return receiveBuilder()
.match(Evt.class, state::update)
.match(SnapshotOffer.class, ss -> state = (ExampleState) ss.snapshot())
.build();
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Cmd.class, c -> {
final String data = c.getData();
final Evt evt = new Evt(data + "-" + getNumEvents());
persist(evt, (Evt e) -> {
state.update(e);
getContext().getSystem().eventStream().publish(e);
if (lastSequenceNr() % snapshotInterval == 0 && lastSequenceNr() != 0)
// IMPORTANT: create a copy of snapshot because ExampleState is mutable
saveSnapshot(state.copy());
});
})
.matchEquals("print", s -> System.out.println(state))
.build();
}
// Inner classes
class ExampleState implements Serializable {
private static final long serialVersionUID = 1L;
private final ArrayList<String> events;
public ExampleState() {
this(new ArrayList<>());
}
public ExampleState(ArrayList<String> events) {
this.events = events;
}
public ExampleState copy() {
return new ExampleState(new ArrayList<>(events));
}
public void update(Evt evt) {
events.add(evt.getData());
}
public int size() {
return events.size();
}
@Override
public String toString() {
return events.toString();
}
}
}
Evt.java
public class Evt implements Serializable {
private static final long serialVersionUID = 1L;
private final String data;
public Evt(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
Cmd.java
public class Cmd implements Serializable {
private static final long serialVersionUID = 1L;
private final String data;
public Cmd(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
application.conf
akka {
persistence {
journal {
plugin = "jdbc-journal"
// Enable the line below to automatically start the journal when the actorsystem is started
auto-start-journals = ["jdbc-journal"]
}
snapshot-store {
plugin = "jdbc-snapshot-store"
// Enable the line below to automatically start the snapshot-store when the actorsystem is started
auto-start-snapshot-stores = ["jdbc-snapshot-store"]
local.dir = "target/snapshots"
}
}
}
jdbc-journal {
slick = ${slick}
}
# the akka-persistence-snapshot-store in use
jdbc-snapshot-store {
slick = ${slick}
}
# the akka-persistence-query provider in use
jdbc-read-journal {
slick = ${slick}
}
slick {
profile = "slick.jdbc.PostgresProfile$"
db {
host = "localhost"
url = "jdbc:postgresql://"${slick.db.host}":5432/testing?reWriteBatchedInserts=true"
user = "test"
password = "test"
driver = "org.postgresql.Driver"
numThreads = 5
maxConnections = 5
minConnections = 1
}
}
然后我尝试在main方法中向MyActor发送消息。这将向角色发送一个Cmd消息。然后,参与者将把该消息作为事件持久保存到PostgreSQL数据库中。
public class App {
public static void main(String[] args) throws IOException {
ActorSystem system = ActorSystem.create();
ActorRef childActor = system.actorOf(Props.create(MyActor.class), "child-actor");
for (int i = 0; i < 20; i++) {
childActor.tell(new Cmd("testCommand " + i), ActorRef.noSender());
}
try {
System.in.read();
} finally {
system.terminate();
}
}
}
运行上面的main方法时,在PostgreSQL的终端窗口中获得以下输出:
2018-11-01 12:53:10.394 UTC [88] ERROR: relation "snapshot" does not exist at character 72
2018-11-01 12:53:10.394 UTC [88] STATEMENT: select "persistence_id", "sequence_number", "created", "snapshot" from "snapshot" where "persistence_id" = $1 order by "sequence_number" desc limit 1
然后在Akka的终端窗口中获得以下输出:
[WARN] [11/01/2018 12:53:09.799] [main] [ManifestInfo(akka://default)] Detected possible incompatible versions on the classpath. Please note that a given Akka version MUST be the same across all modules of Akka that you are using, e.g. if you use [2.5.17] all other modules that are released together MUST be of the same version. Make sure you're using a compatible set of libraries.Possibly conflicting versions [2.5.17, 2.5.13] in libraries [akka-persistence:2.5.17, akka-protobuf:2.5.17, akka-persistence-query:2.5.13, akka-actor:2.5.17, akka-stream:2.5.13]
[INFO] [11/01/2018 12:53:09.867] [default-akka.actor.default-dispatcher-2] [akka.persistence.Persistence(akka://default)] Auto-starting journal plugin `jdbc-journal`
[INFO] [11/01/2018 12:53:09.894] [default-akka.actor.default-dispatcher-2] [akka.persistence.Persistence(akka://default)] Auto-starting snapshot store `jdbc-snapshot-store`
[default-akka.persistence.dispatchers.default-plugin-dispatcher-6] INFO com.zaxxer.hikari.HikariDataSource - slick.db - Started.
[default-akka.persistence.dispatchers.default-plugin-dispatcher-7] INFO com.zaxxer.hikari.HikariDataSource - slick.db - Started.
[ERROR] [11/01/2018 12:53:10.436] [default-akka.actor.default-dispatcher-5] [akka://default/user/child-actor] Persistence failure when replaying events for persistenceId [my-persistent-actor]. Last known sequence number [0]
org.postgresql.util.PSQLException: ERROR: relation "snapshot" does not exist
Position: 72
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:143)
at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:132)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java)
at slick.jdbc.StatementInvoker.results(StatementInvoker.scala:38)
at slick.jdbc.StatementInvoker.iteratorTo(StatementInvoker.scala:21)
at slick.jdbc.Invoker.foreach(Invoker.scala:47)
at slick.jdbc.Invoker.foreach$(Invoker.scala:46)
at slick.jdbc.StatementInvoker.foreach(StatementInvoker.scala:15)
at slick.jdbc.StreamingInvokerAction.run(StreamingInvokerAction.scala:22)
at slick.jdbc.StreamingInvokerAction.run$(StreamingInvokerAction.scala:20)
at slick.jdbc.JdbcActionComponent$QueryActionExtensionMethodsImpl$$anon$1.run(JdbcActionComponent.scala:216)
at slick.jdbc.JdbcActionComponent$QueryActionExtensionMethodsImpl$$anon$1.run(JdbcActionComponent.scala:216)
at slick.basic.BasicBackend$DatabaseDef$$anon$2.liftedTree1$1(BasicBackend.scala:275)
at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:275)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
[INFO] [11/01/2018 12:53:10.446] [default-akka.actor.default-dispatcher-2] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [1] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.446] [default-akka.actor.default-dispatcher-2] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [2] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.446] [default-akka.actor.default-dispatcher-2] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [3] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.446] [default-akka.actor.default-dispatcher-2] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [4] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.446] [default-akka.actor.default-dispatcher-2] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [5] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.446] [default-akka.actor.default-dispatcher-4] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [6] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.446] [default-akka.actor.default-dispatcher-4] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [7] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.447] [default-akka.actor.default-dispatcher-4] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [8] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.447] [default-akka.actor.default-dispatcher-4] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [9] dead letters encountered. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [11/01/2018 12:53:10.447] [default-akka.actor.default-dispatcher-4] [akka://default/user/child-actor] Message [Cmd] without sender to Actor[akka://default/user/child-actor#-1082926238] was not delivered. [10] dead letters encountered, no more dead letters will be logged. If this is not an expected behavior, then [Actor[akka://default/user/child-actor#-1082926238]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.