You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ko...@apache.org on 2018/01/14 02:37:34 UTC

[couchdb] branch dns-cluster-discovery created (now f3a2fb1)

This is an automated email from the ASF dual-hosted git repository.

kocolosk pushed a change to branch dns-cluster-discovery
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


      at f3a2fb1  Enable discovery of cluster nodes through DNS SRV

This branch includes the following new commits:

     new f3a2fb1  Enable discovery of cluster nodes through DNS SRV

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@couchdb.apache.org" <co...@couchdb.apache.org>'].

[couchdb] 01/01: Enable discovery of cluster nodes through DNS SRV

Posted by ko...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kocolosk pushed a commit to branch dns-cluster-discovery
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit f3a2fb165fea4aee4f42ce0fbcd98ba461c26c84
Author: Adam Kocoloski <ko...@apache.org>
AuthorDate: Fri Jan 12 22:16:49 2018 -0500

    Enable discovery of cluster nodes through DNS SRV
    
    This patch enables CouchDB nodes to check SRV records in DNS for cluster
    peers and automatically add any discovered peers to the nodes DB. This
    behavior is disabled by default and can be enabled as follows:
    
    [mem3]
    use_dns_service_discovery = true
    service_record_name = _couchdb._tcp.example.net
    
    If the `service_record_name` is omitted we attempt to generate the
    appropriate record for the query by prepending _couchdb._tcp. to the DNS
    domain name portion of the host / VM / container FQDN.
---
 src/mem3/src/mem3_dns.erl   | 109 ++++++++++++++++++++++++++++++++++++++++++++
 src/mem3/src/mem3_nodes.erl |   1 +
 src/mem3/src/mem3_sup.erl   |   1 +
 3 files changed, 111 insertions(+)

diff --git a/src/mem3/src/mem3_dns.erl b/src/mem3/src/mem3_dns.erl
new file mode 100644
index 0000000..0a954fd
--- /dev/null
+++ b/src/mem3/src/mem3_dns.erl
@@ -0,0 +1,109 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(mem3_dns).
+-behaviour(gen_server).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
+    code_change/3]).
+
+-export([start_link/0]).
+-export([discover_peers/0]).
+
+-include_lib("couch/include/couch_db.hrl").
+
+-record(state, {
+    record_name,
+    discovered_names,
+    last_error,
+    timeout = 2000,
+    max_tries = 10
+}).
+
+start_link() ->
+    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+discover_peers() ->
+    case config:get("mem3", "use_dns_service_discovery", "false") of
+    "true" ->
+        gen_server:cast(?MODULE, discover_peers);
+    _ ->
+        ok
+    end.
+
+init([]) ->
+    {ok, ServiceRecord} = construct_service_record(),
+    {ok, #state{record_name = ServiceRecord}}.
+
+handle_call(_Call, _From, State) ->
+    {reply, ok, State}.
+
+handle_cast(discover_peers, #state{max_tries = 0} = State) ->
+    {ok, State};
+
+handle_cast(discover_peers, St) ->
+    case query_dns(St#state.record_name) of
+    {ok, Hostnames} ->
+        add_nodes(Hostnames),
+        {ok, St#state{discovered_names = Hostnames}};
+    {error, Error} ->
+        #state{max_tries = Max, timeout = Timeout} = St,
+        NewSt = St#state{
+            last_error = Error,
+            max_tries = Max-1,
+            timeout = 2*Timeout
+        },
+        {ok, NewSt, Timeout}
+    end.
+
+handle_info(timeout, State) ->
+    handle_cast(discover_peers, State).
+
+terminate(_Reason, _State) ->
+    ok.
+
+code_change(_OldVsn, #state{}=State, _Extra) ->
+    {ok, State}.
+
+query_dns(ServiceRecord) ->
+    Opts = [{edns, 0}],
+    case inet_res:resolve(ServiceRecord, in, srv, Opts) of
+    {ok, DnsMsg} ->
+        Hostnames = lists:foldl(fun(Answer, Acc) ->
+            case inet_dns:rr(Answer, type) of
+            srv ->
+                {_, _, _, Service} = inet_dns:rr(Answer, data),
+                [Service | Acc];
+            _ ->
+                Acc
+            end
+        end, [], inet_dns:msg(DnsMsg, anlist)),
+        {ok, Hostnames};
+    Error ->
+        Error
+    end.
+
+construct_service_record() ->
+    case config:get("mem3", "service_record_name") of
+    undefined ->
+        [_ | Domain] = string:tokens(net_adm:localhost(), "."),
+        {ok, string:join(["_couchdb", "_tcp" | Domain], ".")};
+    ServiceRecord ->
+        {ok, ServiceRecord}
+    end.
+
+add_nodes(Hostnames) ->
+    DbName = config:get("mem3", "nodes_db", "_nodes"),
+    {ok, Db} = mem3_util:ensure_exists(DbName),
+    Peers = lists:map(fun(Hostname) ->
+        #doc{id = couch_util:to_binary("couchdb@" ++ Hostname)}
+    end, Hostnames),
+    couch_db:update_docs(Db, Peers, []).
diff --git a/src/mem3/src/mem3_nodes.erl b/src/mem3/src/mem3_nodes.erl
index 555389b..02f1a2d 100644
--- a/src/mem3/src/mem3_nodes.erl
+++ b/src/mem3/src/mem3_nodes.erl
@@ -43,6 +43,7 @@ get_node_info(Node, Key) ->
 init([]) ->
     ets:new(?MODULE, [named_table, {read_concurrency, true}]),
     UpdateSeq = initialize_nodelist(),
+    mem3_dns:discover_peers(),
     {Pid, _} = spawn_monitor(fun() -> listen_for_changes(UpdateSeq) end),
     {ok, #state{changes_pid = Pid, update_seq = UpdateSeq}}.
 
diff --git a/src/mem3/src/mem3_sup.erl b/src/mem3/src/mem3_sup.erl
index 80b8ca3..0647447 100644
--- a/src/mem3/src/mem3_sup.erl
+++ b/src/mem3/src/mem3_sup.erl
@@ -20,6 +20,7 @@ start_link() ->
 init(_Args) ->
     Children = [
         child(mem3_events),
+        child(mem3_dns),
         child(mem3_nodes),
         child(mem3_sync_nodes), % Order important?
         child(mem3_sync),

-- 
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.