You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by zh...@apache.org on 2020/09/19 11:32:10 UTC

[bookkeeper] branch master updated: BP-41 make bookieId configurable (#2412)

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

zhaijia pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new a432865  BP-41 make bookieId configurable (#2412)
a432865 is described below

commit a432865dd6e9d5096b0ec0c1ac8cd5862068a366
Author: Enrico Olivelli <eo...@gmail.com>
AuthorDate: Sat Sep 19 13:32:03 2020 +0200

    BP-41 make bookieId configurable (#2412)
    
    ### Motivation
    This is the bookie side implementation of BP-41
    
    ### Changes
    - add new `bookieId` configuration option
    - implement Bookie#getBookieId
    - add test cases
    - make all BookKeeperClusterTestCase to use a random UUID as bookieId in order to increase code coverage
    - add useUUIDasBookieId flag to BookKeeperClusterTestCase for test cases that require using hostname:port
    - add a default BookieServiceInfo provider in tests
    - enable Auditor to use BookieId and not BookieSocketAddress.toBookieId()
    - use BookieId for LocalTransport addresses
    - in Cookie.java rename BookieHost to BookieId (only in Java code, no data format changes)
    
    Master Issue: #2396
    
    Co-authored-by: Enrico Olivelli <en...@diennea.com>
---
 .../java/org/apache/bookkeeper/bookie/Bookie.java  | 12 ++++-
 .../java/org/apache/bookkeeper/bookie/Cookie.java  | 40 ++++++++--------
 .../bookkeeper/conf/ServerConfiguration.java       | 34 ++++++++++++++
 .../bookkeeper/discover/ZKRegistrationClient.java  | 28 +++++++----
 .../apache/bookkeeper/net/BookieSocketAddress.java | 10 ----
 .../apache/bookkeeper/proto/BookieNettyServer.java | 11 +++--
 .../org/apache/bookkeeper/proto/BookieServer.java  | 13 +++++-
 .../bookkeeper/proto/PerChannelBookieClient.java   |  3 +-
 .../proto/SimpleBookieServiceInfoProvider.java     | 54 ++++++++++++++++++++++
 .../bookkeeper/replication/AutoRecoveryMain.java   |  2 +-
 .../tools/cli/commands/cookie/AdminCommand.java    |  2 +-
 .../cli/commands/cookie/GenerateCookieCommand.java |  2 +-
 .../apache/bookkeeper/util/LocalBookKeeper.java    |  2 +-
 .../bookkeeper/bookie/AdvertisedAddressTest.java   | 35 ++++++++++++++
 .../apache/bookkeeper/bookie/BookieShellTest.java  |  2 +-
 .../bookkeeper/bookie/UpdateCookieCmdTest.java     |  3 +-
 .../bookkeeper/client/BookKeeperAdminTest.java     |  2 +-
 .../client/TestGetBookieInfoTimeout.java           |  5 +-
 .../bookkeeper/client/UpdateLedgerCmdTest.java     |  1 +
 .../bookkeeper/client/UpdateLedgerOpTest.java      |  1 +
 .../replication/AuditorPeriodicCheckTest.java      |  8 ++--
 .../AuditorPlacementPolicyCheckTest.java           |  2 +-
 .../replication/AuditorReplicasCheckTest.java      |  2 +-
 .../bookkeeper/test/BookKeeperClusterTestCase.java | 14 ++++--
 .../java/org/apache/bookkeeper/tls/TestTLS.java    | 13 ++----
 conf/bk_server.conf                                |  4 ++
 .../cli/commands/cookie/AdminCommandTest.java      |  2 +-
 .../commands/cookie/GenerateCookieCommandTest.java |  4 +-
 .../cli/commands/cookie/GetCookieCommandTest.java  |  2 +-
 29 files changed, 231 insertions(+), 82 deletions(-)

diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
index a7960f7..7e8452a 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
@@ -85,6 +85,7 @@ import org.apache.bookkeeper.net.BookieId;
 import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.net.DNS;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback;
+import org.apache.bookkeeper.proto.SimpleBookieServiceInfoProvider;
 import org.apache.bookkeeper.stats.NullStatsLogger;
 import org.apache.bookkeeper.stats.StatsLogger;
 import org.apache.bookkeeper.util.BookKeeperConstants;
@@ -329,6 +330,9 @@ public class Bookie extends BookieCriticalThread {
             if (null != conf.getAdvertisedAddress()) {
                 addresses.add(getBookieAddress(conf).toBookieId());
             }
+            if (null != conf.getBookieId()) {
+                addresses.add(BookieId.parse(conf.getBookieId()));
+            }
         } catch (UnknownHostException e) {
             throw new UnknownBookieIdException(e);
         }
@@ -534,7 +538,11 @@ public class Bookie extends BookieCriticalThread {
     }
 
     public static BookieId getBookieId(ServerConfiguration conf) throws UnknownHostException {
-         return getBookieAddress(conf).toBookieId();
+        String customBookieId = conf.getBookieId();
+        if (customBookieId != null) {
+            return BookieId.parse(customBookieId);
+        }
+        return getBookieAddress(conf).toBookieId();
     }
 
     /**
@@ -619,7 +627,7 @@ public class Bookie extends BookieCriticalThread {
 
     public Bookie(ServerConfiguration conf)
             throws IOException, InterruptedException, BookieException {
-        this(conf, NullStatsLogger.INSTANCE, PooledByteBufAllocator.DEFAULT, BookieServiceInfo.NO_INFO);
+        this(conf, NullStatsLogger.INSTANCE, PooledByteBufAllocator.DEFAULT, new SimpleBookieServiceInfoProvider(conf));
     }
 
     private static LedgerStorage buildLedgerStorage(ServerConfiguration conf) throws IOException {
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java
index b80a789..5b542b5 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java
@@ -68,15 +68,15 @@ public class Cookie {
 
     static final int CURRENT_COOKIE_LAYOUT_VERSION = 4;
     private final int layoutVersion;
-    private final String bookieHost;
+    private final String bookieId;
     private final String journalDirs;
     private final String ledgerDirs;
     private final String instanceId;
     private static final String SEPARATOR = "\t";
 
-    private Cookie(int layoutVersion, String bookieHost, String journalDirs, String ledgerDirs, String instanceId) {
+    private Cookie(int layoutVersion, String bookieId, String journalDirs, String ledgerDirs, String instanceId) {
         this.layoutVersion = layoutVersion;
-        this.bookieHost = bookieHost;
+        this.bookieId = bookieId;
         this.journalDirs = journalDirs;
         this.ledgerDirs = ledgerDirs;
         this.instanceId = instanceId;
@@ -130,7 +130,7 @@ public class Cookie {
             errMsg = "Cookie is of too old version " + c.layoutVersion;
             LOG.error(errMsg);
             throw new BookieException.InvalidCookieException(errMsg);
-        } else if (!(c.layoutVersion >= 3 && c.bookieHost.equals(bookieHost)
+        } else if (!(c.layoutVersion >= 3 && c.bookieId.equals(bookieId)
             && c.journalDirs.equals(journalDirs) && verifyLedgerDirs(c, checkIfSuperSet))) {
             errMsg = "Cookie [" + this + "] is not matching with [" + c + "]";
             throw new BookieException.InvalidCookieException(errMsg);
@@ -157,7 +157,7 @@ public class Cookie {
             return toStringVersion3();
         }
         CookieFormat.Builder builder = CookieFormat.newBuilder();
-        builder.setBookieHost(bookieHost);
+        builder.setBookieHost(bookieId);
         builder.setJournalDir(journalDirs);
         builder.setLedgerDirs(ledgerDirs);
         if (null != instanceId) {
@@ -172,7 +172,7 @@ public class Cookie {
     private String toStringVersion3() {
         StringBuilder b = new StringBuilder();
         b.append(CURRENT_COOKIE_LAYOUT_VERSION).append("\n")
-            .append(bookieHost).append("\n")
+            .append(bookieId).append("\n")
             .append(journalDirs).append("\n")
             .append(ledgerDirs).append("\n");
         return b.toString();
@@ -193,14 +193,14 @@ public class Cookie {
                     + "', cannot parse cookie.");
         }
         if (layoutVersion == 3) {
-            cBuilder.setBookieHost(reader.readLine());
+            cBuilder.setBookieId(reader.readLine());
             cBuilder.setJournalDirs(reader.readLine());
             cBuilder.setLedgerDirs(reader.readLine());
         } else if (layoutVersion >= 4) {
             CookieFormat.Builder cfBuilder = CookieFormat.newBuilder();
             TextFormat.merge(reader, cfBuilder);
             CookieFormat data = cfBuilder.build();
-            cBuilder.setBookieHost(data.getBookieHost());
+            cBuilder.setBookieId(data.getBookieHost());
             cBuilder.setJournalDirs(data.getJournalDir());
             cBuilder.setLedgerDirs(data.getLedgerDirs());
             // Since InstanceId is optional
@@ -293,7 +293,7 @@ public class Cookie {
             throws UnknownHostException {
         Builder builder = Cookie.newBuilder();
         builder.setLayoutVersion(CURRENT_COOKIE_LAYOUT_VERSION);
-        builder.setBookieHost(Bookie.getBookieId(conf).toString());
+        builder.setBookieId(Bookie.getBookieId(conf).toString());
         builder.setJournalDirs(Joiner.on(',').join(conf.getJournalDirNames()));
         builder.setLedgerDirs(encodeDirPaths(conf.getLedgerDirNames()));
         return builder;
@@ -364,15 +364,17 @@ public class Cookie {
      *         if the 'bookieHost' was created using a hostname
      */
     public boolean isBookieHostCreatedFromIp() throws IOException {
-        String[] parts = bookieHost.split(":");
+        String[] parts = bookieId.split(":");
         if (parts.length != 2) {
-            throw new IOException(bookieHost + " does not have the form host:port");
+            // custom BookieId ?
+            return false;
         }
         int port;
         try {
             port = Integer.parseInt(parts[1]);
         } catch (NumberFormatException e) {
-            throw new IOException(bookieHost + " does not have the form host:port");
+            // custom BookieId ?
+            return false;
         }
 
         InetSocketAddress addr = new InetSocketAddress(parts[0], port);
@@ -384,7 +386,7 @@ public class Cookie {
      */
     public static class Builder {
         private int layoutVersion = CURRENT_COOKIE_LAYOUT_VERSION;
-        private String bookieHost = null;
+        private String bookieId = null;
         private String journalDirs = null;
         private String ledgerDirs = null;
         private String instanceId = null;
@@ -392,10 +394,10 @@ public class Cookie {
         private Builder() {
         }
 
-        private Builder(int layoutVersion, String bookieHost, String journalDirs, String ledgerDirs,
+        private Builder(int layoutVersion, String bookieId, String journalDirs, String ledgerDirs,
                         String instanceId) {
             this.layoutVersion = layoutVersion;
-            this.bookieHost = bookieHost;
+            this.bookieId = bookieId;
             this.journalDirs = journalDirs;
             this.ledgerDirs = ledgerDirs;
             this.instanceId = instanceId;
@@ -406,8 +408,8 @@ public class Cookie {
             return this;
         }
 
-        public Builder setBookieHost(String bookieHost) {
-            this.bookieHost = bookieHost;
+        public Builder setBookieId(String bookieId) {
+            this.bookieId = bookieId;
             return this;
         }
 
@@ -427,7 +429,7 @@ public class Cookie {
         }
 
         public Cookie build() {
-            return new Cookie(layoutVersion, bookieHost, journalDirs, ledgerDirs, instanceId);
+            return new Cookie(layoutVersion, bookieId, journalDirs, ledgerDirs, instanceId);
         }
     }
 
@@ -447,7 +449,7 @@ public class Cookie {
      * @return cookie builder
      */
     public static Builder newBuilder(Cookie oldCookie) {
-        return new Builder(oldCookie.layoutVersion, oldCookie.bookieHost, oldCookie.journalDirs, oldCookie.ledgerDirs,
+        return new Builder(oldCookie.layoutVersion, oldCookie.bookieId, oldCookie.journalDirs, oldCookie.ledgerDirs,
                 oldCookie.instanceId);
     }
 }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
index 8cd3ef8..6dd2c9f 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
@@ -38,6 +38,7 @@ import org.apache.bookkeeper.common.conf.validators.RangeValidator;
 import org.apache.bookkeeper.common.util.ReflectionUtils;
 import org.apache.bookkeeper.discover.RegistrationManager;
 import org.apache.bookkeeper.discover.ZKRegistrationManager;
+import org.apache.bookkeeper.net.BookieId;
 import org.apache.bookkeeper.stats.NullStatsProvider;
 import org.apache.bookkeeper.stats.StatsProvider;
 import org.apache.commons.configuration.ConfigurationException;
@@ -148,6 +149,7 @@ public class ServerConfiguration extends AbstractConfiguration<ServerConfigurati
     protected static final String LISTENING_INTERFACE = "listeningInterface";
     protected static final String ALLOW_LOOPBACK = "allowLoopback";
     protected static final String ADVERTISED_ADDRESS = "advertisedAddress";
+    protected static final String BOOKIE_ID = "bookieId";
     protected static final String ALLOW_EPHEMERAL_PORTS = "allowEphemeralPorts";
 
     protected static final String JOURNAL_DIR = "journalDirectory";
@@ -1006,6 +1008,38 @@ public class ServerConfiguration extends AbstractConfiguration<ServerConfigurati
         return this;
     }
 
+     /**
+     * Get the configured BookieId for the bookie.
+     *
+     * <p>If present, this setting will take precedence over the
+     * automatic BookieId generation, based on Network Addresses.
+     *
+     * @see #setBookieId(java.lang.String)
+     * @see #getAdvertisedAddress()
+     * @return the configure address to be advertised
+     */
+    public String getBookieId() {
+        return this.getString(BOOKIE_ID, null);
+    }
+
+    /**
+     * Configure the bookie to advertise a specific BookieId.
+     *
+     * <p>By default, a bookie will advertise a BookieId computed
+     * from the primary network endpoint addresss.
+     *
+     * @see #getBookieId()
+     * @see #setAdvertisedAddress(java.lang.String)
+     * @param bookieId the bookie id
+     *
+     * @return server configuration
+     */
+    public ServerConfiguration setBookieId(String bookieId) {
+        BookieId.parse(bookieId);
+        this.setProperty(BOOKIE_ID, bookieId);
+        return this;
+    }
+
     /**
      * Get the configured advertised address for the bookie.
      *
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/ZKRegistrationClient.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/ZKRegistrationClient.java
index dc17507..dd9bac1 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/ZKRegistrationClient.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/ZKRegistrationClient.java
@@ -258,7 +258,9 @@ public class ZKRegistrationClient implements RegistrationClient {
                     bookieServiceInfoCache.put(bookieId, result);
                     promise.complete(result);
                 } catch (IOException ex) {
-                    promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc), path));
+                    log.error("Cannot update BookieInfo for {}", ex);
+                    promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc), path)
+                            .initCause(ex));
                     return;
                 }
             } else if (KeeperException.Code.NONODE.intValue() == rc) {
@@ -273,7 +275,9 @@ public class ZKRegistrationClient implements RegistrationClient {
                             bookieServiceInfoCache.put(bookieId, result);
                             promise.complete(result);
                         } catch (IOException ex) {
-                            promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc2), path2));
+                            log.error("Cannot update BookieInfo for {}", ex);
+                            promise.completeExceptionally(KeeperException.create(KeeperException.Code.get(rc2), path2)
+                                    .initCause(ex));
                             return;
                         }
                     } else {
@@ -343,14 +347,18 @@ public class ZKRegistrationClient implements RegistrationClient {
                     bookieInfoUpdated.add(readBookieServiceInfo(id));
                 }
             }
-            FutureUtils
-                    .collect(bookieInfoUpdated)
-                    .whenComplete((List<Versioned<BookieServiceInfo>> info, Throwable error) -> {
-                        // we are ignoring errors intentionally
-                        // there could be bookies that published unparseable information
-                        // or other temporary/permanent or temporary errors
-                        future.complete(new Versioned<>(bookies, version));
-                    });
+            if (bookieInfoUpdated.isEmpty()) {
+                future.complete(new Versioned<>(bookies, version));
+            } else {
+                FutureUtils
+                        .collect(bookieInfoUpdated)
+                        .whenComplete((List<Versioned<BookieServiceInfo>> info, Throwable error) -> {
+                            // we are ignoring errors intentionally
+                            // there could be bookies that publish unparseable information
+                            // or other temporary/permanent errors
+                            future.complete(new Versioned<>(bookies, version));
+                        });
+            }
         }, null);
         return future;
     }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/net/BookieSocketAddress.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/net/BookieSocketAddress.java
index 06da0dc..3e3fb85 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/net/BookieSocketAddress.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/net/BookieSocketAddress.java
@@ -24,7 +24,6 @@ import static org.apache.bookkeeper.util.BookKeeperConstants.COLON;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.google.common.net.InetAddresses;
-import io.netty.channel.local.LocalAddress;
 
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
@@ -106,15 +105,6 @@ public class BookieSocketAddress {
         });
     }
 
-    /**
-     * Maps the socketAddress to a "local" address.
-     */
-    @JsonIgnore
-    public LocalAddress getLocalAddress() {
-        // for local address, we just need "port" to differentiate different addresses.
-        return new LocalAddress("" + port);
-    }
-
     // Return the String "serialized" version of this object.
     @Override
     public String toString() {
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
index a48f749..d6e6f21 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
@@ -44,6 +44,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel;
 import io.netty.channel.group.ChannelGroup;
 import io.netty.channel.group.ChannelGroupFuture;
 import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.channel.local.LocalAddress;
 import io.netty.channel.local.LocalChannel;
 import io.netty.channel.local.LocalServerChannel;
 import io.netty.channel.socket.SocketChannel;
@@ -77,6 +78,7 @@ import org.apache.bookkeeper.bookie.BookieException;
 import org.apache.bookkeeper.common.collections.BlockingMpscQueue;
 import org.apache.bookkeeper.common.util.affinity.CpuAffinity;
 import org.apache.bookkeeper.conf.ServerConfiguration;
+import org.apache.bookkeeper.net.BookieId;
 import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.processor.RequestProcessor;
 import org.apache.bookkeeper.util.ByteBufList;
@@ -103,6 +105,7 @@ class BookieNettyServer {
     volatile boolean suspended = false;
     ChannelGroup allChannels;
     final BookieSocketAddress bookieAddress;
+    final BookieId bookieId;
     final InetSocketAddress bindAddress;
 
     final BookieAuthProvider.Factory authProviderFactory;
@@ -160,7 +163,7 @@ class BookieNettyServer {
         } else {
             jvmEventLoopGroup = null;
         }
-
+        bookieId = Bookie.getBookieId(conf);
         bookieAddress = Bookie.getBookieAddress(conf);
         if (conf.getListeningInterface() == null) {
             bindAddress = new InetSocketAddress(conf.getBookiePort());
@@ -410,10 +413,10 @@ class BookieNettyServer {
                     pipeline.addLast("contextHandler", contextHandler);
                 }
             });
-
+            LOG.info("Binding jvm bookie-rpc endpoint to {}", bookieId.toString());
             // use the same address 'name', so clients can find local Bookie still discovering them using ZK
-            jvmBootstrap.bind(bookieAddress.getLocalAddress()).sync();
-            LocalBookiesRegistry.registerLocalBookieAddress(bookieAddress.toBookieId());
+            jvmBootstrap.bind(new LocalAddress(bookieId.toString())).sync();
+            LocalBookiesRegistry.registerLocalBookieAddress(bookieId);
         }
     }
 
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieServer.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieServer.java
index 2864b29..ee83327 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieServer.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieServer.java
@@ -44,6 +44,7 @@ import org.apache.bookkeeper.common.allocator.ByteBufAllocatorBuilder;
 import org.apache.bookkeeper.common.util.JsonUtil.ParseJsonException;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.apache.bookkeeper.discover.BookieServiceInfo;
+import org.apache.bookkeeper.discover.BookieServiceInfoUtils;
 import org.apache.bookkeeper.net.BookieId;
 import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.processor.RequestProcessor;
@@ -85,13 +86,23 @@ public class BookieServer {
     public BookieServer(ServerConfiguration conf) throws IOException,
             KeeperException, InterruptedException, BookieException,
             UnavailableException, CompatibilityException, SecurityException {
-        this(conf, NullStatsLogger.INSTANCE, BookieServiceInfo.NO_INFO);
+        this(conf, NullStatsLogger.INSTANCE, null);
     }
 
     public BookieServer(ServerConfiguration conf, StatsLogger statsLogger,
             Supplier<BookieServiceInfo> bookieServiceInfoProvider)
             throws IOException, KeeperException, InterruptedException,
             BookieException, UnavailableException, CompatibilityException, SecurityException {
+        if (bookieServiceInfoProvider == null) {
+            bookieServiceInfoProvider = () -> {
+                try {
+                    return BookieServiceInfoUtils
+                            .buildLegacyBookieServiceInfo(this.getLocalAddress().toBookieId().toString());
+                } catch (IOException err) {
+                    throw new RuntimeException(err);
+                }
+            };
+        }
         this.conf = conf;
         validateUser(conf);
         String configAsString;
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
index 45650b2..45d42c5 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
@@ -46,6 +46,7 @@ import io.netty.channel.EventLoopGroup;
 import io.netty.channel.WriteBufferWaterMark;
 import io.netty.channel.epoll.EpollEventLoopGroup;
 import io.netty.channel.epoll.EpollSocketChannel;
+import io.netty.channel.local.LocalAddress;
 import io.netty.channel.local.LocalChannel;
 import io.netty.channel.socket.nio.NioSocketChannel;
 import io.netty.channel.unix.Errors.NativeIoException;
@@ -599,7 +600,7 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
 
         SocketAddress bookieAddr = addr.getSocketAddress();
         if (eventLoopGroup instanceof DefaultEventLoopGroup) {
-            bookieAddr = addr.getLocalAddress();
+            bookieAddr = new LocalAddress(bookieId.toString());
         }
 
         ChannelFuture future = bootstrap.connect(bookieAddr);
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/SimpleBookieServiceInfoProvider.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/SimpleBookieServiceInfoProvider.java
new file mode 100644
index 0000000..2231b95
--- /dev/null
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/SimpleBookieServiceInfoProvider.java
@@ -0,0 +1,54 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ *
+ */
+package org.apache.bookkeeper.proto;
+
+import java.net.UnknownHostException;
+import java.util.function.Supplier;
+import org.apache.bookkeeper.bookie.Bookie;
+import org.apache.bookkeeper.conf.ServerConfiguration;
+import org.apache.bookkeeper.discover.BookieServiceInfo;
+import org.apache.bookkeeper.discover.BookieServiceInfoUtils;
+import org.apache.bookkeeper.net.BookieSocketAddress;
+
+/**
+ * Simple Implementation of BookieServiceInfo supplier.
+ */
+public class SimpleBookieServiceInfoProvider implements Supplier<BookieServiceInfo> {
+    private final BookieSocketAddress bookieSocketAddress;
+
+    public SimpleBookieServiceInfoProvider(ServerConfiguration serverConfiguration) {
+        try {
+            this.bookieSocketAddress = Bookie.getBookieAddress(serverConfiguration);
+        } catch (UnknownHostException err) {
+            throw new RuntimeException(err);
+        }
+    }
+
+    @Override
+    public BookieServiceInfo get() {
+        try {
+            return BookieServiceInfoUtils.buildLegacyBookieServiceInfo(bookieSocketAddress.toBookieId().toString());
+        } catch (UnknownHostException err) {
+            throw new RuntimeException(err);
+        }
+    }
+
+}
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/AutoRecoveryMain.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/AutoRecoveryMain.java
index 303a401..1ccb322 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/AutoRecoveryMain.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/AutoRecoveryMain.java
@@ -100,7 +100,7 @@ public class AutoRecoveryMain {
         });
 
         auditorElector = new AuditorElector(
-            Bookie.getBookieAddress(conf).toString(),
+            Bookie.getBookieId(conf).toString(),
             conf,
             bkc,
             statsLogger.scope(AUDITOR_SCOPE),
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/cookie/AdminCommand.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/cookie/AdminCommand.java
index 5cdefd0..7429afc 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/cookie/AdminCommand.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/cookie/AdminCommand.java
@@ -160,7 +160,7 @@ public class AdminCommand extends BookieCommand<AdminCommand.AdminFlags> {
                               useHostname, nne);
                     return false;
                 }
-                Cookie newCookie = Cookie.newBuilder(oldCookie.getValue()).setBookieHost(newBookieId).build();
+                Cookie newCookie = Cookie.newBuilder(oldCookie.getValue()).setBookieId(newBookieId).build();
 
                 boolean hasCookieUpdatedInDirs = verifyCookie(newCookie, journalDirectories[0]);
                 for (File dir : ledgerDirectories) {
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/cookie/GenerateCookieCommand.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/cookie/GenerateCookieCommand.java
index 3ef8116..a5997b0 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/cookie/GenerateCookieCommand.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tools/cli/commands/cookie/GenerateCookieCommand.java
@@ -110,7 +110,7 @@ public class GenerateCookieCommand extends CookieCommand<Flags> {
         }
 
         Builder builder = Cookie.newBuilder();
-        builder.setBookieHost(bookieId.toString());
+        builder.setBookieId(bookieId.toString());
         if (StringUtils.isEmpty(instanceId)) {
             builder.setInstanceId(null);
         } else {
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/LocalBookKeeper.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/LocalBookKeeper.java
index 1c87284..d9570ff 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/LocalBookKeeper.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/LocalBookKeeper.java
@@ -254,7 +254,7 @@ public class LocalBookKeeper {
             bsConfs[i].setLedgerDirNames(ledgerDirs);
 
             // write config into file before start so we can know what's wrong if start failed
-            String fileName = Bookie.getBookieAddress(bsConfs[i]).toString() + ".conf";
+            String fileName = Bookie.getBookieId(bsConfs[i]).toString() + ".conf";
             serializeLocalBookieConfig(bsConfs[i], fileName);
 
             // Mimic BookKeeper Main
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/AdvertisedAddressTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/AdvertisedAddressTest.java
index ad522c7..2b02883 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/AdvertisedAddressTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/AdvertisedAddressTest.java
@@ -27,6 +27,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Collection;
 
+import java.util.UUID;
 import org.apache.bookkeeper.client.BookKeeperAdmin;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.apache.bookkeeper.conf.TestBKConfiguration;
@@ -105,4 +106,38 @@ public class AdvertisedAddressTest extends BookKeeperClusterTestCase {
         assertEquals(bkAddress.toBookieId(), Bookie.getBookieId(conf));
     }
 
+    /**
+     * Test starting bookie with a bookieId.
+     */
+    @Test
+    public void testSetBookieId() throws Exception {
+        String uuid = UUID.randomUUID().toString();
+        ServerConfiguration conf = TestBKConfiguration.newServerConfiguration();
+        conf.setJournalDirName(newDirectory(false))
+            .setLedgerDirNames(new String[] { newDirectory(false) })
+            .setBookiePort(bookiePort)
+            .setBookieId(uuid)
+            .setMetadataServiceUri(zkUtil.getMetadataServiceUri());
+
+        conf.setAdvertisedAddress("10.0.0.1");
+        assertEquals("10.0.0.1", conf.getAdvertisedAddress());
+        assertEquals(uuid, conf.getBookieId());
+
+        BookieSocketAddress bkAddress = new BookieSocketAddress("10.0.0.1", bookiePort);
+        assertEquals(bkAddress, Bookie.getBookieAddress(conf));
+        assertEquals(uuid, Bookie.getBookieId(conf).getId());
+
+        Bookie b = new Bookie(conf);
+        b.start();
+
+        BookKeeperAdmin bka = new BookKeeperAdmin(baseClientConf);
+        Collection<BookieId> bookies = bka.getAvailableBookies();
+
+        assertEquals(1, bookies.size());
+        BookieId address = bookies.iterator().next();
+        assertEquals(BookieId.parse(uuid), address);
+
+        b.shutdown();
+        bka.close();
+    }
 }
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/BookieShellTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/BookieShellTest.java
index 8ab38c1..6fb759b 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/BookieShellTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/BookieShellTest.java
@@ -140,7 +140,7 @@ public class BookieShellTest {
         when(admin.getConf()).thenReturn(this.clientConf);
         this.rm = PowerMockito.mock(RegistrationManager.class);
         this.cookie = Cookie.newBuilder()
-            .setBookieHost("127.0.0.1:3181")
+            .setBookieId("127.0.0.1:3181")
             .setInstanceId("xyz")
             .setJournalDirs("/path/to/journal/dir")
             .setLedgerDirs("/path/to/journal/dir")
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/UpdateCookieCmdTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/UpdateCookieCmdTest.java
index e0d37bb..840f2bd 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/UpdateCookieCmdTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/UpdateCookieCmdTest.java
@@ -54,6 +54,7 @@ public class UpdateCookieCmdTest extends BookKeeperClusterTestCase {
 
     public UpdateCookieCmdTest() {
         super(1);
+        useUUIDasBookieId = false;
     }
 
     @Override
@@ -148,7 +149,7 @@ public class UpdateCookieCmdTest extends BookKeeperClusterTestCase {
         Cookie.Builder cookieBuilder = Cookie.newBuilder(cookie);
         conf.setUseHostNameAsBookieID(false); // sets to hostname
         final String newBookieHost = Bookie.getBookieAddress(conf).toString();
-        cookieBuilder.setBookieHost(newBookieHost);
+        cookieBuilder.setBookieId(newBookieHost);
         cookieBuilder.build().writeToRegistrationManager(rm, conf, Version.NEW);
         verifyCookieInZooKeeper(conf, 2);
 
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookKeeperAdminTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookKeeperAdminTest.java
index 6d2b972..f6477d4 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookKeeperAdminTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookKeeperAdminTest.java
@@ -210,7 +210,7 @@ public class BookKeeperAdminTest extends BookKeeperClusterTestCase {
         }
         Assert.assertFalse("initBookie shouldn't have succeeded, since cookie in ZK is not deleted yet",
                 BookKeeperAdmin.initBookie(confOfExistingBookie));
-        String bookieId = Bookie.getBookieAddress(confOfExistingBookie).toString();
+        String bookieId = Bookie.getBookieId(confOfExistingBookie).toString();
         String bookieCookiePath =
             ZKMetadataDriverBase.resolveZkLedgersRootPath(confOfExistingBookie)
                 + "/" + BookKeeperConstants.COOKIE_NODE
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestGetBookieInfoTimeout.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestGetBookieInfoTimeout.java
index 8541420..3a97461 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestGetBookieInfoTimeout.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/TestGetBookieInfoTimeout.java
@@ -38,8 +38,6 @@ import org.apache.bookkeeper.client.BookieInfoReader.BookieInfo;
 import org.apache.bookkeeper.common.util.OrderedExecutor;
 import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.net.BookieId;
-import org.apache.bookkeeper.net.BookieSocketAddress;
-import org.apache.bookkeeper.proto.BookieAddressResolver;
 import org.apache.bookkeeper.proto.BookieClient;
 import org.apache.bookkeeper.proto.BookieClientImpl;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GetBookieInfoCallback;
@@ -108,10 +106,9 @@ public class TestGetBookieInfoTimeout extends BookKeeperClusterTestCase {
         CountDownLatch latch = sleepBookie(bookieToSleep, sleeptime);
         latch.await();
 
-        BookieAddressResolver bookieAddressResolver = BookieSocketAddress.LEGACY_BOOKIEID_RESOLVER;
         // try to get bookie info from the sleeping bookie. It should fail with timeout error
         BookieClient bc = new BookieClientImpl(cConf, eventLoopGroup, UnpooledByteBufAllocator.DEFAULT, executor,
-                scheduler, NullStatsLogger.INSTANCE, bookieAddressResolver);
+                scheduler, NullStatsLogger.INSTANCE, bkc.getBookieAddressResolver());
         long flags = BookkeeperProtocol.GetBookieInfoRequest.Flags.FREE_DISK_SPACE_VALUE
                 | BookkeeperProtocol.GetBookieInfoRequest.Flags.TOTAL_DISK_CAPACITY_VALUE;
 
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/UpdateLedgerCmdTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/UpdateLedgerCmdTest.java
index 1a849ae..cad0718 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/UpdateLedgerCmdTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/UpdateLedgerCmdTest.java
@@ -54,6 +54,7 @@ public class UpdateLedgerCmdTest extends BookKeeperClusterTestCase {
 
     public UpdateLedgerCmdTest() {
         super(3);
+        useUUIDasBookieId = false;
         baseConf.setGcWaitTime(100000);
     }
 
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/UpdateLedgerOpTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/UpdateLedgerOpTest.java
index 6c08ddd..788922d 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/UpdateLedgerOpTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/UpdateLedgerOpTest.java
@@ -57,6 +57,7 @@ public class UpdateLedgerOpTest extends BookKeeperClusterTestCase {
 
     public UpdateLedgerOpTest() {
         super(3);
+        useUUIDasBookieId = false;
         baseConf.setGcWaitTime(100000);
     }
 
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPeriodicCheckTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPeriodicCheckTest.java
index 01ee5d8..8ea6636 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPeriodicCheckTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPeriodicCheckTest.java
@@ -338,7 +338,7 @@ public class AuditorPeriodicCheckTest extends BookKeeperClusterTestCase {
         }
 
         try (final Auditor auditor = new Auditor(
-                Bookie.getBookieAddress(bsConfs.get(0)).toString(),
+                Bookie.getBookieId(bsConfs.get(0)).toString(),
                 bsConfs.get(0), NullStatsLogger.INSTANCE)) {
             final AtomicBoolean exceptionCaught = new AtomicBoolean(false);
             final CountDownLatch latch = new CountDownLatch(1);
@@ -401,7 +401,7 @@ public class AuditorPeriodicCheckTest extends BookKeeperClusterTestCase {
         servConf.setAuditorPeriodicCheckInterval(auditorPeriodicCheckInterval);
         servConf.setAuditorPeriodicPlacementPolicyCheckInterval(0);
         servConf.setAuditorPeriodicBookieCheckInterval(0);
-        final TestAuditor auditor = new TestAuditor(Bookie.getBookieAddress(servConf).toString(), servConf, bkc, false,
+        final TestAuditor auditor = new TestAuditor(Bookie.getBookieId(servConf).toString(), servConf, bkc, false,
                 statsLogger);
         CountDownLatch latch = auditor.getLatch();
         assertEquals("CHECK_ALL_LEDGERS_TIME SuccessCount", 0, checkAllLedgersStatsLogger.getSuccessCount());
@@ -494,7 +494,7 @@ public class AuditorPeriodicCheckTest extends BookKeeperClusterTestCase {
         servConf.setAuditorPeriodicPlacementPolicyCheckInterval(auditorPeriodicPlacementPolicyCheckInterval);
         servConf.setAuditorPeriodicCheckInterval(0);
         servConf.setAuditorPeriodicBookieCheckInterval(0);
-        final TestAuditor auditor = new TestAuditor(Bookie.getBookieAddress(servConf).toString(), servConf, bkc, false,
+        final TestAuditor auditor = new TestAuditor(Bookie.getBookieId(servConf).toString(), servConf, bkc, false,
                 statsLogger);
         CountDownLatch latch = auditor.getLatch();
         assertEquals("PLACEMENT_POLICY_CHECK_TIME SuccessCount", 0, placementPolicyCheckStatsLogger.getSuccessCount());
@@ -598,7 +598,7 @@ public class AuditorPeriodicCheckTest extends BookKeeperClusterTestCase {
         servConf.setAuditorPeriodicReplicasCheckInterval(auditorPeriodicReplicasCheckInterval);
         servConf.setAuditorPeriodicCheckInterval(0);
         servConf.setAuditorPeriodicBookieCheckInterval(0);
-        final TestAuditor auditor = new TestAuditor(Bookie.getBookieAddress(servConf).toString(), servConf, bkc, false,
+        final TestAuditor auditor = new TestAuditor(Bookie.getBookieId(servConf).toString(), servConf, bkc, false,
                 statsLogger);
         CountDownLatch latch = auditor.getLatch();
         assertEquals("REPLICAS_CHECK_TIME SuccessCount", 0, replicasCheckStatsLogger.getSuccessCount());
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPlacementPolicyCheckTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPlacementPolicyCheckTest.java
index 2f8e7e0..3c8d0c4 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPlacementPolicyCheckTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorPlacementPolicyCheckTest.java
@@ -672,7 +672,7 @@ public class AuditorPlacementPolicyCheckTest extends BookKeeperClusterTestCase {
         TestOpStatsLogger placementPolicyCheckStatsLogger = (TestOpStatsLogger) statsLogger
                 .getOpStatsLogger(ReplicationStats.PLACEMENT_POLICY_CHECK_TIME);
 
-        final TestAuditor auditor = new TestAuditor(Bookie.getBookieAddress(servConf).toString(), servConf,
+        final TestAuditor auditor = new TestAuditor(Bookie.getBookieId(servConf).toString(), servConf,
                 statsLogger);
         auditorRef.setValue(auditor);
         CountDownLatch latch = auditor.getLatch();
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorReplicasCheckTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorReplicasCheckTest.java
index abf439f..8d54113 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorReplicasCheckTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuditorReplicasCheckTest.java
@@ -149,7 +149,7 @@ public class AuditorReplicasCheckTest extends BookKeeperClusterTestCase {
         TestOpStatsLogger replicasCheckStatsLogger = (TestOpStatsLogger) statsLogger
                 .getOpStatsLogger(ReplicationStats.REPLICAS_CHECK_TIME);
 
-        final TestAuditor auditor = new TestAuditor(Bookie.getBookieAddress(servConf).toString(), servConf, bkc, true,
+        final TestAuditor auditor = new TestAuditor(Bookie.getBookieId(servConf).toString(), servConf, bkc, true,
                 new TestBookKeeperAdmin(bkc, statsLogger, expectedReturnAvailabilityOfEntriesOfLedger,
                         errorReturnValueForGetAvailabilityOfEntriesOfLedger),
                 true, statsLogger);
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BookKeeperClusterTestCase.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BookKeeperClusterTestCase.java
index 78a3b11..2156859 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BookKeeperClusterTestCase.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/BookKeeperClusterTestCase.java
@@ -37,6 +37,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Future;
 import java.util.concurrent.SynchronousQueue;
@@ -99,6 +100,7 @@ public abstract class BookKeeperClusterTestCase {
     private final Map<BookieId, TestStatsProvider> bsLoggers = new HashMap<>();
     protected int numBookies;
     protected BookKeeperTestClient bkc;
+    protected boolean useUUIDasBookieId = true;
 
     /*
      * Loopback interface is set as the listening interface and allowloopback is
@@ -632,6 +634,12 @@ public abstract class BookKeeperClusterTestCase {
     public int startNewBookie()
             throws Exception {
         ServerConfiguration conf = newServerConfiguration();
+
+        // use a random BookieId
+        if (useUUIDasBookieId) {
+            conf.setBookieId(UUID.randomUUID().toString());
+        }
+
         bsConfs.add(conf);
         LOG.info("Starting new bookie on port: {}", conf.getBookiePort());
         BookieServer server = startBookie(conf);
@@ -661,8 +669,7 @@ public abstract class BookKeeperClusterTestCase {
     protected BookieServer startBookie(ServerConfiguration conf)
             throws Exception {
         TestStatsProvider provider = new TestStatsProvider();
-        BookieServer server = new BookieServer(conf, provider.getStatsLogger(""),
-                                               BookieServiceInfo.NO_INFO);
+        BookieServer server = new BookieServer(conf, provider.getStatsLogger(""), null);
         BookieId address = Bookie.getBookieId(conf);
         bsLoggers.put(address, provider);
 
@@ -696,8 +703,7 @@ public abstract class BookKeeperClusterTestCase {
     protected BookieServer startBookie(ServerConfiguration conf, final Bookie b)
             throws Exception {
         TestStatsProvider provider = new TestStatsProvider();
-        BookieServer server = new BookieServer(conf, provider.getStatsLogger(""),
-                                        BookieServiceInfo.NO_INFO) {
+        BookieServer server = new BookieServer(conf, provider.getStatsLogger(""), null) {
             @Override
             protected Bookie newBookie(ServerConfiguration conf, ByteBufAllocator allocator,
                                        Supplier<BookieServiceInfo> s) {
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/tls/TestTLS.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/tls/TestTLS.java
index dc9ce40..37f6e25 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/tls/TestTLS.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/tls/TestTLS.java
@@ -60,6 +60,7 @@ import org.apache.bookkeeper.net.BookieId;
 import org.apache.bookkeeper.proto.BookieConnectionPeer;
 import org.apache.bookkeeper.proto.BookieServer;
 import org.apache.bookkeeper.proto.ClientConnectionPeer;
+import org.apache.bookkeeper.proto.PerChannelBookieClient;
 import org.apache.bookkeeper.proto.TestPerChannelBookieClient;
 import org.apache.bookkeeper.test.BookKeeperClusterTestCase;
 import org.apache.bookkeeper.test.TestStatsProvider;
@@ -856,11 +857,7 @@ public class TestTLS extends BookKeeperClusterTestCase {
             InetSocketAddress addr = bookie.getLocalAddress().getSocketAddress();
             StringBuilder nameBuilder = new StringBuilder(BookKeeperClientStats.CHANNEL_SCOPE)
                     .append(".")
-                    .append(addr.getAddress().getHostAddress()
-                    .replace('.', '_')
-                    .replace('-', '_'))
-                    .append("_")
-                    .append(addr.getPort())
+                    .append(PerChannelBookieClient.buildStatsLoggerScopeName(bookie.getBookieId()))
                     .append(".");
 
             // check stats on TLS enabled client
@@ -959,11 +956,7 @@ public class TestTLS extends BookKeeperClusterTestCase {
         InetSocketAddress addr = bookie.getLocalAddress().getSocketAddress();
         StringBuilder nameBuilder = new StringBuilder(BookKeeperClientStats.CHANNEL_SCOPE)
                 .append(".")
-                .append(addr.getAddress().getHostAddress()
-                        .replace('.', '_')
-                        .replace('-', '_'))
-                .append("_")
-                .append(addr.getPort())
+                .append(PerChannelBookieClient.buildStatsLoggerScopeName(bookie.getBookieId()))
                 .append(".");
 
         assertEquals("TLS handshake failure expected", 1,
diff --git a/conf/bk_server.conf b/conf/bk_server.conf
index e6e3558..e585777 100755
--- a/conf/bk_server.conf
+++ b/conf/bk_server.conf
@@ -33,6 +33,10 @@
 ## Server parameters
 #############################################################################
 
+# Unique ID for the bookie, if it is not set if will be computed from the network address
+# of the Bookie.
+#bookieId=
+
 # The port that the bookie server listens on.
 bookiePort=3181
 
diff --git a/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/AdminCommandTest.java b/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/AdminCommandTest.java
index b9c0a09..2d710ad 100644
--- a/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/AdminCommandTest.java
+++ b/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/AdminCommandTest.java
@@ -131,7 +131,7 @@ public class AdminCommandTest extends BookieCommandTestBase {
         when(cookieVersioned.getValue()).thenReturn(cookie);
         Cookie.Builder builder = mock(Cookie.Builder.class);
         PowerMockito.when(Cookie.newBuilder(eq(cookie))).thenReturn(builder);
-        PowerMockito.when(builder.setBookieHost(anyString())).thenReturn(builder);
+        PowerMockito.when(builder.setBookieId(anyString())).thenReturn(builder);
         when(builder.build()).thenReturn(cookie);
 
         PowerMockito.when(serverConfiguration.setUseHostNameAsBookieID(anyBoolean())).thenReturn(serverConfiguration);
diff --git a/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/GenerateCookieCommandTest.java b/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/GenerateCookieCommandTest.java
index 5b571df..7a39d2b 100644
--- a/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/GenerateCookieCommandTest.java
+++ b/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/GenerateCookieCommandTest.java
@@ -136,7 +136,7 @@ public class GenerateCookieCommandTest extends CookieCommandTestBase {
         String instanceId = "test-instance-id";
 
         Cookie cookie = Cookie.newBuilder()
-            .setBookieHost(BOOKIE_ID)
+            .setBookieId(BOOKIE_ID)
             .setInstanceId(instanceId)
             .setJournalDirs(journalDir)
             .setLedgerDirs(Cookie.encodeDirPaths(ledgersDir.split(",")))
@@ -172,7 +172,7 @@ public class GenerateCookieCommandTest extends CookieCommandTestBase {
         String instanceId = "test-instance-id";
 
         Cookie cookie = Cookie.newBuilder()
-            .setBookieHost(BOOKIE_ID)
+            .setBookieId(BOOKIE_ID)
             .setInstanceId(instanceId)
             .setJournalDirs(journalDir)
             .setLedgerDirs(Cookie.encodeDirPaths(ledgersDir.split(",")))
diff --git a/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/GetCookieCommandTest.java b/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/GetCookieCommandTest.java
index 4c55507..36f9d7f 100644
--- a/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/GetCookieCommandTest.java
+++ b/tools/ledger/src/test/java/org/apache/bookkeeper/tools/cli/commands/cookie/GetCookieCommandTest.java
@@ -96,7 +96,7 @@ public class GetCookieCommandTest extends CookieCommandTestBase {
     @Test
     public void testGetCookieFromExistentCookieFile() throws Exception {
         Cookie cookie = Cookie.newBuilder()
-            .setBookieHost(BOOKIE_ID)
+            .setBookieId(BOOKIE_ID)
             .setInstanceId("test-instance-id")
             .setJournalDirs("/path/to/journal/dir")
             .setLedgerDirs("/path/to/ledger/dirs")