{"id":443,"date":"2012-06-22T12:38:27","date_gmt":"2012-06-22T04:38:27","guid":{"rendered":"http:\/\/rmohan.com\/?p=443"},"modified":"2012-06-22T12:45:18","modified_gmt":"2012-06-22T04:45:18","slug":"setting-up-clustering-on-apachejboss-using-jakarta-mod_jk","status":"publish","type":"post","link":"https:\/\/mohan.sg\/?p=443","title":{"rendered":"Setting up Clustering on Apache\/Jboss\/Tomcat  using Jakarta mod_jk"},"content":{"rendered":"<div>\n<p>Clustering Jboss for two reasons\u00a0 load balancing and failover.<\/p>\n<\/div>\n<h3>Fail-over<\/h3>\n<div>\n<p>Fail-over is probably the most important issue for web applications. If the front end load balancer detects that one of the nodes has gone down it will redirect all the traffic to the second instance and your clients, apart from any on the failed node, won\u2019t even notice. Well that\u2019s the theory \u2013 if the site is under high load you may find that the surviving Tomcat cannot cope with the increased load and fails in short order. You need to size and correctly configure your hardware and software.<\/p>\n<p>You can also manually fail-over a system to upgrade the hardware, JVM or other application without end users being aware. If your management doesn\u2019t tolerate any downtime this is an extremely important feature. Your JVM\u2019s can be installed on separate or the same physical host. The latter leaves you exposed to hardware problems.<\/p>\n<\/div>\n<h2>Load-balancing<\/h2>\n<div>\n<p>There are two easy ways to increase application performance without tuning the application software itself. Buy faster hardware or add more hardware. If you add a second server running Jboss you can use load balancing to distribute the work between the two servers. Requests come in to the Apache front end, static content is served directly by Apache and any dynamic requests forwarded to the Tomcats based on some algorithm. The Apache Jakarta <em>mod_jk<\/em> connector is the most popular way of doing this.<\/p>\n<p>In this exercise we will configure two physical computers each running one Apache web server and two tomcats for both failover and load balancing. The example ignores any back-end data storage considerations but will discuss load balancing between the two computers.<\/p>\n<\/div>\n<h2><a id=\"front-end-load-balancing\" name=\"front-end-load-balancing\"><\/a>Front End Load Balancing<\/h2>\n<div><\/div>\n<h3>DNS Round Robin<\/h3>\n<div>\n<p>The simplest technique for load balancing between the two Apache front end servers is the <a title=\"http:\/\/en.wikipedia.org\/wiki\/Round_robin_DNS\" href=\"http:\/\/en.wikipedia.org\/wiki\/Round_robin_DNS\">DNS Round Robin<\/a> strategy. This performs load balancing by returning a different server IP address each time a (<acronym title=\"Domain Name System\">DNS<\/acronym>) name server is queried by a client. It is usually found as front-end service on large clusters of servers to provide a server address that is geographically close to the client. Normally an intelligent name server such as <em>lbnamed<\/em> is used. This will poll the web servers in the list to check if they are online and not overloaded.<\/p>\n<p><acronym title=\"Domain Name System\">DNS<\/acronym> Load balancing has some significant drawbacks. Addresses may be cached by clients and local <acronym title=\"Domain Name System\">DNS<\/acronym> resolvers and it can be hard to accurately manage load. The system simply shuffles the order of the address records each time the name server is queried. No account is taken of real server load or network congestion.<\/p>\n<\/div>\n<h3><a id=\"load-balanced\" name=\"load-balanced\"><\/a>Load Balanced<\/h3>\n<div>\n<p>The advantage of using a load balancer compared to using round robin <acronym title=\"Domain Name System\">DNS<\/acronym> is that it takes care of the load on the web server nodes and will direct requests to the node with the least load. It can also remove failed nodes from the list. Some round robin <acronym title=\"Domain Name System\">DNS<\/acronym> software can do this, the problem is they have little control about how client\u2019s cache IP addresses.<\/p>\n<p>Many web applications (e.g. forum software, shopping carts, etc.) make use of sessions. If you are in a session on Apache node 1, you would lose that session if suddenly node 2 served your requests. This assumes that the web servers don\u2019t share their session data, say via a database.<\/p>\n<p>For <acronym title=\"Domain Name System\">DNS<\/acronym> load balancing this is not a problem, the IP address will resolve to a single server. However a front end load balancer must be aware of sessions and always redirect requests from the same user to the same backend server.<\/p>\n<p>There are a number of packages to support front end load balancing. F<strong>or example RedHat <em>Piranha<\/em> or <em>Ultramonkey<\/em>. There are also hardware\/firmware solutions from companies such as Cisco.<\/strong><\/p>\n<p>&nbsp;<\/p>\n<h2>Apache httpd<\/h2>\n<div><\/div>\n<h2>MaxClients<\/h2>\n<div>\n<p>MaxClients limits the maximum simultaneous connections that Apache can serve. This value should be tuned carefully based on the amount of memory available on the system.<\/p>\n<pre>MaxClients ? (RAM - size_all_other_processes)\/(size_apache_process(es))<\/pre>\n<p>If Apache is using the <strong>PreFork MPM<\/strong> a separate Apache process will be created for each connection, so the total number of processes will be MaxClients + 1. Each process will have a single connection the mod_jk pool to talk to a Jboss instance. The <strong>Worker MPM<\/strong> module uses the thread model to handle client requests and should be slightly more efficient.<\/p>\n<p>As a guide Apache <strong>MaxClients<\/strong> and the number of available jboss threads configured in <em>server.xml<\/em> should be equal. Mod_jk maintains persistent connections between Apache and jboss. If the Apache front end accepts more users than jboss can handle you will see connection errors. In a clustered environment we have to take account of errors the load balancer makes when it tracks the number of concurrent threads to the Tomcat back-ends so the following formula is a starting point:<\/p>\n<pre>Apache.MaxClients = 0.8 * (Tomcat-1.maxThreads + \u2026 Tomcat-n.maxThreads)<\/pre>\n<p>i.e.<\/p>\n<pre>400 = 0.8 * (250 + 250)<\/pre>\n<p>Use:<\/p>\n<ul>\n<li>\n<div>httpd \u2013V to see how Apache is compiled<\/div>\n<\/li>\n<li>\n<div>ps or top to see how much memory is being used on the system<\/div>\n<\/li>\n<li>\n<div>vmstat to tune memory usage<\/div>\n<\/li>\n<\/ul>\n<p>The Sezame Apache front end also serves static content and a number of client connections will be used for this purpose for each requested page of content.<\/p>\n<\/div>\n<h3>MaxRequestsPerChild<\/h3>\n<div>\n<p>Sets the total number of requests that each Apache process will handle before it quits. This is useful to control memory leaks issues with loaded modules. Because mod_jk maintains permanent connections in its pool between Apache and jboss we will set this to zero which means that unlimited requests can be handled.<\/p>\n<\/div>\n<h3>Redirection requests to the mod_jk load balancer<\/h3>\n<p>We will need to load the mod_jk module (a shared library) into Apache when it starts and tell the module where to find the <em>workers.properties<\/em> file and where to write logs (useful for debugging\/crashes).<br \/>\n\/etc\/httpd\/conf\/httpd.conf<\/p>\n<p>1. httpd.conf:<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\n# Include mod_jk&#8217;s specific configuration file<br \/>\nInclude conf\/mod-jk.conf<\/p>\n<p>2. mod-jk.conf:<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br \/>\n# Load mod_jk module<br \/>\n# Specify the filename of the mod_jk lib<br \/>\nLoadModule jk_module modules\/mod_jk.so<br \/>\n# Where to find workers.properties<br \/>\nJkWorkersFile conf\/workers.properties<br \/>\n# Where to put jk logs<br \/>\nJkLogFile logs\/mod_jk.log<br \/>\n# Set the jk log level [debug\/error\/info]<br \/>\nJkLogLevel info<br \/>\n# Select the log format<br \/>\nJkLogStampFormat &#8220;[%a %b %d %H:%M:%S %Y]&#8221;<br \/>\n# JkOptions indicates to send SSK KEY SIZE<br \/>\nJkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories<br \/>\n# JkRequestLogFormat<br \/>\nJkRequestLogFormat &#8220;%w %V %T&#8221;<br \/>\n# Mount your applications<br \/>\nJkMount \/myapp\/* loadbalancer<br \/>\nJkMount \/jspellhtml2k4\/* loadbalancer<br \/>\nJkMount \/jspelliframe2k4\/* loadbalancer<br \/>\nJkMount \/jspellhtml2k4 loadbalancer<br \/>\nJkMount \/jspelliframe2k4 loadbalancer<\/p>\n<p># You can use external file for mount points.<br \/>\n# It will be checked for updates each 60 seconds.<br \/>\n# The format of the file is: \/url=worker<br \/>\n# \/examples\/*=loadbalancer<br \/>\nJkMountFile conf\/uriworkermap.properties<\/p>\n<p># Add shared memory.<br \/>\n# This directive is present with 1.2.10 and<br \/>\n# later versions of mod_jk, and is needed for<br \/>\n# for load balancing to work properly<br \/>\n# Note: Replaced JkShmFile logs\/jk.shm due to SELinux issues. Refer to<br \/>\n# https:\/\/bugzilla.redhat.com\/bugzilla\/show_bug.cgi?id=225452<br \/>\nJkShmFile run\/jk.shm<\/p>\n<p># Add jkstatus for managing runtime data<br \/>\n&lt;Location \/jkstatus&gt;<br \/>\nJkMount status<br \/>\nOrder deny,allow<br \/>\nDeny from all<br \/>\nAllow from 127.0.0.1<br \/>\n&lt;\/Location&gt;<\/p>\n<p>2. uriworkermap.properties<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>\n# Simple worker configuration file<br \/>\n# Mount the Servlet context to the ajp13 worker<br \/>\n\/jmx-console=loadbalancer<br \/>\n\/jmx-console\/*=loadbalancer<br \/>\n\/web-console=loadbalancer<br \/>\n\/web-console\/*=loadbalancer<br \/>\n\/myapp\/*=loadbalancer<br \/>\n\/myapp=loadbalancer<br \/>\n\/jspellhtml2k4\/*=loadbalancer<br \/>\n\/jspellhtml2k4=loadbalancer<br \/>\n\/jspelliframe2k4\/*=loadbalancer<br \/>\n\/jspelliframe2k4=loadbalancer<\/p>\n<p>The following is a suggested configuration for two physical servers with a pair Tomcat instances running on each. The rational is that the front end load balancer will distribute load between the two physical hosts. The f\/e load balancer is itself configured for fail-over using a <a title=\"http:\/\/en.wikipedia.org\/wiki\/Virtual_IP_address\" href=\"http:\/\/en.wikipedia.org\/wiki\/Virtual_IP_address\">virtual IP address<\/a> and a heartbeat type operation to determine if the balancer is still operational.<\/p>\n<p>Each physical server has an Apache web server and two tomcat servlet engines. Apache will serve static content either from an NFS mounted disk or from a replicated file system using something like Web. Apache will load balance between the two local\u00a0 jboss but if these become overloaded or crash it can forward requests on to the other physical server.<\/p>\n<p>The Apache mod_jk load-balancer can distribute work using one of three methods:<\/p>\n<ul>\n<li>\n<div>B (busyness): choose the worker with the lowest number of requests currently in progress<\/div>\n<\/li>\n<li>\n<div>R (requests): choose the worker that has processed the lowest number of requests overall<\/div>\n<\/li>\n<li>\n<div>T (traffic): choose the worker that transmitted the lowest number of bytes<\/div>\n<\/li>\n<\/ul>\n<p>The sticky_session is set to true to maintain a session between the client and Tomcat.<\/p>\n<pre>worker.list=loadbalancer\r\n\r\nworker.loadbalancer.type=lb\r\nworker.loadbalancer.method=B\r\nworker.loadbalancer.balance_workers=worker1,worker2,worker3,worker4\r\nworker.loadbalancer.sticky_session=true<\/pre>\n<p>This is common configuration for all workers. Note if Prefork MPM is used you will want to set the <strong>cachesize<\/strong> property. This should reflect the estimated average concurrent number of users for the Tomcat instance. <strong>Cache_timeout<\/strong> should be set to close cached sockets. This reduces the number of idle threads on the Tomcat server. Note that <strong>connection_pool_size<\/strong> and <strong>connection_pool_timeout<\/strong> should be used with mod_jk 1.2.16 and later.<\/p>\n<p>If there is a firewall between Apache and Jboss t the <strong>socket_keepalive<\/strong> property should be used. <strong>Socket_timeout<\/strong> will tell Apache to close an ajp13 connection after some inactivity time. This also reduces idle threads on Tomcat.<\/p>\n<pre># common config\r\nworker.basic.type=ajp13\r\nworker.basic.socket_timeout=300\r\nworker.basic.lbfactor=5<\/pre>\n<p>3. workers.properties<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>\n# The configuration directives are valid<br \/>\n# for the mod_jk version 1.2.18 and later<br \/>\n#<br \/>\nworker.list=loadbalancer,status<\/p>\n<p># Define Node1<br \/>\n# modify the host as your host IP or DNS name.<br \/>\nworker.node1.port=8009<br \/>\nworker.node1.host=myapp-myapp.myapp.com<br \/>\nworker.node1.type=ajp13<br \/>\nworker.node1.lbfactor=1<br \/>\nworker.node1.connection_pool_size=10<br \/>\nworker.node1.cachesize=10<\/p>\n<p># Define Node2<br \/>\n# modify the host as your host IP or DNS name.<br \/>\nworker.node2.port=8009<br \/>\nworker.node2.host=myapp-myapp1.myapp.com<br \/>\nworker.node2.type=ajp13<br \/>\nworker.node2.lbfactor=1<br \/>\nworker.node2.connection_pool_size=10<br \/>\nworker.node2.cachesize=10<\/p>\n<p># Load-balancing behaviour<br \/>\nworker.loadbalancer.type=lb<br \/>\nworker.loadbalancer.balance_workers=node1,node2<br \/>\nworker.loadbalancer.sticky_session=1<\/p>\n<p># Status worker for managing load balancer<br \/>\nworker.status.type=status<\/p>\n<p>2.\u00a0\u00a0\u00a0 Make Sure all below given settings are available in JBoss configurations in all nodes of\u00a0 Jboss cluster.<\/p>\n<p>JBoss Server Side Configuration Changes:<br \/>\n\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2013<\/p>\n<p>1. Remove\/comment out below two ports from ja.properties file.<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>\nvi \/opt\/jboss\/jboss-5.0\/jboss-as\/server\/template_cluster\/conf\/ja.properties file.<br \/>\nSearch for below two lines<br \/>\nOAPort=3528<br \/>\nOASSLPort=3529<br \/>\nCommentout both lines like below and save the file.<br \/>\n#OAPort=3528<br \/>\n#OASSLPort=3529<\/p>\n<p>2. Add jvmRoute<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br \/>\nvi \/opt\/jboss\/jboss-5.06\/jboss-as\/server\/template_cluster\/deploy\/jboss-web.deployer\/server.xml<\/p>\n<p>Search For Below Text:<br \/>\n&lt;Engine name=&#8221;jboss.web&#8221; defaultHost=&#8221;localhost&#8221;&gt;<br \/>\nChange it to:<br \/>\n&lt;Engine name=&#8221;jboss.web&#8221; defaultHost=&#8221;localhost&#8221; jvmRoute=&#8221;node1&#8243;&gt;<\/p>\n<p>Note: This configuration needs to be done in all the nodes and all the configuration files need to be changed accordingly.<br \/>\nCheck the workers.properties file to know which host is node1 or nodex<br \/>\nExample: For node2 the jvmRoute will be node2(HostName can be found out from workers.properties file)<br \/>\n&lt;Engine name=&#8221;jboss.web&#8221; defaultHost=&#8221;localhost&#8221; jvmRoute=&#8221;node2&#8243;&gt;<\/p>\n<p>3. Change UseJK to true<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>\nvi \/opt\/jboss\/jboss-5.0\/jboss-as\/server\/template_cluster\/deploy\/jboss-web.deployer\/META-INF\/jboss-service.xml<\/p>\n<p>Search For Below Text:<br \/>\n&lt;attribute name=&#8221;UseJK&#8221;&gt;false&lt;\/attribute&gt;<br \/>\nChange it to:<br \/>\n&lt;attribute name=&#8221;UseJK&#8221;&gt;true&lt;\/attribute&gt;<\/p>\n<p>Note: This configuration needs to be done in all the nodes and all the configuration files need to be changed accordingly.<\/p>\n<p>4. Make Sure Below properties are present in jboss-service.xml config file.<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br \/>\nvi \/opt\/jboss\/jboss-5.0\/jboss-as\/server\/template_cluster\/deploy\/jboss-web-cluster.sar\/META-INF\/jboss-service.xml<\/p>\n<p>&lt;mbean code=&#8221;org.jboss.cache.aop.TreeCacheAop&#8221; name=&#8221;jboss.cache:service=TomcatClusteringCache&#8221;&gt;<br \/>\n&lt;depends&gt;jboss:service=Naming&lt;\/depends&gt;<br \/>\n&lt;depends&gt;jboss:service=TransactionManager&lt;\/depends&gt;<br \/>\n&lt;depends&gt;jboss.aop:service=AspectDeployer&lt;\/depends&gt;<br \/>\n&lt;attribute name=&#8221;TransactionManagerLookupClass&#8221;&gt;org.jboss.cache.BatchModeTransactionManagerLookup&lt;\/attribute&gt;<br \/>\n&lt;attribute name=&#8221;IsolationLevel&#8221;&gt;REPEATABLE_READ&lt;\/attribute&gt;<br \/>\n&lt;attribute name=&#8221;CacheMode&#8221;&gt;REPL_ASYNC&lt;\/attribute&gt;<br \/>\n&lt;attribute name=&#8221;ClusterName&#8221;&gt;Tomcat-${jboss.partition.name:Cluster}&lt;\/attribute&gt;<br \/>\n&lt;attribute name=&#8221;UseMarshalling&#8221;&gt;false&lt;\/attribute&gt;<br \/>\n&lt;attribute name=&#8221;InactiveOnStartup&#8221;&gt;false&lt;\/attribute&gt;<br \/>\n&lt;attribute name=&#8221;ClusterConfig&#8221;&gt;<br \/>\n&#8230; &#8230;<br \/>\n&lt;\/attribute&gt;<br \/>\n&lt;attribute name=&#8221;LockAcquisitionTimeout&#8221;&gt;15000&lt;\/attribute&gt;<br \/>\n&lt;\/mbean&gt;<\/p>\n<p>The sticky_session is set to true to maintain a session between the client and Tomcat.<\/p>\n<pre>worker.list=loadbalancer\r\n\r\nworker.loadbalancer.type=lb\r\nworker.loadbalancer.method=B\r\nworker.loadbalancer.balance_workers=worker1,worker2,worker3,worker4\r\nworker.loadbalancer.sticky_session=true<\/pre>\n<p>This is common configuration for all workers. Note if Prefork MPM is used you will want to set the <strong>cachesize<\/strong> property. This should reflect the estimated average concurrent number of users for the Tomcat instance. <strong>Cache_timeout<\/strong> should be set to close cached sockets. This reduces the number of idle threads on the Tomcat server. Note that <strong>connection_pool_size<\/strong> and <strong>connection_pool_timeout<\/strong> should be used with mod_jk 1.2.16 and later.<\/p>\n<p>If there is a firewall between Apache and Tomcat the <strong>socket_keepalive<\/strong> property should be used. <strong>Socket_timeout<\/strong> will tell Apache to close an ajp13 connection after some inactivity time. This also reduces idle threads on Tomcat.<\/p>\n<pre># common config\r\nworker.basic.type=ajp13\r\nworker.basic.socket_timeout=300\r\nworker.basic.lbfactor=5<\/pre>\n<p>These are the two workers. Notice the use of the <strong>local_worker<\/strong> property. The load-balancer will always favour local_workers with a value set to 1.<\/p>\n<pre>worker.worker1.host=server1\r\nworker.worker1.port=8009\r\nworker.worker1.local_worker=1\r\nworker.worker1.reference=worker.basic\r\n\r\nworker.worker2.host=server1\r\nworker.worker2.port=8010\r\nworker.worker2.local_worker=1\r\nworker.worker2.reference=worker.basic\r\n\r\nworker.worker3.host=server2\r\nworker.worker3.port=8009\r\nworker.worker3.local_worker=0\r\nworker.worker3.reference=worker.basic\r\n\r\nworker.worker4.host=server2\r\nworker.worker4.port=8010\r\nworker.worker4.local_worker=0\r\nworker.worker4.reference=worker.basic<\/pre>\n<h2>Tomcat Configuration<\/h2>\n<div>\n<p>Http access is only required by administrators for checking if a Tomcat instance is still running by connecting directly to the specified port. The firewall should block client access to this port.<\/p>\n<pre>&lt;Connector port=\"8899\"  minSpareThreads=\"5\" maxThreads=\"10\" enableLookups=\"false\" redirectPort=\"8443\" acceptCount=\"10\" debug=\"0\" connectionTimeout=\"60000\"\/&gt;<\/pre>\n<p>The Tomcat instance must listen on the same port as is specified in the corresponding worker\u2019s section in <em>worker.propeties<\/em>.<\/p>\n<pre>&lt;Connector port=\"8009\" enableLookups=\"false\" redirectPort=\"8443\" \r\nprotocol=\"AJP\/1.3\" maxThreads=\"400\" minSpareThreads=\"50\"  maxSpareThreads=\"300\" \/&gt;<\/pre>\n<p><strong>maxThreads<\/strong> should be configured so that the CPU can be loaded to no more than 100% without seeing JVM error messages about insufficient threads.<\/p>\n<p>The Engine <strong>jvmRoute<\/strong> property should correspond to the worker name in the <em>worker.properties<\/em> file or the load balancer will not be able to handle stickyness.<\/p>\n<pre>&lt;Engine name=\"Catalina\" defaultHost=\"localhost\" jvmRoute=\"worker1\"&gt;<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"\n<p>Clustering Jboss for two reasons load balancing and failover.<\/p>\n<p> Fail-over <\/p>\n<p>Fail-over is probably the most important issue for web applications. If the front end load balancer detects that one of the nodes has gone down it will redirect all the traffic to the second instance and your clients, apart from any on the failed [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,21],"tags":[],"_links":{"self":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/443"}],"collection":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=443"}],"version-history":[{"count":6,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/443\/revisions"}],"predecessor-version":[{"id":446,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/443\/revisions\/446"}],"wp:attachment":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}