You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2019/04/10 16:19:05 UTC

[logging-log4j2] branch release-2.x updated: LOG4J2-2586 - TCP Appender should support a host name resolving to multiple IP addresses.

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

rgoers pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/release-2.x by this push:
     new 741e21e  LOG4J2-2586 - TCP Appender should support a host name resolving to multiple IP addresses.
741e21e is described below

commit 741e21ecdf294de340f6461850ca10cd98a24cbb
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Wed Apr 10 09:18:53 2019 -0700

    LOG4J2-2586 - TCP Appender should support a host name resolving to multiple IP addresses.
---
 log4j-core/revapi.json                             | 356 ++-------------------
 .../logging/log4j/core/net/SslSocketManager.java   |  23 +-
 .../logging/log4j/core/net/TcpSocketManager.java   |  93 +++++-
 .../log4j/core/net/SocketReconnectTest.java        | 260 +++++++++++----
 log4j-core/src/test/resources/log4j-socket.xml     |   6 +-
 src/changes/changes.xml                            |   3 +
 src/site/xdoc/manual/appenders.xml                 |  11 +-
 7 files changed, 353 insertions(+), 399 deletions(-)

diff --git a/log4j-core/revapi.json b/log4j-core/revapi.json
index 9f6aef1..ae62904 100644
--- a/log4j-core/revapi.json
+++ b/log4j-core/revapi.json
@@ -31,346 +31,52 @@
     "extension": "revapi.ignore",
     "configuration": [
       {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.AsyncAppender.Builder org.apache.logging.log4j.core.appender.AsyncAppender.Builder::setFilter(org.apache.logging.log4j.core.Filter)",
-        "new": "method B org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B>>>::setFilter(org.apache.logging.log4j.core.Filter) @ org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B extends org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B extends org.apache.logging.log4j.core.appender.AsyncAppender.Buil [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.AsyncAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B extends org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.generics.elementNowParameterized",
-        "old": "class org.apache.logging.log4j.core.appender.AsyncAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B extends org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.generics.formalTypeParameterAdded",
-        "old": "class org.apache.logging.log4j.core.appender.AsyncAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B extends org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B>>",
-        "typeParameter": "B extends org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B extends org.apache.logging.log4j.core.appender.AsyncAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.annotation.attributeAdded",
-        "old": "parameter org.apache.logging.log4j.core.appender.NullAppender org.apache.logging.log4j.core.appender.NullAppender::createAppender(===java.lang.String===)",
-        "new": "parameter org.apache.logging.log4j.core.appender.NullAppender org.apache.logging.log4j.core.appender.NullAppender::createAppender(===java.lang.String===)",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginAttribute(value = \"name\", defaultString = \"null\")",
-        "attribute": "defaultString",
-        "justification": "LOG4J2-2447 - Allow NullAppender to default its name to null"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder::setFilter(org.apache.logging.log4j.core.Filter)",
-        "new": "method B org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B>>>::setFilter(org.apache.logging.log4j.core.Filter) @ org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.Outp [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder::setFollow(boolean)",
-        "new": "method B org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>>::setFollow(boolean)",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder::setIgnoreExceptions(boolean)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setIgnoreExceptions(boolean) @ org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Bu [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder::setLayout(org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setLayout(org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>) @ org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache. [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder::setName(java.lang.String)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setName(java.lang.String) @ org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Build [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder::setTarget(java.io.OutputStream)",
-        "new": "method B org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>>::setTarget(java.io.OutputStream)",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.generics.elementNowParameterized",
-        "old": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.generics.formalTypeParameterAdded",
-        "old": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "typeParameter": "B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender.Builder::setFilter(org.apache.logging.log4j.core.Filter)",
-        "new": "method B org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B>>>::setFilter(org.apache.logging.log4j.core.Filter) @ org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.B [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender.Builder::setFollow(boolean)",
-        "new": "method B org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>>::setFollow(boolean)",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender.Builder::setIgnoreExceptions(boolean)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setIgnoreExceptions(boolean) @ org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.parameterTypeChanged",
-        "old": "parameter org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender.Builder::setLayout(===org.apache.logging.log4j.core.StringLayout===)",
-        "new": "parameter B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setLayout(===org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>===) @ org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.log [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender.Builder::setLayout(org.apache.logging.log4j.core.StringLayout)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setLayout(org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>) @ org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4 [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender.Builder::setName(java.lang.String)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setName(java.lang.String) @ org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender.Builder::setTarget(java.io.Writer)",
-        "new": "method B org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>>::setTarget(java.io.Writer)",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.WriterAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.WriterAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.generics.elementNowParameterized",
-        "old": "class org.apache.logging.log4j.core.appender.WriterAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.generics.formalTypeParameterAdded",
-        "old": "class org.apache.logging.log4j.core.appender.WriterAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>",
-        "typeParameter": "B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender.Builder<B extends org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender.Builder<B>>",
-        "new": "class org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender.Builder<B extends org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender.Builder<B extends org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
         "code": "java.method.numberOfParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager::getManager(java.lang.String, int, org.apache.logging.log4j.core.appender.db.jdbc.ConnectionSource, java.lang.String, org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig[], org.apache.logging.log4j.core.appender.db.ColumnMapping[])",
-        "new": "method org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager::getManager(java.lang.String, int, org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>, org.apache.logging.log4j.core.appender.db.jdbc.ConnectionSource, java.lang.String, org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig[], org.apache.logging.log4j.core.appender.db.ColumnMapping[], boolean, long)",
-        "justification": "LOG4J2-2500 - Allow a JDBC Appender to truncate string to match a table's metadata column length limit"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder::setFilter(org.apache.logging.log4j.core.Filter)",
-        "new": "method B org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B>>>::setFilter(org.apache.logging.log4j.core.Filter) @ org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppende [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
+        "old": "method java.net.Socket org.apache.logging.log4j.core.net.SslSocketManager::createSocket(java.lang.String, int) throws java.io.IOException",
+        "new": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.net.InetSocketAddress, org.apache.logging.log4j.core.net.SocketOptions, int) throws java.io.IOException @ org.apache.logging.log4j.core.net.SslSocketManager",
+        "justification": "LOG4J2-2586 - Support the host name resolving to mulitple ip addresses"
       },
       {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder::setIgnoreExceptions(boolean)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setIgnoreExceptions(boolean) @ org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
+        "code": "java.method.nowStatic",
+        "old": "method java.net.Socket org.apache.logging.log4j.core.net.SslSocketManager::createSocket(java.lang.String, int) throws java.io.IOException",
+        "new": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.net.InetSocketAddress, org.apache.logging.log4j.core.net.SocketOptions, int) throws java.io.IOException @ org.apache.logging.log4j.core.net.SslSocketManager",
+        "justification": "LOG4J2-2586 - Support the host name resolving to mulitple ip addresses"
       },
       {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder::setLayout(org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setLayout(org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>) @ org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.lo [...]
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder::setName(java.lang.String)",
-        "new": "method B org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B>>>::setName(java.lang.String) @ org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.appender.AbstractAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.class.nonFinalClassInheritsFromNewClass",
-        "old": "class org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>",
-        "superClass": "org.apache.logging.log4j.core.filter.AbstractFilterable.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.generics.elementNowParameterized",
-        "old": "class org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.generics.formalTypeParameterAdded",
-        "old": "class org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder",
-        "new": "class org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>",
-        "typeParameter": "B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.core.config.Property[] org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender.Builder<B>>>::getProperties()",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method B org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender.Builder<B>>>::setProperties(org.apache.logging.log4j.core.config.Property[])",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
-
-      },
-      {
-        "code": "java.method.returnTypeChanged",
-        "old": "method void org.apache.logging.log4j.core.util.Closer::close(java.lang.AutoCloseable) throws java.lang.Exception",
-        "new": "method boolean org.apache.logging.log4j.core.util.Closer::close(java.lang.AutoCloseable) throws java.lang.Exception",
-        "justification": "LOG4J2-2496 - JDBC Appender should reconnect to the database when a connection goes stale"
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method java.lang.Object org.apache.logging.log4j.core.util.Loader::newInstanceOf(java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException",
-        "new": "method <T> T org.apache.logging.log4j.core.util.Loader::newInstanceOf(java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException",
-        "justification": "LOG4J2-2482 - BasicContextSelector cannot be used in an OSGi application"
-      },
-      {
-        "code": "java.generics.elementNowParameterized",
-        "old": "method java.lang.Object org.apache.logging.log4j.core.util.Loader::newInstanceOf(java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException",
-        "new": "method <T> T org.apache.logging.log4j.core.util.Loader::newInstanceOf(java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException",
-        "justification": "LOG4J2-2482 - BasicContextSelector cannot be used in an OSGi application"
-      },
-      {
-        "code": "java.generics.formalTypeParameterAdded",
-        "old": "method java.lang.Object org.apache.logging.log4j.core.util.Loader::newInstanceOf(java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException",
-        "new": "method <T> T org.apache.logging.log4j.core.util.Loader::newInstanceOf(java.lang.String) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.InstantiationException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException",
-        "typeParameter": "T",
-        "justification": "LOG4J2-2482 - BasicContextSelector cannot be used in an OSGi application"
+        "code": "java.method.numberOfParametersChanged",
+        "old": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.lang.String, int, org.apache.logging.log4j.core.net.SocketOptions, int) throws java.io.IOException @ org.apache.logging.log4j.core.net.SslSocketManager",
+        "new": "method java.net.Socket org.apache.logging.log4j.core.net.SslSocketManager::createSocket(java.net.InetSocketAddress) throws java.io.IOException",
+        "justification": "LOG4J2-2586 - Support the host name resolving to mulitple ip addresses"
       },
       {
-        "code": "java.field.enumConstantOrderChanged",
-        "old": "field org.apache.logging.log4j.core.util.datetime.FixedDateFormat.FixedFormat.ISO8601_PERIOD",
-        "new": "field org.apache.logging.log4j.core.util.datetime.FixedDateFormat.FixedFormat.ISO8601_PERIOD",
-        "justification": "LOG4J2-1247 - PatternLayout %date conversion pattern should render time zone designator"
-
+        "code": "java.method.noLongerStatic",
+        "old": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.lang.String, int, org.apache.logging.log4j.core.net.SocketOptions, int) throws java.io.IOException @ org.apache.logging.log4j.core.net.SslSocketManager",
+        "new": "method java.net.Socket org.apache.logging.log4j.core.net.SslSocketManager::createSocket(java.net.InetSocketAddress) throws java.io.IOException",
+        "justification": "LOG4J2-2586 - Support the host name resolving to mulitple ip addresses"
       },
       {
-        "code": "java.method.addedToInterface",
-        "new": "method void org.apache.logging.log4j.core.appender.rolling.DirectFileRolloverStrategy::clearCurrentFileName()",
-        "justification": "Required to reset file name so it can be calculated at the appropriate time"
+        "code": "java.method.numberOfParametersChanged",
+        "old": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.lang.String, int) throws java.io.IOException",
+        "new": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.net.InetSocketAddress, org.apache.logging.log4j.core.net.SocketOptions, int) throws java.io.IOException",
+        "justification": "LOG4J2-2586 - Support the host name resolving to mulitple ip addresses"
       },
       {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender::newBuilder()",
-        "new": "method <B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>> B org.apache.logging.log4j.core.appender.WriterAppender::newBuilder()",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
+        "code": "java.method.nowStatic",
+        "old": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.lang.String, int) throws java.io.IOException",
+        "new": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.net.InetSocketAddress, org.apache.logging.log4j.core.net.SocketOptions, int) throws java.io.IOException",
+        "justification": "LOG4J2-2586 - Support the host name resolving to mulitple ip addresses"
       },
       {
-        "code": "java.generics.elementNowParameterized",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender::newBuilder()",
-        "new": "method <B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>> B org.apache.logging.log4j.core.appender.WriterAppender::newBuilder()",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
+        "code": "java.method.numberOfParametersChanged",
+        "old": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.lang.String, int, org.apache.logging.log4j.core.net.SocketOptions, int) throws java.io.IOException",
+        "new": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.net.InetSocketAddress) throws java.io.IOException",
+        "justification": "LOG4J2-2586 - Support the host name resolving to mulitple ip addresses"
       },
       {
-        "code": "java.generics.formalTypeParameterAdded",
-        "old": "method org.apache.logging.log4j.core.appender.WriterAppender.Builder org.apache.logging.log4j.core.appender.WriterAppender::newBuilder()",
-        "new": "method <B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>> B org.apache.logging.log4j.core.appender.WriterAppender::newBuilder()",
-        "typeParameter": "B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B extends org.apache.logging.log4j.core.appender.WriterAppender.Builder<B>>",
-        "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
+        "code": "java.method.noLongerStatic",
+        "old": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.lang.String, int, org.apache.logging.log4j.core.net.SocketOptions, int) throws java.io.IOException",
+        "new": "method java.net.Socket org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.net.InetSocketAddress) throws java.io.IOException",
+        "justification": "LOG4J2-2586 - Support the host name resolving to mulitple ip addresses"
       }
     ]
   }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
index 074b34a..e9e018d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.util.List;
 
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
@@ -134,11 +135,10 @@ public class SslSocketManager extends TcpSocketManager {
     }
 
     @Override
-    protected Socket createSocket(final String host, final int port) throws IOException {
+    protected Socket createSocket(final InetSocketAddress socketAddress) throws IOException {
         final SSLSocketFactory socketFactory = createSslSocketFactory(sslConfig);
-        final InetSocketAddress address = new InetSocketAddress(host, port);
         final Socket newSocket = socketFactory.createSocket();
-        newSocket.connect(address, getConnectTimeoutMillis());
+        newSocket.connect(socketAddress, getConnectTimeoutMillis());
         return newSocket;
     }
 
@@ -167,12 +167,21 @@ public class SslSocketManager extends TcpSocketManager {
 
         @Override
         Socket createSocket(final SslFactoryData data) throws IOException {
-            return SslSocketManager.createSocket(data.host, data.port, data.connectTimeoutMillis, data.sslConfiguration,
-                    data.socketOptions);
+            List<InetSocketAddress> socketAddresses = resolver.resolveHost(data.host, data.port);
+            IOException ioe = null;
+            for (InetSocketAddress socketAddress : socketAddresses) {
+                try {
+                    return SslSocketManager.createSocket(socketAddress, data.connectTimeoutMillis,
+                            data.sslConfiguration, data.socketOptions);
+                } catch (IOException ex) {
+                    ioe = ex;
+                }
+            }
+            throw new IOException(errorMessage(data, socketAddresses) , ioe);
         }
     }
 
-    static Socket createSocket(final String host, final int port, final int connectTimeoutMillis,
+    static Socket createSocket(final InetSocketAddress socketAddress, final int connectTimeoutMillis,
             final SslConfiguration sslConfiguration, final SocketOptions socketOptions) throws IOException {
         final SSLSocketFactory socketFactory = createSslSocketFactory(sslConfiguration);
         final SSLSocket socket = (SSLSocket) socketFactory.createSocket();
@@ -180,7 +189,7 @@ public class SslSocketManager extends TcpSocketManager {
             // Not sure which options must be applied before or after the connect() call.
             socketOptions.apply(socket);
         }
-        socket.connect(new InetSocketAddress(host, port), connectTimeoutMillis);
+        socket.connect(socketAddress, connectTimeoutMillis);
         if (socketOptions != null) {
             // Not sure which options must be applied before or after the connect() call.
             socketOptions.apply(socket);
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java
index c5967c0..d71740d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java
@@ -24,7 +24,9 @@ import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
@@ -340,9 +342,30 @@ public class TcpSocketManager extends AbstractSocketManager {
         }
 
         void reconnect() throws IOException {
-            final Socket sock = createSocket(inetAddress.getHostName(), port);
+            List<InetSocketAddress> socketAddresses = FACTORY.resolver.resolveHost(host, port);
+            if (socketAddresses.size() == 1) {
+                LOGGER.debug("Reconnecting " + socketAddresses.get(0));
+                connect(socketAddresses.get(0));
+            } else {
+                IOException ioe = null;
+                for (InetSocketAddress socketAddress : socketAddresses) {
+                    try {
+                        LOGGER.debug("Reconnecting " + socketAddress);
+                        connect(socketAddress);
+                        return;
+                    } catch (IOException ex) {
+                        ioe = ex;
+                    }
+                }
+                throw ioe;
+            }
+        }
+
+        private void connect(InetSocketAddress socketAddress) throws IOException {
+            final Socket sock = createSocket(socketAddress);
             @SuppressWarnings("resource") // newOS is managed by the enclosing Manager.
             final OutputStream newOS = sock.getOutputStream();
+            InetAddress prev = socket != null ? socket.getInetAddress() : null;
             synchronized (owner) {
                 Closer.closeSilently(getOutputStream());
                 setOutputStream(newOS);
@@ -350,7 +373,9 @@ public class TcpSocketManager extends AbstractSocketManager {
                 reconnector = null;
                 shutdown = true;
             }
-            LOGGER.debug("Connection to {}:{} reestablished: {}", host, port, socket);
+            String type = prev != null && prev.getHostAddress().equals(socketAddress.getAddress().getHostAddress()) ?
+                    "reestablished" : "established";
+            LOGGER.debug("Connection to {}:{} {}: {}", host, port, type, socket);
         }
 
         @Override
@@ -366,19 +391,19 @@ public class TcpSocketManager extends AbstractSocketManager {
         return recon;
     }
 
-    protected Socket createSocket(final String host, final int port) throws IOException {
-        return createSocket(host, port, socketOptions, connectTimeoutMillis);
+    protected Socket createSocket(final InetSocketAddress socketAddress) throws IOException {
+        return createSocket(socketAddress, socketOptions, connectTimeoutMillis);
     }
 
-    protected static Socket createSocket(final String host, final int port, final SocketOptions socketOptions,
+    protected static Socket createSocket(final InetSocketAddress socketAddress, final SocketOptions socketOptions,
             final int connectTimeoutMillis) throws IOException {
-        LOGGER.debug("Creating socket {}:{}", host, port);
+        LOGGER.debug("Creating socket {}", socketAddress.toString());
         final Socket newSocket = new Socket();
         if (socketOptions != null) {
             // Not sure which options must be applied before or after the connect() call.
             socketOptions.apply(newSocket);
         }
-        newSocket.connect(new InetSocketAddress(host, port), connectTimeoutMillis);
+        newSocket.connect(socketAddress, connectTimeoutMillis);
         if (socketOptions != null) {
             // Not sure which options must be applied before or after the connect() call.
             socketOptions.apply(newSocket);
@@ -431,6 +456,8 @@ public class TcpSocketManager extends AbstractSocketManager {
     protected static class TcpSocketManagerFactory<M extends TcpSocketManager, T extends FactoryData>
             implements ManagerFactory<M, T> {
 
+        static HostResolver resolver = new HostResolver();
+
         @SuppressWarnings("resource")
         @Override
         public M createManager(final String name, final T data) {
@@ -467,9 +494,59 @@ public class TcpSocketManager extends AbstractSocketManager {
         }
 
         Socket createSocket(final T data) throws IOException {
-            return TcpSocketManager.createSocket(data.host, data.port, data.socketOptions, data.connectTimeoutMillis);
+            List<InetSocketAddress> socketAddresses = resolver.resolveHost(data.host, data.port);
+            IOException ioe = null;
+            for (InetSocketAddress socketAddress : socketAddresses) {
+                try {
+                    return TcpSocketManager.createSocket(socketAddress, data.socketOptions, data.connectTimeoutMillis);
+                } catch (IOException ex) {
+                    ioe = ex;
+                }
+            }
+            throw new IOException(errorMessage(data, socketAddresses) , ioe);
         }
 
+        protected String errorMessage(final T data, List<InetSocketAddress> socketAddresses) {
+            StringBuilder sb = new StringBuilder("Unable to create socket for ");
+            sb.append(data.host).append(" at port ").append(data.port);
+            if (socketAddresses.size() == 1) {
+                if (!socketAddresses.get(0).getAddress().getHostAddress().equals(data.host)) {
+                    sb.append(" using ip address ").append(socketAddresses.get(0).getAddress().getHostAddress());
+                    sb.append(" and port ").append(socketAddresses.get(0).getPort());
+                }
+            } else {
+                sb.append(" using ip addresses and ports ");
+                for (int i = 0; i < socketAddresses.size(); ++i) {
+                    if (i > 0) {
+                        sb.append(", ");
+                        sb.append(socketAddresses.get(i).getAddress().getHostAddress());
+                        sb.append(":").append(socketAddresses.get(i).getPort());
+                    }
+                }
+            }
+            return sb.toString();
+        }
+
+    }
+
+    /**
+     * This method is only for unit testing. It is not Thread-safe.
+     * @param resolver the HostResolver.
+     */
+    public static void setHostResolver(HostResolver resolver) {
+        TcpSocketManagerFactory.resolver = resolver;
+    }
+
+    public static class HostResolver {
+
+        public List<InetSocketAddress> resolveHost(String host, int port) throws UnknownHostException {
+            InetAddress[] addresses = InetAddress.getAllByName(host);
+            List<InetSocketAddress> socketAddresses = new ArrayList<>(addresses.length);
+            for (InetAddress address: addresses) {
+                socketAddresses.add(new InetSocketAddress(address, port));
+            }
+            return socketAddresses;
+        }
     }
 
     /**
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/SocketReconnectTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/SocketReconnectTest.java
index 151d444..92d1beb 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/SocketReconnectTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/SocketReconnectTest.java
@@ -16,27 +16,36 @@
  */
 package org.apache.logging.log4j.core.net;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.AppenderLoggingException;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
 import java.io.BufferedReader;
+import java.io.IOException;
 import java.io.InputStreamReader;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.appender.AppenderLoggingException;
-import org.apache.logging.log4j.junit.LoggerContextRule;
-import org.apache.logging.log4j.test.AvailablePortFinder;
-import org.apache.logging.log4j.util.Strings;
-import org.junit.ClassRule;
-import org.junit.Ignore;
-import org.junit.Test;
-
 import static org.junit.Assert.*;
 
-@Ignore("Currently needs better port choosing support")
+//@Ignore("Currently needs better port choosing support")
 public class SocketReconnectTest {
-    private static final int SOCKET_PORT = AvailablePortFinder.getNextAvailable();
+    private static final int SOCKET_PORT1 = AvailablePortFinder.getNextAvailable();
+    private static final int SOCKET_PORT2 = AvailablePortFinder.getNextAvailable();
 
     private static final String CONFIG = "log4j-socket.xml";
 
@@ -46,41 +55,84 @@ public class SocketReconnectTest {
         "................................................................" + Strings.LINE_SEPARATOR +
         "................................................................" + Strings.LINE_SEPARATOR;
 
-    @ClassRule
-    public static LoggerContextRule context = new LoggerContextRule(CONFIG);
+    public static LocalHostResolver resolver = new LocalHostResolver();
 
-    @Test
-    public void testReconnect() throws Exception {
+    private static LoggerContext loggerContext;
 
-        final List<String> list = new ArrayList<>();
-        TestSocketServer server = new TestSocketServer(list);
-        server.start();
-        Thread.sleep(300);
+    private static final List<String> list = new ArrayList<>();
+    private static int[] ports;
+    private static TestSocketServer server1;
+    private static TestSocketServer server2;
+    private static Logger logger;
 
-        //System.err.println("Initializing logger");
-        final Logger logger = context.getLogger();
 
-        String message = "Log #1";
-        logger.error(message);
-        final String expectedHeader = "Header";
+    @BeforeClass
+    public static void beforeClass() throws IOException, InterruptedException {
+        server1 = new TestSocketServer(0);
+        server2 = new TestSocketServer(0);
+        server1.start();
+        server2.start();
+        Thread.sleep(100);
+        ports = new int[] { server1.getPort(), server2.getPort()};
+        resolver.ports = ports;
+        TcpSocketManager.setHostResolver(resolver);
+        loggerContext = Configurator.initialize("SocketReconnectTest", SocketReconnectTest.class.getClassLoader(),
+                CONFIG);
+        logger = LogManager.getLogger(SocketReconnectTest.class);
+        server1.shutdown();
+        server1.join();
+        server2.shutdown();
+        server2.join();
+        server1 = null;
+        server2 = null;
+        Thread.sleep(100);
+        list.clear();
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        Configurator.shutdown(loggerContext);
+    }
+
+    @After
+    public void after() throws InterruptedException {
+        if (server1 != null) {
+            server1.shutdown();
+            server1.join();
+        }
+        if (server2 != null) {
+            server2.shutdown();
+            server2.join();
+        }
+        server1 = null;
+        server2 = null;
+        Thread.sleep(300);
+    }
 
+    @Test
+    public void testReconnect() throws Exception {
+        list.clear();
+        resolver.ports = new int[] {ports[0]};
+        server1 = new TestSocketServer(ports[0]);
+        server1.start();
+        Thread.sleep(200);
+        String message = "Log #1";
         String msg = null;
-        String header = null;
         for (int i = 0; i < 5; ++i) {
+            logger.error(message);
             Thread.sleep(100);
-            if (list.size() > 1) {
-                header = list.get(0);
-                msg = list.get(1);
-                break;
+            if (list.size() > 0) {
+                msg = list.get(0);
+                if (msg != null) {
+                    break;
+                }
             }
         }
-        assertNotNull("No header", header);
-        assertEquals(expectedHeader, header);
         assertNotNull("No message", msg);
         assertEquals(message, msg);
 
         logger.error(SHUTDOWN);
-        server.join();
+        server1.join();
 
         list.clear();
 
@@ -100,73 +152,173 @@ public class SocketReconnectTest {
         message = "Log #3";
 
 
-        server = new TestSocketServer(list);
-        server.start();
+        server1 = new TestSocketServer(ports[0]);
+        server1.start();
         Thread.sleep(300);
 
         msg = null;
-        header = null;
-        logger.error(message);
         for (int i = 0; i < 5; ++i) {
+            logger.error(message);
             Thread.sleep(100);
-            if (list.size() > 1) {
-                header = list.get(0);
-                msg = list.get(1);
-                break;
+            if (list.size() > 0) {
+                msg = list.get(0);
+                if (msg != null) {
+                    break;
+                }
             }
         }
-        assertNotNull("No header", header);
-        assertEquals(expectedHeader, header);
         assertNotNull("No message", msg);
         assertEquals(message, msg);
         logger.error(SHUTDOWN);
-        server.join();
+        server1.join();
+    }
+
+    @Test
+    public void testFailover() throws Exception {
+        list.clear();
+        server1 = new TestSocketServer(ports[0]);
+        server2 = new TestSocketServer(ports[1]);
+        resolver.ports = ports;
+        server1.start();
+        server2.start();
+        Thread.sleep(100);
+
+        String message = "Log #1";
+
+        String msg = null;
+        for (int i = 0; i < 5; ++i) {
+            logger.error(message);
+            Thread.sleep(100);
+            if (list.size() > 0) {
+                msg = list.get(0);
+                if (msg != null) {
+                    break;
+                }
+            }
+        }
+        assertNotNull("No message", msg);
+        assertEquals(message, msg);
+
+        server1.shutdown();
+        server1.join();
+        logger.error("Ignore");
+
+        list.clear();
+
+        message = "Log #2";
+        for (int i = 0; i < 5; ++i) {
+            logger.error(message);
+            Thread.sleep(100);
+            if (list.size() > 0) {
+                msg = list.get(0);
+                if (msg != null) {
+                    break;
+                }
+            }
+        }
+        assertNotNull("No message", msg);
+        assertEquals(message, msg);
+
+        server2.shutdown();
+        server2.join();
     }
 
 
     private static class TestSocketServer extends Thread {
         private volatile boolean shutdown = false;
-        private final List<String> list;
-        private Socket client;
+        private volatile boolean started = false;
+        private volatile Socket client;
+        private final int port;
+        private ServerSocket server;
+
+        public TestSocketServer(int port) throws IOException {
+            this.port = port;
+            server = new ServerSocket(port);
+        }
 
-        public TestSocketServer(final List<String> list) {
-            this.list = list;
+        public int getPort() {
+            return port == 0 ? server.getLocalPort() : port;
+        }
+
+        public void shutdown() {
+            if (!shutdown) {
+                shutdown = true;
+                if (server != null && server.isBound()) {
+                    try {
+                        if (client != null) {
+                            Socket serverClient = client;
+                            client = null;
+                            serverClient.shutdownInput();
+                            serverClient.shutdownOutput();
+                            serverClient.setSoLinger(true, 0);
+                            serverClient.close();
+                        }
+                        ServerSocket serverSocket = server;
+                        server = null;
+                        serverSocket.close();
+                    } catch (Exception ex) {
+                        System.out.println("Unable to send shutdown message");
+                        ex.printStackTrace();
+                    }
+                }
+                return;
+            }
         }
 
         @Override
         public void run() {
-            ServerSocket server = null;
             client = null;
             try {
-                server = new ServerSocket(SOCKET_PORT);
                 client = server.accept();
+                started = true;
                 while (!shutdown) {
                     final BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
                     final String line = reader.readLine();
-                    if (line.equals("Shutdown")) {
+                    if (line == null || line.equals("Shutdown")) {
                         shutdown = true;
                     } else {
                         list.add(line);
                     }
                 }
+            } catch (final SocketException ex) {
+                if (!shutdown) {
+                    ex.printStackTrace();
+                }
             } catch (final Exception ex) {
                 ex.printStackTrace();
             } finally {
-                if (client != null) {
+                if (client != null && !client.isClosed()) {
                     try {
+                        client.setSoLinger(true, 0);
+                        client.shutdownOutput();
                         client.close();
                     } catch (final Exception ex) {
-                        System.out.println("Unable to close socket " + ex.getMessage());
+                        System.out.println("Unable to close socket: " + ex.getMessage());
                     }
                 }
-                if (server != null) {
+                if (server != null && !server.isClosed()) {
                     try {
                         server.close();
                     } catch (final Exception ex) {
-                        System.out.println("Unable to close server socket " + ex.getMessage());
+                        System.out.println("Unable to close server socket: " + ex.getMessage());
                     }
                 }
             }
         }
     }
+
+    private static class LocalHostResolver extends TcpSocketManager.HostResolver {
+        public volatile int[] ports;
+
+        @Override
+        public List<InetSocketAddress> resolveHost(String host, int port) throws UnknownHostException {
+            int[] socketPorts = ports;
+            List<InetSocketAddress> socketAddresses = new ArrayList<>(ports.length);
+            InetAddress addr = InetAddress.getLocalHost();
+            for (int i = 0; i < socketPorts.length; ++i){
+                socketAddresses.add(new InetSocketAddress(addr, socketPorts[i]));
+            }
+            return socketAddresses;
+        }
+    }
 }
diff --git a/log4j-core/src/test/resources/log4j-socket.xml b/log4j-core/src/test/resources/log4j-socket.xml
index a437071..c627452 100644
--- a/log4j-core/src/test/resources/log4j-socket.xml
+++ b/log4j-core/src/test/resources/log4j-socket.xml
@@ -15,11 +15,11 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<Configuration status="OFF" name="MyApp">
+<Configuration status="ERROR" name="MyApp">
 	<Appenders>
 		<Socket name="socket" host="localhost" port="5514" protocol="TCP" ignoreExceptions="false"
-				reconnectionDelay="100">
-			<BasicLayout />
+				reconnectionDelay="100" immediateFlush="true">
+			<PatternLayout pattern="%m%n"/>
 		</Socket>
 	</Appenders>
 	<Loggers>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b4d308a..5ba0bfd 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
          - "remove" - Removed
     -->
     <release version="2.12.0" date="2019-MM-DD" description="GA Release 2.12.0">
+      <action issue="LOG4J2-2586" dev="rgoers" type="add">
+        TCP Appender should support a host name resolving to multiple IP addresses.
+      </action>
       <action issue="LOG4J2-2559" dev="ggregory" type="fix" due-to="Li Lei, Gary Gregory">
         NullPointerException in JdbcAppender.createAppender().
       </action>
diff --git a/src/site/xdoc/manual/appenders.xml b/src/site/xdoc/manual/appenders.xml
index 263a2d3..62cf5ee 100644
--- a/src/site/xdoc/manual/appenders.xml
+++ b/src/site/xdoc/manual/appenders.xml
@@ -4822,7 +4822,11 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity {
           <p>
             The <code>SocketAppender</code> is an OutputStreamAppender that writes its output to a remote destination
             specified by a host and port. The data can be sent over either TCP or UDP and can be sent in any format.
-            You can optionally secure communication with <a href="#SSL">SSL</a>.
+            You can optionally secure communication with <a href="#SSL">SSL</a>. Note that the TCP and SSL variants
+            write to the socket as a stream and do not expect response from the target destination. Due to limitations
+            in the TCP protocol that means that when the target server closes its connection some log events may
+            continue to appear to succeed until a closed connection exception is raised, causing those events to be
+            lost. If guaranteed delivery is required a protocol that requires acknowledgements must be used.
           </p>
           <table>
             <caption align="top"><code>SocketAppender</code> Parameters</caption>
@@ -4839,7 +4843,10 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity {
             <tr>
               <td>host</td>
               <td>String</td>
-              <td>The name or address of the system that is listening for log events. This parameter is required.</td>
+              <td>The name or address of the system that is listening for log events. This parameter is required. If
+                the host name resolves to multiple IP addresses the TCP and SSL variations will fail over to
+                the next IP address when a connection is lost.
+              </td>
             </tr>
             <tr>
               <td>port</td>