### Elasticsearch Version

7.17, 8.0

### Installed Plugins

_No response_

### Java Version

_bundled_

### OS Version

n/a

### Problem Description

The TransportDeprecationInfoAction calls DeprecationInfoAction on the current thread, which is a transport_worker thread. Unfortunately if there are a lot of indices this can take tens of seconds. And since it is on the transport_worker thread it can interfere with communication to and from the other machines in the cluster. The result is that this machine (the master) will see that other nodes are not responding, and remove them from the cluster. And other nodes will see that the master is not responding, so they will elect a new master.

### Steps to Reproduce

We have seen this on a cluster with ~5500 indices and ~22,000 fields total. Just running 
```
GET _migration/deprecations
```
will do it.

### Logs (if relevant)

Here is an example thread from our hot_threads log:
```
   100.1% [cpu=100.1%, other=0.0%] (500.4ms out of 500ms) cpu usage by thread 'elasticsearch[es-prod-es-rack1-controller-0][transport_worker][T#7]'
     2/10 snapshots sharing following 120 elements
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readValueUnsafe(AbstractXContentParser.java:394)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readMapEntries(AbstractXContentParser.java:318)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readValueUnsafe(AbstractXContentParser.java:394)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readMapEntries(AbstractXContentParser.java:318)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readValueUnsafe(AbstractXContentParser.java:394)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readMapEntries(AbstractXContentParser.java:318)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readValueUnsafe(AbstractXContentParser.java:394)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readMapEntries(AbstractXContentParser.java:318)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.readMapSafe(AbstractXContentParser.java:304)
       app//org.elasticsearch.xcontent.support.AbstractXContentParser.mapOrdered(AbstractXContentParser.java:259)
       app//org.elasticsearch.common.xcontent.XContentHelper.convertToMap(XContentHelper.java:188)
       app//org.elasticsearch.common.xcontent.XContentHelper.convertToMap(XContentHelper.java:147)
       app//org.elasticsearch.common.xcontent.XContentHelper.convertToMap(XContentHelper.java:106)
       app//org.elasticsearch.cluster.metadata.MappingMetadata.sourceAsMap(MappingMetadata.java:142)
       app//org.elasticsearch.cluster.metadata.MappingMetadata.getSourceAsMap(MappingMetadata.java:154)
       org.elasticsearch.xpack.deprecation.IndexDeprecationChecks.checkGeoShapeMappings(IndexDeprecationChecks.java:729)
       org.elasticsearch.xpack.deprecation.DeprecationChecks.lambda$static$34(DeprecationChecks.java:268)
       org.elasticsearch.xpack.deprecation.DeprecationChecks$$Lambda$1089/0x000000080100d000.apply(Unknown Source)
       org.elasticsearch.xpack.deprecation.DeprecationInfoAction$Response.lambda$from$3(DeprecationInfoAction.java:285)
       org.elasticsearch.xpack.deprecation.DeprecationInfoAction$Response$$Lambda$8943/0x00000008020b1d90.apply(Unknown Source)
       java.base@17.0.2/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
       java.base@17.0.2/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
       java.base@17.0.2/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
       java.base@17.0.2/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
       java.base@17.0.2/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
       java.base@17.0.2/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
       java.base@17.0.2/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
       org.elasticsearch.xpack.deprecation.DeprecationInfoAction.filterChecks(DeprecationInfoAction.java:68)
       org.elasticsearch.xpack.deprecation.DeprecationInfoAction$Response.from(DeprecationInfoAction.java:285)
       org.elasticsearch.xpack.deprecation.TransportDeprecationInfoAction.lambda$masterOperation$1(TransportDeprecationInfoAction.java:130)
       org.elasticsearch.xpack.deprecation.TransportDeprecationInfoAction$$Lambda$8747/0x0000000801ef1468.accept(Unknown Source)
       app//org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:136)
       org.elasticsearch.xpack.deprecation.TransportDeprecationInfoAction.lambda$pluginSettingIssues$4(TransportDeprecationInfoAction.java:160)
       org.elasticsearch.xpack.deprecation.TransportDeprecationInfoAction$$Lambda$8750/0x0000000801ef1b20.accept(Unknown Source)
       app//org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:136)
       app//org.elasticsearch.action.support.GroupedActionListener.onResponse(GroupedActionListener.java:55)
       org.elasticsearch.xpack.deprecation.MlDeprecationChecker.lambda$check$1(MlDeprecationChecker.java:133)
       org.elasticsearch.xpack.deprecation.MlDeprecationChecker$$Lambda$8786/0x0000000801ef3c00.accept(Unknown Source)
       app//org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:136)
       app//org.elasticsearch.action.support.ContextPreservingActionListener.onResponse(ContextPreservingActionListener.java:31)
       app//org.elasticsearch.action.support.TransportAction$1.onResponse(TransportAction.java:88)
       app//org.elasticsearch.action.support.TransportAction$1.onResponse(TransportAction.java:82)
       app//org.elasticsearch.action.support.ContextPreservingActionListener.onResponse(ContextPreservingActionListener.java:31)
       org.elasticsearch.xpack.security.action.filter.SecurityActionFilter.lambda$applyInternal$2(SecurityActionFilter.java:192)
       org.elasticsearch.xpack.security.action.filter.SecurityActionFilter$$Lambda$6585/0x0000000801e1c8d0.accept(Unknown Source)
       app//org.elasticsearch.action.ActionListener$DelegatingFailureActionListener.onResponse(ActionListener.java:219)
       org.elasticsearch.xpack.ml.action.TransportGetModelSnapshotsAction.lambda$getModelSnapshots$2(TransportGetModelSnapshotsAction.java:81)
       org.elasticsearch.xpack.ml.action.TransportGetModelSnapshotsAction$$Lambda$8791/0x000000080204af50.accept(Unknown Source)
       org.elasticsearch.xpack.ml.job.persistence.JobResultsProvider.lambda$modelSnapshots$31(JobResultsProvider.java:1309)
       org.elasticsearch.xpack.ml.job.persistence.JobResultsProvider$$Lambda$8799/0x000000080204ba50.accept(Unknown Source)
       app//org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:136)
       app//org.elasticsearch.action.support.ContextPreservingActionListener.onResponse(ContextPreservingActionListener.java:31)
       app//org.elasticsearch.action.support.TransportAction$1.onResponse(TransportAction.java:88)
       app//org.elasticsearch.action.support.TransportAction$1.onResponse(TransportAction.java:82)
       app//org.elasticsearch.action.support.ContextPreservingActionListener.onResponse(ContextPreservingActionListener.java:31)
       org.elasticsearch.xpack.security.action.filter.SecurityActionFilter.lambda$applyInternal$2(SecurityActionFilter.java:192)
       org.elasticsearch.xpack.security.action.filter.SecurityActionFilter$$Lambda$6585/0x0000000801e1c8d0.accept(Unknown Source)
       app//org.elasticsearch.action.ActionListener$DelegatingFailureActionListener.onResponse(ActionListener.java:219)
       app//org.elasticsearch.action.ActionListener$RunAfterActionListener.onResponse(ActionListener.java:341)
       app//org.elasticsearch.action.search.AbstractSearchAsyncAction.sendSearchResponse(AbstractSearchAsyncAction.java:707)
       app//org.elasticsearch.action.search.ExpandSearchPhase.run(ExpandSearchPhase.java:106)
       app//org.elasticsearch.action.search.AbstractSearchAsyncAction.executePhase(AbstractSearchAsyncAction.java:454)
       app//org.elasticsearch.action.search.AbstractSearchAsyncAction.executeNextPhase(AbstractSearchAsyncAction.java:448)
       app//org.elasticsearch.action.search.FetchSearchPhase.moveToNextPhase(FetchSearchPhase.java:287)
       app//org.elasticsearch.action.search.FetchSearchPhase.lambda$innerRun$1(FetchSearchPhase.java:114)
       app//org.elasticsearch.action.search.FetchSearchPhase$$Lambda$6996/0x0000000801eadd30.run(Unknown Source)
       app//org.elasticsearch.action.search.CountedCollector.countDown(CountedCollector.java:40)
       app//org.elasticsearch.action.search.CountedCollector$$Lambda$8804/0x0000000802099440.run(Unknown Source)
       app//org.elasticsearch.action.search.ArraySearchPhaseResults.consumeResult(ArraySearchPhaseResults.java:35)
       app//org.elasticsearch.action.search.CountedCollector.onResult(CountedCollector.java:48)
       app//org.elasticsearch.action.search.FetchSearchPhase$2.innerOnResponse(FetchSearchPhase.java:226)
       app//org.elasticsearch.action.search.FetchSearchPhase$2.innerOnResponse(FetchSearchPhase.java:220)
       app//org.elasticsearch.action.search.SearchActionListener.onResponse(SearchActionListener.java:33)
       app//org.elasticsearch.action.search.SearchActionListener.onResponse(SearchActionListener.java:18)
       app//org.elasticsearch.action.ActionListenerResponseHandler.handleResponse(ActionListenerResponseHandler.java:43)
       app//org.elasticsearch.action.search.SearchTransportService$ConnectionCountingHandler.handleResponse(SearchTransportService.java:642)
       app//org.elasticsearch.transport.TransportService$4.handleResponse(TransportService.java:847)
       app//org.elasticsearch.transport.TransportService$ContextRestoreResponseHandler.handleResponse(TransportService.java:1471)
       app//org.elasticsearch.transport.InboundHandler.doHandleResponse(InboundHandler.java:340)
       app//org.elasticsearch.transport.InboundHandler.handleResponse(InboundHandler.java:324)
       app//org.elasticsearch.transport.InboundHandler.messageReceived(InboundHandler.java:134)
       app//org.elasticsearch.transport.InboundHandler.inboundMessage(InboundHandler.java:88)
       app//org.elasticsearch.transport.TcpTransport.inboundMessage(TcpTransport.java:743)
       org.elasticsearch.transport.netty4.Netty4MessageChannelHandler$$Lambda$6021/0x0000000801b7e510.accept(Unknown Source)
       app//org.elasticsearch.transport.InboundPipeline.forwardFragments(InboundPipeline.java:147)
       app//org.elasticsearch.transport.InboundPipeline.doHandleBytes(InboundPipeline.java:119)
       app//org.elasticsearch.transport.InboundPipeline.handleBytes(InboundPipeline.java:84)
       org.elasticsearch.transport.netty4.Netty4MessageChannelHandler.channelRead(Netty4MessageChannelHandler.java:71)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:280)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1374)
       io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1237)
       io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1286)
       io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:507)
       io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:446)
       io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
       io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
       io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
       io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:620)
       io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:583)
       io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
       io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
       io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
       java.base@17.0.2/java.lang.Thread.run(Thread.java:833)
```
x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/DeprecationInfoAction.java
* differ at most by meta values (if that). The returned tuples also contain the node name the deprecation issue was found on. If all
     * nodes in the cluster were configured identically then all tuples in a list will differ only by the node name.
     */
    private static Collection<List<Tuple<DeprecationIssue, String>>> getDeprecationIssuesThatDifferOnlyByMeta(
        List<NodesDeprecationCheckAction.NodeResponse> nodeResponses
    ) {
        Map<DeprecationIssue, List<Tuple<DeprecationIssue, String>>> issuesToMerge = new HashMap<>();
        for (NodesDeprecationCheckAction.NodeResponse resp : nodeResponses) {
            for (DeprecationIssue issue : resp.getDeprecationIssues()) {
                issuesToMerge.computeIfAbsent(
                    new DeprecationIssue(
                        issue.getLevel(),
                        issue.getMessage(),
                        issue.getUrl(),
                        issue.getDetails(),
                        issue.isResolveDuringRollingUpgrade(),
                        null 
                    ),
                    (key) -> new ArrayList<>()
                ).add(new Tuple<>(issue, resp.getNode().getName()));
            }
        }
        return issuesToMerge.values();
    }
    /*
     * At this point we have one DeprecationIssue per node for a given deprecation. This method rolls them up into a single DeprecationIssue
     * with a list of nodes that they appear on. If two DeprecationIssues on two different nodes differ only by the set of removable
     * settings (i.e. they have different elasticsearch.yml configurations) then this method takes the intersection of those settings when
     * it rolls them up.
     */