2nd Generation Server Array:
This thing rocks. The 2nd Gen Server Array stripes and mirrors ones objects across multiple servers much like RAID. The user doesn't know or care where the bytes go. The difference is that this is part of your java heap being persistently scaled over an array. I was watching a test yesterday that showed 25,000 fully persistent WRITE transactions per second. This wasn't some rosy best case scenario testing only local reads for marketing. These transactions were 2k in size fully persistent striped over 8 servers. The load that can be handled thus far has been linear. The only thing one changes to use the Server Array instead of a single server is listing the new server groups in the configuration file.
Below is a sample config for a mirrored and striped array. The topology is defined between lines 54 and 77 as mirror groups and stripes. Everything else will be the same as using regular Terracotta.
Below is a sample config for a mirrored and striped array. The topology is defined between lines 54 and 77 as mirror groups and stripes. Everything else will be the same as using regular Terracotta.
1 <application>
1
2 <?xml version="1.0" encoding="UTF-8"?>
3
4 <tc:tc-config xmlns:tc="http://www.terracotta.org/config">
5 <tc-properties>
6 <property name="l2.healthcheck.l1.ping.interval" value="10000"/>
7 <property name="l2.healthcheck.l1.ping.idletime" value="10000"/>
8 <property name="l2.healthcheck.l1.ping.probes" value="20"/>
9 </tc-properties>
10 <system>
11 <configuration-model>production</configuration-model>
12 </system>
13 <servers>
14 <server host="eng01" name="server1">
15 <logs>%(user.home)/local1/tc-runtime/test-app/server-logs</logs>
16 <statistics>%(user.home)/local1/tc-runtime/test-app/server-stats</statistics>
17 <dso-port>9510</dso-port>
18 <jmx-port>9520</jmx-port>
19 <l2-group-port>9530</l2-group-port>
20 <data>%(user.home)/remote/tc-runtime/test-app/server-data</data>
21 <dso>
22 <client-reconnect-window>100</client-reconnect-window>
23 <persistence>
24 <mode>permanent-store</mode>
25 </persistence>
26 <garbage-collection>
27 <enabled>true</enabled>
28 <verbose>true</verbose>
29 <interval>180</interval>
30 </garbage-collection>
31 </dso>
32 </server>
33 <server host="eng02" name="server2">
34 <logs>%(user.home)/local1/tc-runtime/test-app/server-logs</logs>
35 <statistics>%(user.home)/local1/tc-runtime/test-app/server-stats</statistics>
36 <dso-port>9510</dso-port>
37 <jmx-port>9520</jmx-port>
38 <l2-group-port>9530</l2-group-port>
39 <data>%(user.home)/remote/tc-runtime/test-app/server-data</data>
40 <dso>
41 <client-reconnect-window>100</client-reconnect-window>
42 <persistence>
43 <mode>permanent-store</mode>
44 </persistence>
45 <garbage-collection>
46 <enabled>true</enabled>
47 <verbose>true</verbose>
48 <interval>180</interval>
49 </garbage-collection>
50 </dso>
51 </server>
52
53
54 <mirror-groups>
55 <mirror-group>
56 <members>
57 <member>server1</member>
58 </members>
59 <ha>
60 <mode>networked-active-passive</mode>
61 <networked-active-passive>
62 <election-time>1</election-time>
63 </networked-active-passive>
64 </ha>
65 </mirror-group>
66 <mirror-group>
67 <members>
68 <member>server2</member>
69 </members>
70 <ha>
71 <mode>networked-active-passive</mode>
72 <networked-active-passive>
73 <election-time>1</election-time>
74 </networked-active-passive>
75 </ha>
76 </mirror-group>
77 </mirror-groups>
78 <ha>
79 <mode>networked-active-passive</mode>
80 <networked-active-passive>
81 <election-time>1</election-time>
82 </networked-active-passive>
83 </ha>
84 </servers>
85 </tc:tc-config>
Terracotta Topology API
In Terracotta 3.0 we have added a Terracotta Topology API. This is used to monitor and take action on
things like nodes joining and leaving, who am I, and is this object local. In the Terracotta Config
one needs to specify where to inject the DsoCluster topology object:
2 <dso>
3 <injected-instances>
4 <injected-field>
5 <field-name>org.sharrissf.sample.ClusterAPISample.cluster</field-name>
6 </injected-field>
7 </injected-instances>
Below is some sample code that takes advantage of the Topology API to find out what nodes are entering
and leaving the cluster and what my node ID is. For a fully working example of how to use this API check out the
chatter demo in the kit.
1 package org.sharrissf.sample;
2
3 import com.tc.cluster.DsoCluster;
4 import com.tc.cluster.DsoClusterEvent;
5 import com.tc.cluster.DsoClusterListener;
6
7 public class ClusterAPISample implements DsoClusterListener {
8
9 private DsoCluster cluster;
10
11 public ClusterAPISample() {
12 System.out
13 .println("***** Hello, I'm node: " + cluster.getCurrentNode());
14 cluster.addClusterListener(this);
15 try {
16 if ("ClientID[0]".equals(cluster.getCurrentNode().getId()))
17 Thread.sleep(2000);
18 else
19 Thread.sleep(10000);
20 } catch (InterruptedException e) {
21 // TODO Auto-generated catch block
22 e.printStackTrace();
23 }
24 }
25
26 public void nodeJoined(DsoClusterEvent event) {
27 System.out.println("***** NODE JOINED: " + event.getNode());
28 }
29
30 public void nodeLeft(DsoClusterEvent event) {
31 System.out.println("***** NODE LEFT: " + event.getNode());
32 }
33
34 public void operationsDisabled(DsoClusterEvent event) {
35 System.out.println("***** OPERATIONS DISABLED: " + event.getNode());
36 }
37
38 public void operationsEnabled(DsoClusterEvent event) {
39 System.out.println("***** OPERATIONS ENABLED: " + event.getNode());
40 }
41
42 public final static void main(String[] args) throws Exception {
43 new ClusterAPISample();
44 }
45 }
I put the sleeps in so that one node prints out when the other node leaves if you run this twice.
I'll highlight some of the other new stuff in a follow on post.