{"id":501,"date":"2009-09-09T12:52:27","date_gmt":"2009-09-09T17:52:27","guid":{"rendered":"http:\/\/appcrawler.com\/wordpress\/?p=501"},"modified":"2017-04-13T14:54:42","modified_gmt":"2017-04-13T19:54:42","slug":"manually-subscribing-to-oracle-fan-events","status":"publish","type":"post","link":"http:\/\/appcrawler.com\/wordpress\/2009\/09\/09\/manually-subscribing-to-oracle-fan-events\/","title":{"rendered":"Manually subscribing to Oracle FAN events"},"content":{"rendered":"<p>JDBC and dot Net clients are the recommended way to automatically subscribe to high availability events in an Oracle clustered environment, AKA, a RAC.<\/p>\n<p>I was curious as to how this could be implemented using your own code behind the scenes.  To show this, we will use a combination of PL\/SQL and python.<\/p>\n<p>First, we should note the queue used by Oracle to store high availability events is a member of the SYS schema and is named SYS$SERVICE_METRICS.  As such, we first need to allow our user who will will be monitoring the service health of our cluster to dequeue events from this queue.<\/p>\n<p>As SYS&#8230;<\/p>\n<pre lang=\"plsql\" line=\"1\">\r\nbegin\r\n  dbms_aqadm.grant_queue_privilege (privilege =>'DEQUEUE',\r\n                                    queue_name => 'sys.SYS$SERVICE_METRICS',\r\n                                    grantee => 'HOWARDS',\r\n                                    grant_option=>FALSE);\r\nend;\r\n\/\r\n<\/pre>\n<p>We also need to allow our user to perform operations using the PAYLOAD_TYPE used by the queue.  This is also a member of the SYS schema and is named SYS$RLBTYP.<\/p>\n<pre lang=\"sql\" line=\"1\">\r\ngrant execute on dbms_aq to howards;\r\nGRANT EXECUTE ON SYS.SYS$RLBTYP to HOWARDS;\r\n<\/pre>\n<p>We must then add ourselves as a subscriber of this queue&#8230;<\/p>\n<pre lang=\"plsql\" line=\"1\">\r\ndeclare\r\n  subscriber sys.aq$_agent;\r\nbegin\r\n  subscriber:=sys.aq$_agent('HOWARDS',null,null);\r\n  dbms_aqadm.add_subscriber(queue_name => 'sys.SYS$SERVICE_METRICS', subscriber=>subscriber);\r\nend;\r\n\/\r\n<\/pre>\n<p>Next, we use a PL\/SQL procedure to dequeue our events.  This is created in the HOWARDS schema.<\/p>\n<pre lang=\"plsql\" line=\"1\">\r\nCREATE OR REPLACE procedure get_rac_events (p_srv out varchar2,\r\n                                            p_payload out varchar2) is\r\n  l_dequeue_options     DBMS_AQ.dequeue_options_t;\r\n  l_message_properties  DBMS_AQ.message_properties_t;\r\n  l_message_handle      RAW(16);\r\n  l_event_msg           SYS.SYS$RLBTYP;\r\nBEGIN\r\n    l_dequeue_options.consumer_name := 'HOWARDS';\r\n    l_dequeue_options.visibility := DBMS_AQ.IMMEDIATE;\r\n    l_dequeue_options.dequeue_mode := DBMS_AQ.BROWSE;\r\n    DBMS_AQ.dequeue(queue_name          => 'sys.SYS$SERVICE_METRICS',\r\n                    dequeue_options     => l_dequeue_options,\r\n                    message_properties  => l_message_properties,\r\n                    payload             => l_event_msg,\r\n                    msgid               => l_message_handle);\r\n    dbms_output.put_line(l_event_msg.srv || ' ' || l_event_msg.payload);\r\n    p_srv := l_event_msg.srv;\r\n    p_payload := l_event_msg.payload;\r\n    COMMIT;\r\nEND;\r\n\/\r\n\r\nSHOW ERRORS\r\n<\/pre>\n<p>Ensure that your service is configured for high availability events&#8230;<\/p>\n<pre lang=\"plsql\" line=\"1\">\r\nbegin\r\n  dbms_service.modify_service('reqman',AQ_HA_NOTIFICATIONS=>true,GOAL=>1,clb_goal=>1);\r\nend;\r\n\/\r\n<\/pre>\n<p>Lastly, we use a short python script to run in a loop and print events as we dequeue them with our procedure created above&#8230;<\/p>\n<pre lang=\"python\" line=\"1\">\r\n#!\/usr\/local\/bin\/python\r\n\r\nimport cx_Oracle\r\nimport string\r\nimport time\r\n\r\nora = cx_Oracle.Connection('howards\/****@perfrac')\r\ncurs = ora.cursor()\r\nn = curs.var(cx_Oracle.STRING)\r\no = curs.var(cx_Oracle.STRING)\r\nmin=0\r\nwhile True:\r\n  curs.callproc('get_rac_events',[n,o])\r\n  service=string.split(string.split(str(o),\" \")[5],\"=\")[1]\r\n  instances=string.split(string.split(str(o),\"{ \")[1],\" }\")[0]\r\n  found=True\r\n  while found == True:\r\n    thisone=string.replace(string.split(instances,\"}\")[0],\"{\",\"\")\r\n    if thisone == \"\":\r\n      found = False\r\n    else:\r\n      instance=string.split(string.split(str(thisone),\" \")[0],\"=\")[1]\r\n      pct=string.split(string.split(str(thisone),\" \")[1],\"=\")[1]\r\n      print \"For service \" + service + \", send \" + str(pct) + \"% of traffic to instance \" + instance\r\n    instances=string.replace(instances[instances.find(\"}\") + 1:],\"{\",\"\")\r\n<\/pre>\n<p>When you run this, you should see output similar to what is below&#8230;<\/p>\n<pre lang=\"text\" line=\"1\">\r\nC:\\>type.py\r\nFor service perfcnx, send 50% of traffic to instance perfrac1\r\nFor service perfcnx, send 50% of traffic to instance perfrac2\r\nFor service perfrac.dev.oclc.org, send 54% of traffic to instance perfrac1\r\nFor service perfrac.dev.oclc.org, send 46% of traffic to instance perfrac2\r\nFor service reqman, send 100% of traffic to instance perfrac2\r\nFor service perfcnx, send 50% of traffic to instance perfrac1\r\nFor service perfcnx, send 50% of traffic to instance perfrac2\r\nFor service perfrac.dev.oclc.org, send 69% of traffic to instance perfrac1\r\nFor service perfrac.dev.oclc.org, send 31% of traffic to instance perfrac2\r\nFor service reqman, send 100% of traffic to instance perfrac2\r\nFor service perfcnx, send 50% of traffic to instance perfrac1\r\nFor service perfcnx, send 50% of traffic to instance perfrac2\r\nFor service perfrac.dev.oclc.org, send 60% of traffic to instance perfrac1\r\nFor service perfrac.dev.oclc.org, send 40% of traffic to instance perfrac2\r\nFor service reqman, send 100% of traffic to instance perfrac2\r\nFor service perfcnx, send 50% of traffic to instance perfrac1\r\nFor service perfcnx, send 50% of traffic to instance perfrac2\r\nFor service perfrac.dev.oclc.org, send 55% of traffic to instance perfrac1\r\nFor service perfrac.dev.oclc.org, send 45% of traffic to instance perfrac2\r\nFor service reqman, send 100% of traffic to instance perfrac2\r\nFor service perfcnx, send 50% of traffic to instance perfrac1\r\nFor service perfcnx, send 50% of traffic to instance perfrac2\r\nFor service perfrac.dev.oclc.org, send 76% of traffic to instance perfrac1\r\nFor service perfrac.dev.oclc.org, send 24% of traffic to instance perfrac2\r\nFor service reqman, send 100% of traffic to instance perfrac2\r\nFor service perfcnx, send 50% of traffic to instance perfrac1\r\nFor service perfcnx, send 50% of traffic to instance perfrac2\r\nFor service perfrac.dev.oclc.org, send 87% of traffic to instance perfrac1\r\nFor service perfrac.dev.oclc.org, send 13% of traffic to instance perfrac2\r\n<\/pre>\n<p>Obviously, you can make this much more sophisticated.  <\/p>\n<p>Next time, we will look at a <b>far<\/b> more efficient way of doing this, similar to subscribing to the ONS setup which we configure when using an OracleDataSource in java.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>JDBC and dot Net clients are the recommended way to automatically subscribe to high availability events in an Oracle clustered environment, AKA, a RAC. I was curious as to how this could be implemented using your own code behind the&hellip;<\/p>\n<p class=\"more-link-p\"><a class=\"more-link\" href=\"http:\/\/appcrawler.com\/wordpress\/2009\/09\/09\/manually-subscribing-to-oracle-fan-events\/\">Read more &rarr;<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"footnotes":""},"categories":[19,24,22,26],"tags":[],"_links":{"self":[{"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/posts\/501"}],"collection":[{"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/comments?post=501"}],"version-history":[{"count":21,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/posts\/501\/revisions"}],"predecessor-version":[{"id":6239,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/posts\/501\/revisions\/6239"}],"wp:attachment":[{"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/media?parent=501"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/categories?post=501"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/appcrawler.com\/wordpress\/wp-json\/wp\/v2\/tags?post=501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}