[Technische Anwendung] Der in Springboot integrierte Tomcat konfiguriert Unix-Domänen-Socket-Attribute

I. Einleitung

In letzter Zeit wurden viele unix domain socketin Arbeit befindliche **UNIX Domain Socket Protocol ()**-Anwendungen zusammengefasst, aber es gibt ein UNIX DOMAIN SOCKET协议Anwendungsbeispiel, das von den am häufigsten verwendeten Komponenten in Arbeit unterstützt wird und nicht zusammengefasst wurde, nämlich: Tomcat unterstützt UNIX Domain-Sockets Anwendungsbeispiele für das Word-Protokoll (Unix-Domain-Socket) , heute zusammengefasst;

Beispiele früherer Anwendungen des UNIX-Domain-Socket-Protokolls in Komponenten:

1. [Technische Anwendung] Java stellt eine Verbindung zu Redis basierend auf dem UNIX-Domänen-Socket (Unix-Domänen-Socket) her.

2. [Technische Anwendung] Java stellt eine Verbindung zur Postgresql-Datenbank basierend auf dem UNIX-Domänen-Socket (Unix-Domänen-Socket) her.

3. [Technische Anwendung] Java stellt eine Verbindung zur MySQL-Datenbank basierend auf dem UNIX-Domänen-Socket (Unix-Domänen-Socket) her.

2. Springboot verfügt über einen integrierten Tomcat

1. Springboot unterstützt die integrierte Funktion von Tomcat. Das Projekt kann zur Ausführung direkt in ein JAR-Paket kompiliert werden, und Tomcat kann in das Innere des JAR kompiliert werden, was die Anwendung vereinfacht. Dies ist auch eine wichtige Funktion von Springboot ;

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2. Die Konfigurationselementattribute des in Springboot integrierten Tomcat werden normalerweise application.yml配置文件wie folgt festgelegt:

server:
  tomcat:
    accept-count: 80 #挂起的请求队列最大连接数,默认100
    max-connections: 2000  #最大连接数,默认10000,tomcat内tcp连接池的大小
    max-threads: 200 #最大线程数,默认200,超过加入等待队列,默认是100,当等待队列达到100后,直接拒绝此次请求返回connection refused。连接超时时间默认为20秒
    min-spare-threads: 5  #最小工作线程数
    connection-timeout: 60000  #server端的socket超时间,默认60s
    accesslog:
      enabled: true #启动tomcat访问日志

Nach der Analyse aller Konfigurationselemente unixdomainsocketwurden jedoch keine relevanten Konfigurationsinformationen gefunden, sodass apllication.yml配置文件die Funktion unixdomainsocket nicht implementiert werden kann.

3. Konfigurieren Sie das integrierte Tocmat-Attribut über den Code in Springboot.

1) Konfigurieren Sie den Port des Servlet-Containers auf 9000

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import
org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
@Component
public class MyWebServerFactoryCustomizer implements
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
    
    
  @Override
  public void customize(ConfigurableServletWebServerFactory server) {
    
    
  server.setPort(9000);
  }
}

2) Verwenden Sie ConfigurableServletWebServerFactoryUnterklassen (z. B. TomcatServletWebServerFactory), um den Servlet-Container zu konfigurieren

import java.time.Duration;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class MyTomcatWebServerFactoryCustomizer implements
WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
    
    
  @Override
  public void customize(TomcatServletWebServerFactory server) {
    
    
  server.addConnectorCustomizers((connector) ->
connector.setAsyncTimeout(Duration.ofSeconds(20).toMillis()));
  }
}

3. Analyse der Unterstützung von Tomcat für das Unix-Domain-Socket-Protokoll

1. Die Zusammensetzung von Tomcat kann in zwei Teile unterteilt werden: 连接器und 容器
Connector : Wird speziell zur Behandlung von Problemen im Zusammenhang mit Netzwerkverbindungen verwendet, z. B. Socket-Links in der Webentwicklung, Anforderungskapselung, Verbindungs-Thread-Pools usw.
Container (Servlet) : Wird zum Speichern der von uns geschriebenen Website-Programme verwendet. Tomcat verfügt insgesamt über vier Container: Engine, Host, Context und Wrapper. Ein Wrapper entspricht einem Servlet, ein Kontext entspricht einer Anwendung (standardmäßig entspricht die in webapps/ROOT gespeicherte Hauptanwendung beispielsweise dem Stammverzeichnis einer Site), ein Host entspricht einer Site (z. B. einer anderen Domäne). Namen) und Engine ist die Engine .

2. Die für die Verarbeitung von Anforderungen im Connector verantwortlichen Protokolle basieren hauptsächlich auf bio,nio,nio2,aprmehreren verschiedenen http-Protokollen, und 支持NIO协议die Attributeinstellungen unterstützen die unixdomainsocket属性Konfiguration.

pollerThreadPriority:(int)The priority of the poller threads
selectorTimeout:(int)The time in milliseconds to timeout on a select() for the poller
useSendfile:(bool)Use this attribute to enable or disable sendfile capability
socket.directBuffer:(bool)Boolean value, whether to use direct ByteBuffers or java mapped ByteBuffers
 
socket.directSslBuffer:(bool)Boolean value, whether to use direct ByteBuffers or java mapped ByteBuffers for the SSL buffers
socket.appReadBufSize:(int)Each connection that is opened up in Tomcat get associated with a read ByteBuffer
socket.appWriteBufSize:(int)Each connection that is opened up in Tomcat get associated with a write ByteBuffer
socket.bufferPool:(int)The NIOx connector uses a class called NioXChannel that holds elements linked to a socket
socket.bufferPoolSize:(int)The NioXChannel pool can also be size based, not used object based
 
socket.processorCache:(int)Tomcat will cache SocketProcessor objects to reduce garbage collection
socket.eventCache:(int)Tomcat will cache PollerEvent objects to reduce garbage collection
 
unixDomainSocketPath:Where supported, the path to a Unix Domain Socket that this Connector will create and await incoming connections
unixDomainSocketPathPermissions:Where supported, the posix permissions that will be applied to the to the Unix Domain Socket specified with unixDomainSocketPath above
useInheritedChannel:(bool)Defines if this connector should inherit an inetd/systemd network socket

Daher müssen wir nur das Attribut unixDomainSocketPath festlegen.

4. Der in Springboot integrierte Tomcat verwendet ein Beispiel für das Unixdomainsocket-Protokoll

1. JDK-Version
Bei Verwendung des integrierten Tomcat von Springboot wird das abhängige JDK verwendet 最低版本是jdk16, da Unix-Sockets erst ab jdk16 unterstützt werden.
Im Jahr 2019 bieten Windows Server und Windows 10 Unterstützung für Unix-Sockets und Unix-Sockets werden häufig verwendet Kommunikation zwischen lokalen Prozessen. Im Vergleich zum TCP-Protokoll können lokale Prozesse mithilfe von Unix-Sockets effizienter und sicherer kommunizieren. JDK16 fügt eine neue Schnittstelle für Unix-Sockets hinzu java.net.UnixDomainSocketAddress, um diese Funktion zu unterstützen

Wenn die JDK-Version niedriger als 16 ist, wird ein Fehler gemeldet:

Caused by: java.lang.UnsupportedOperationException: Java Runtime does not support Unix domain sockets. You must use Java 16 to use this feature.
	at org.apache.tomcat.util.compat.JreCompat.openUnixDomainServerSocketChannel(JreCompat.java:337) ~[tomcat-embed-core-9.0.70.jar:9.0.70]
	at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:252) ~[tomcat-embed-core-9.0.70.jar:9.0.70]
	at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:230) ~[tomcat-embed-core-9.0.70.jar:9.0.70]
	at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.70.jar:9.0.70]
	at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1240) ~[tomcat-embed-core-9.0.70.jar:9.0.70]
	at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:604) ~[tomcat-embed-core-9.0.70.jar:9.0.70]
	at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:76) ~[tomcat-embed-core-9.0.70.jar:9.0.70]
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:1047) ~[tomcat-embed-core-9.0.70.jar:9.0.70]
	... 21 common frames omitted

Also verwenden wir jdk19

<properties>
        <java.version>19</java.version>
    </properties>

2. Springboot-integrierte Tomcat-Attributkonfiguration

Mit dem integrierten Tomcat von Springboot lässt sich das Unix-Domain-Socket-Protokoll sehr einfach konfigurieren. Sie müssen es nur festlegenconnector.setProperty("unixDomainSocketPath","D:\\http.sock")

package com.example.tomcat19.config;

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MyTomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
    
    

    @Override
    public void customize(TomcatServletWebServerFactory server) {
    
    
        server.addConnectorCustomizers((connector) -> {
    
    
                    //connector.setAsyncTimeout(Duration.ofSeconds(20).toMillis());
                    //connector.setProperty("protocol","org.apache.coyote.http11.Http11NioProtocol");
                    connector.setProperty("unixDomainSocketPath","D:\\http.sock");
                }
        );
    }
}

3. Serverseitige Testschnittstelle

package com.example.tomcat19.action;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class TestAction {
    
    

    @GetMapping("/test")
    public String test(){
    
    
        log.info("收到请求id:1");
        return "哈哈哈";
    }

}

Struktur des Serverprojekts:
Fügen Sie hier eine Bildbeschreibung ein

4. Kunden anfordern

Um die Überprüfung zu erleichtern, verwenden wir hier socketdas http.sockSenden von HTTP-Anforderungsnachrichten an den Server.

package com.sk.init;

import java.net.StandardProtocolFamily;
import java.net.UnixDomainSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class Test {
    
    

    public static void main(String[] args) throws Exception{
    
    
        // 建立 Unix Socket 连接
        //File sockFile = new File("D:\\http.sock");
        SocketChannel socketChannel = SocketChannel.open(StandardProtocolFamily.UNIX);

        UnixDomainSocketAddress of = UnixDomainSocketAddress.of("D:\\http.sock");
        //UnixDomainSocketAddress of = UnixDomainSocketAddress.of("D:\\test.sock");
        boolean connect = socketChannel.connect(of);
        System.out.println(connect);

        String newData = "this is domain socket..." + System.currentTimeMillis();
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("GET /test HTTP/1.1").append("\n");
       
        stringBuffer.append("Host: 127.0.0.1").append("\r\n");
        stringBuffer.append("Connection: keep-alive").append("\r\n");
        stringBuffer.append("Cache-Control: max-age=0").append("\r\n");
        stringBuffer.append("sec-ch-ua: \" Not A;Brand\";v=\"99\", \"Chromium\";v=\"100\", \"Google Chrome\";v=\"100\"").append("\r\n");
        stringBuffer.append("sec-ch-ua-mobile: ?0").append("\r\n");
        stringBuffer.append("sec-ch-ua-platform: \"Windows\"").append("\r\n");
        stringBuffer.append("Upgrade-Insecure-Requests: 1").append("\r\n");
        stringBuffer.append("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36").append("\r\n");
        stringBuffer.append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9").append("\r\n");
        stringBuffer.append("Sec-Fetch-Site: none").append("\r\n");
        stringBuffer.append("Sec-Fetch-Mode: navigate").append("\r\n");
        stringBuffer.append("Sec-Fetch-User: ?1").append("\r\n");
        stringBuffer.append("Sec-Fetch-Dest: document").append("\r\n");
        stringBuffer.append("Accept-Encoding: gzip, deflate, br").append("\r\n");
        stringBuffer.append("Accept-Language: zh-CN,zh;q=0.9").append("\r\n");
        stringBuffer.append("\r\n");

        //stringBuffer.append("Accept: */*").append("\r\n");
        ByteBuffer buf = ByteBuffer.allocate(2048);
        buf.clear();
        buf.put(stringBuffer.toString().getBytes());
        //buf.put(newData.getBytes());
        buf.flip();
        while (buf.hasRemaining()) {
    
    
            socketChannel.write(buf);
        }
        socketChannel.close();
    }

}

5. Fordern Sie Ergebnisse an

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::       (v3.0.2-SNAPSHOT)

23:06:54.720 [main] INFO  org.springframework.boot.StartupInfoLogger.logStarting(StartupInfoLogger.java:51) - Starting Tomcat19Application using Java 19.0.1 with PID 6248 (G:\work3\UDS redis\tomcat19\target\classes started by Administrator in G:\work3\UDS redis\tomcat19)
23:06:54.962 [main] INFO  org.springframework.boot.SpringApplication.logStartupProfileInfo(SpringApplication.java:630) - No active profile set, falling back to 1 default profile: "default"
23:06:55.895 [main] INFO  org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:108) - Tomcat initialized with port(s): 8086 (http)
23:06:55.905 [main] INFO  org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:173) - Initializing ProtocolHandler ["http-nio-D:\\http.sock"]
23:06:55.906 [main] INFO  org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:173) - Starting service [Tomcat]
23:06:55.906 [main] INFO  org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:173) - Starting Servlet engine: [Apache Tomcat/10.1.4]
23:06:55.996 [main] INFO  org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:173) - Initializing Spring embedded WebApplicationContext
23:06:55.996 [main] INFO  org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext(ServletWebServerApplicationContext.java:291) - Root WebApplicationContext: initialization completed in 991 ms
23:06:56.344 [main] INFO  org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:173) - Starting ProtocolHandler ["http-nio-D:\\http.sock"]
23:06:56.364 [main] INFO  org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:220) - Tomcat started on port(s): -1 (http) with context path ''
23:06:56.374 [main] INFO  org.springframework.boot.StartupInfoLogger.logStarted(StartupInfoLogger.java:57) - Started Tomcat19Application in 2.287 seconds (process running for 4.057)
23:07:12.012 [http-nio-D:\\http.sock-exec-1] INFO  org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:173) - Initializing Spring DispatcherServlet 'dispatcherServlet'
23:07:12.032 [http-nio-D:\\http.sock-exec-1] INFO  org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:532) - Initializing Servlet 'dispatcherServlet'
23:07:12.033 [http-nio-D:\\http.sock-exec-1] INFO  org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:554) - Completed initialization in 1 ms
23:07:12.062 [http-nio-D:\\http.sock-exec-1] INFO  com.example.tomcat19.action.TestAction.test(TestAction.java:13) - 收到请求id:1

5. Springboot External Tomcat konfiguriert den Unixdomainsocket

<Service name="CatalinaLocal">
        <Connector
            protocol="org.apache.coyote.http11.Http11AprProtocol"
            unixDomainSocketPath="/opt/app-name/http.sock" />
        <Engine
            defaultHost="localhost"
            name="Catalina">
            <Host
                name="localhost"
                appBase="webapps"
                unpackWARs="true"
                autoDeploy="false"
                deployIgnore="(?!.*hawtio).*">
                <Valve
                    className="org.apache.catalina.valves.RemoteIpValve" />
            </Host>
        </Engine>
    </Service>

Hinweis: Die Konfiguration hier wurde nicht überprüft. Wenn Sie interessiert sind, können Sie sie in der Praxis testen.

6. Zusammenfassung

unix域套接字协议Es ist immer noch sehr nützlich, insbesondere wenn es um die Leistungsoptimierung geht. Die Microservice-Architekturen vieler großer Hersteller unterstützen das Unix Domain Socket Protocol;

=Wenn der Artikel für Sie hilfreich ist, liken Sie ihn bitte und sammeln Sie ihn=====================

Supongo que te gusta

Origin blog.csdn.net/weixin_37598243/article/details/128488839
Recomendado
Clasificación