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>.