{"id":2768,"date":"2021-05-10T09:00:20","date_gmt":"2021-05-10T16:00:20","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=2768"},"modified":"2022-01-12T05:23:50","modified_gmt":"2022-01-12T13:23:50","slug":"cassandra-api-java","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/cassandra-api-java\/","title":{"rendered":"Cassandra API Recommendations for Java"},"content":{"rendered":"<p>The <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/cassandra-introductio\" target=\"_blank\" rel=\"noopener\">Cassandra API<\/a> lets you have the maintenance and <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/manage-scale-cassandra\" target=\"_blank\" rel=\"noopener\">elasticity<\/a> benefits of a powerful cloud-native database platform like <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/introduction\" target=\"_blank\" rel=\"noopener\">Azure Cosmos DB<\/a>, while still being able to consume the programmability layer of one of the most popular and widely used open-source databases: <a href=\"https:\/\/cassandra.apache.org\/\" target=\"_blank\" rel=\"noopener\">Apache Cassandra<\/a>!<\/p>\n<p>You can communicate with Cassandra API through any CQL Binary v4 wire protocol compliant open-source Apache Cassandra client driver. While you should not need to make any substantial code changes to existing apps using Apache Cassandra, there are some approaches and settings that we recommend for Cassandra API in Cosmos DB that will improve the experience.<\/p>\n<p>In this blog we are going to be focusing on Java, specifically <a href=\"https:\/\/github.com\/datastax\/java-driver\/tree\/4.x\" target=\"_blank\" rel=\"noopener\">version 4<\/a> of the Cassandra client driver for Java. We have created an <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/tree\/release\/java-driver-4\/1.0.0\" target=\"_blank\" rel=\"noopener\">extension<\/a> that you can implement without any code changes (just update pom.xml and application.conf) for a better overall experience. You may also want to try out this <a href=\"https:\/\/github.com\/Azure-Samples\/azure-cosmos-cassandra-extensions-java-sample-v4\">code sample<\/a> which walks through an implementation of this extension, specifically to illustrate the <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/blob\/release\/java-driver-4\/0.1.0-beta.1\/package\/src\/main\/java\/com\/azure\/cosmos\/cassandra\/CosmosRetryPolicy.java\">retry policy<\/a> and <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/blob\/release\/java-driver-4\/0.1.0-beta.1\/package\/src\/main\/java\/com\/azure\/cosmos\/cassandra\/CosmosLoadBalancingPolicy.java\">load balancing policy<\/a>. When you take a dependency on the <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\">extension<\/a>, the following settings and policies are applied within it\u2019s <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/blob\/release\/java-driver-4\/1.0.0\/driver-4\/src\/main\/resources\/reference.conf\" target=\"_blank\" rel=\"noopener\">reference.conf<\/a> file (you can also override these settings in <a href=\"https:\/\/github.com\/Azure-Samples\/azure-cosmos-cassandra-extensions-java-sample-v4\/blob\/main\/src\/main\/resources\/application.conf\" target=\"_blank\" rel=\"noopener\">application.conf<\/a>). In this blog we\u2019ll talk you through these settings, why they are recommended, and in what circumstances you may want to override them.<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-size: 18pt;\"><strong>Authentication<\/strong><\/span><\/h2>\n<p>PlainTextAuthProvider is used by default. This is because the Cosmos DB Cassandra API requires authentication, and uses plain text authentication.<\/p>\n<pre><code>    auth-provider {\r\n      class = PlainTextAuthProvider\r\n    }<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-size: 18pt;\"><strong>Connection<\/strong><\/span><\/h2>\n<p>Cosmos DB load-balances requests against a large number of backend nodes. The default settings in the extension for local and remote node sizes work well in development, test, and low-volume production or staging environments. However, you should increase these values (i.e. override them within an <a href=\"https:\/\/github.com\/Azure-Samples\/azure-cosmos-cassandra-extensions-java-sample-v4\/blob\/master\/java-examples\/src\/main\/resources\/application.conf\" target=\"_blank\" rel=\"noopener\">application.conf<\/a> file) based on the <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/request-units\" target=\"_blank\" rel=\"noopener\">Request Units (RUs)<\/a> provisioned for your database. See table below for suggested settings depending on the amount of throughput provisioned:<\/p>\n<table style=\"border-collapse: collapse; width: 100%; height: 81px;\">\n<tbody>\n<tr style=\"height: 27px;\">\n<td style=\"width: 33.3333%; height: 27px;\">Request Units (RUs)<\/td>\n<td style=\"width: 33.3333%; height: 27px;\">local.size<\/td>\n<td style=\"width: 33.3333%; height: 27px;\">remote.size<\/td>\n<\/tr>\n<tr style=\"height: 27px;\">\n<td style=\"width: 33.3333%; height: 27px;\">100,000<\/td>\n<td style=\"width: 33.3333%; height: 27px;\">50-100<\/td>\n<td style=\"width: 33.3333%; height: 27px;\">50-100<\/td>\n<\/tr>\n<tr style=\"height: 27px;\">\n<td style=\"width: 33.3333%; height: 27px;\">200,000+<\/td>\n<td style=\"width: 33.3333%; height: 27px;\">100<\/td>\n<td style=\"width: 33.3333%; height: 27px;\">100<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>    connection {\r\n      pool {\r\n        local {\r\n          size = 10\r\n        }\r\n        remote {\r\n          size = 10\r\n        }\r\n      }\r\n    }<\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-size: 18pt;\"><strong>Token map<\/strong><\/span><\/h2>\n<p>Token maps are disabled because they are not relevant to routing when the v4 Java Driver is used to access a Cosmos DB Cassandra instance.<\/p>\n<pre><code>    metadata {\r\n      token-map {\r\n        enabled = false\r\n      }\r\n    }<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-size: 18pt;\"><strong>Reconnection Policy<\/strong><\/span><\/h2>\n<p>The Java v4 driver provides two implementations out-of-the-box: <code>ExponentialReconnectionPolicy<\/code> and <code>ConstantReconnectionPolicy<\/code>. <code>ExponentialReconnectionPolicy<\/code> is the default policy. However, we recommend <code>ConstantReconnectionPolicy<\/code> for Cassandra API, with a <code>base-delay<\/code> of 2 seconds:<\/p>\n<pre><code>    reconnection-policy {\r\n      class = ConstantReconnectionPolicy\r\n      base-delay = 2 second\r\n    }<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-size: 18pt;\"><strong>Retry Policy<\/strong><\/span><\/h2>\n<p>The retry policy handles errors such as <code>OverLoadedException<\/code> (which may occur due to <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/manage-scale-cassandra#handling-rate-limiting-429-errors\" target=\"_blank\" rel=\"noopener\">rate limiting<\/a>), and uses an exponential growing back-off scheme for retries. The time between retries is increased by a growing back off time (default: 1000 ms) on each retry, unless <code>maxRetryCount<\/code> is <code>-1<\/code>, in which case it backs off with a fixed duration.<\/p>\n<p>The default retry policy in the Java Driver does not handle this exception, which is why we have prepared this custom policy for Cassandra API. It is important to handle rate limiting in Azure Cosmos DB to prevent errors when <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/set-throughput\" target=\"_blank\" rel=\"noopener\">provisioned throughput<\/a> has been exhausted. The parameters for the retry policy are defined within <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/blob\/release\/java-driver-4\/1.0.0\/driver-4\/src\/main\/resources\/reference.conf\" target=\"_blank\" rel=\"noopener\">reference.conf<\/a> of the Cosmos DB <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/tree\/release\/java-driver-4\/1.0.0\" target=\"_blank\" rel=\"noopener\">extension<\/a> for Cassandra API, see below:<\/p>\n<pre><code>    retry-policy {\r\n      class = com.azure.cosmos.cassandra.CosmosRetryPolicy\r\n      max-retries = 5              \r\n      fixed-backoff-time = 5000    \r\n      growing-backoff-time = 1000  \r\n    }<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-size: 18pt;\"><strong>SSL Connection<\/strong><\/span><\/h2>\n<p>The DefaultSslEngineFactory is used by default. This is because Cosmos Cassandra API requires SSL:<\/p>\n<pre>    ssl-engine-factory {\r\n      class = DefaultSslEngineFactory\r\n    }<\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-size: 18pt;\"><strong>Load balancing policy<\/strong><\/span><\/h2>\n<p>The default load balancing policy in the v4 driver inhibits application-level failover, and specifying a single local datacenter for the CqlSession object is required by the policy. The native Apache Cassandra database is a multi-master system by default, and does not provide an option for single-master with multi-region replication for reads only. The concept of application-level failover to another region for writes is essentially redundant in Apache Cassandra as all nodes are independent and there is no single point of failure, which explains the default policy.<\/p>\n<p>However, Azure Cosmos DB provides the out-of-box ability to configure either single master, or multi-master regions for writes. One of the advantages of having a single master region for writes is the avoidance of cross-region conflict scenarios, and the option of maintaining strong consistency across multiple regions, while still maintaining a level of high availability. Thus, unlike native Apache Cassandra, Azure Cosmos DB allows you to navigate the trade-off between Recovery-point-objective (RPO) and Recovery-time-objective (RTO) at a platform level. You can read more about RPO and RTO as it applies to the Cosmos DB platform <a href=\"https:\/\/docs.microsoft.com\/en-gb\/azure\/cosmos-db\/consistency-levels#rto\">here<\/a>.<\/p>\n<p>The class for the Cosmos DB custom load balancing policy (<a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/blob\/release\/java-driver-4\/1.0.0\/driver-4\/src\/main\/java\/com\/azure\/cosmos\/cassandra\/CosmosLoadBalancingPolicy.java\" target=\"_blank\" rel=\"noopener\">CosmosLoadBalancingPolicy<\/a>) is referenced in <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/blob\/release\/java-driver-4\/1.0.0\/driver-4\/src\/main\/resources\/reference.conf\" target=\"_blank\" rel=\"noopener\">reference.conf<\/a> of the extension for Cassandra API, but the values for <code>global-endpoint<\/code>, <code>read-datacenter<\/code>, and <code>write-datacenter<\/code> should be overriden in an <a href=\"https:\/\/github.com\/Azure-Samples\/azure-cosmos-cassandra-extensions-java-sample-v4\/blob\/master\/java-examples\/src\/main\/resources\/application.conf\" target=\"_blank\" rel=\"noopener\">application.conf<\/a> within your code. When global-endpoint is specified, you may specify a <code>read-datacenter<\/code>, but must not specify a <code>write-datacenter<\/code>. Writes will go to the default write region when a global-endpoint is specified. When global-endpoint is not specified, you must specify values for <code>read-datacenter<\/code> and <code>write-datacenter<\/code>.<\/p>\n<pre> \u00a0\u00a0\u00a0load-balancing-policy {\r\n \u00a0\u00a0\u00a0\u00a0\u00a0global-endpoint = \"\"\r\n \u00a0\u00a0\u00a0\u00a0\u00a0read-datacenter = \"Australia East\"\r\n \u00a0\u00a0\u00a0\u00a0\u00a0write-datacenter = \"UK South\"\r\n\u00a0\u00a0\u00a0\u00a0}\r\n<\/pre>\n<h3 id=\"preferred-regions\" class=\"code-line code-line\" data-line=\"152\"><span style=\"font-size: 18pt;\"><strong>Preferred regions<\/strong><\/span><\/h3>\n<p class=\"code-line code-line\" data-line=\"154\">The load balancing policy mentioned above also include a &#8220;preferred regions&#8221; feature. This allows you to configure deterministic failover to specified regions in a multi-region deployment, in case of regional outages. The policy uses the regions in the list you specify, in priority order as determined by <code>preferred-regions<\/code>, to perform operations. If <code>preferred-regions<\/code> is null or not present, the policy uses the region specified in <code>read-datacenter<\/code> for reads, and either <code>write-datacenter<\/code> or <code>global-endpoint<\/code> to determine the region for writes. If neither preferred-regions or <code>read-datacenter<\/code> are present, the write region is the preferred location for all operations. When multi-region writes are enabled on the Cosmos DB account (and multi-region-write is set to true), the priority order for writes will be exactly the same as for reads.<\/p>\n<div>\n<div>\n<pre> \u00a0\u00a0\u00a0load-balancing-policy\u00a0{\r\n \u00a0\u00a0\u00a0\u00a0\u00a0multi-region-writes\u00a0=\u00a0false\r\n \u00a0\u00a0\u00a0\u00a0\u00a0global-endpoint\u00a0=\u00a0\"\"\r\n \u00a0\u00a0\u00a0\u00a0\u00a0read-datacenter\u00a0=\u00a0\"Australia\u00a0East\"\r\n \u00a0\u00a0\u00a0\u00a0\u00a0write-datacenter\u00a0=\u00a0\"UK\u00a0South\"\r\n \u00a0\u00a0\u00a0\u00a0\u00a0preferred-regions\u00a0=\u00a0[\"Australia\u00a0East\",\u00a0\"UK\u00a0West\"]\r\n\u00a0\u00a0\u00a0\u00a0}<\/pre>\n<\/div>\n<\/div>\n<h2><span style=\"font-size: 18pt;\"><b>Timeouts<\/b><\/span><\/h2>\n<p>A request timeout of 60 seconds provides a better out-of-box experience than the default value of 2 seconds. Adjust this value up or down based on workload and Cosmos Cassandra throughput provisioning. The more throughput you provision, the lower you might set this value.<\/p>\n<pre><code>    request {\r\n      timeout = \"60 seconds\"\r\n    }\r\n<\/code><\/pre>\n<h2><span style=\"font-size: 18pt;\"><strong>Get started<\/strong><\/span><\/h2>\n<p>Create a new account using the Azure Portal, ARM template or Azure CLI and connect to it using your favorite tools. Check out the <a href=\"https:\/\/github.com\/Azure-Samples\/azure-cosmos-cassandra-extensions-java-sample-v4\" target=\"_blank\" rel=\"noopener\">code sample<\/a> which walks through an implementation of the <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/tree\/release\/java-driver-4\/1.0.0\" target=\"_blank\" rel=\"noopener\">extension<\/a> referred to above, specifically to illustrate the <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/blob\/release\/java-driver-4\/1.0.0\/driver-4\/src\/main\/java\/com\/azure\/cosmos\/cassandra\/CosmosRetryPolicy.java\" target=\"_blank\" rel=\"noopener\">retry policy<\/a> and <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-cassandra-extensions\/blob\/release\/java-driver-4\/1.0.0\/driver-4\/src\/main\/java\/com\/azure\/cosmos\/cassandra\/CosmosLoadBalancingPolicy.java\" target=\"_blank\" rel=\"noopener\">load balancing policy<\/a>. We\u2019d love to hear your feedback as well at askcosmosdbcassandra@microsoft.com. Stay up-to-date on the latest Azure\u202f<a href=\"https:\/\/twitter.com\/search?q=%23cosmosdb\">#CosmosDB<\/a>\u202fnews and features by following us on Twitter\u202f<a href=\"https:\/\/twitter.com\/azurecosmosdb\">@AzureCosmosDB<\/a>. We are really excited to see what you will build with Azure Cosmos DB!<\/p>\n<p>&nbsp;<\/p>\n<pre><code><\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Check out the latest recommendations for using Java V4 Cassandra Driver with Azure Cosmos DB&#8217;s Cassandra API. We&#8217;ve created a custom Java extension that you can implement without any code changes, for a better overall experience. <\/p>\n","protected":false},"author":9387,"featured_media":1094,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[16,19],"tags":[1079,1075,287,1782,1779,1781,1780],"class_list":["post-2768","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cassandra-api","category-tips-and-tricks","tag-apache-cassandra","tag-cassandra-api","tag-cosmos-db","tag-failover","tag-java-v4-driver","tag-load-balancing","tag-retry-policy"],"acf":[],"blog_post_summary":"<p>Check out the latest recommendations for using Java V4 Cassandra Driver with Azure Cosmos DB&#8217;s Cassandra API. We&#8217;ve created a custom Java extension that you can implement without any code changes, for a better overall experience. <\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/2768","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/users\/9387"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/comments?post=2768"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/2768\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/1094"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=2768"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=2768"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=2768"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}