Browse Source

add java isocket-nio to test,thanks (#6674)

* add isocket-nio

* remove global message and instance message every request
longzl 4 years ago
parent
commit
94f74ee1f3

+ 23 - 0
frameworks/Java/isocket-nio/README.md

@@ -0,0 +1,23 @@
+# isocket-nio Benchmarking Test
+
+
+This is the isocket-nio portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+* [Plaintext test source](src/main/java/cn/ibaijia/tfb/HttpBootstrap.java)
+* [JSON test source](src/main/java/cn/ibaijia/tfb/HttpBootstrap.java)
+
+## Versions
+
+* [Java OpenJDK 1.8](http://openjdk.java.net/)
+* [isocket-nio 1.0.2](https://gitee.com/longzhili2005/soe)
+
+## Test URLs
+    
+### JSON Encoding Test
+
+    http://localhost:8080/json
+    
+### Plaintext Encoding Test
+
+    http://localhost:8080/plaintext

+ 26 - 0
frameworks/Java/isocket-nio/benchmark_config.json

@@ -0,0 +1,26 @@
+{
+  "framework": "isocket-nio",
+  "tests": [
+    {
+      "default": {
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Platform",
+        "database": "None",
+        "framework": "isocket-nio",
+        "language": "Java",
+        "flavor": "None",
+        "orm": "Raw",
+        "platform": "isocket-nio",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "isocket-nio",
+        "notes": "",
+        "versus": "isocket-nio"
+      }
+    }
+  ]
+}

+ 15 - 0
frameworks/Java/isocket-nio/config.toml

@@ -0,0 +1,15 @@
+[framework]
+name = "isocket-nio"
+
+[main]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+approach = "Realistic"
+classification = "Platform"
+database = "None"
+database_os = "Linux"
+os = "Linux"
+orm = "Raw"
+platform = "None"
+webserver = "None"
+versus = "isocket-nio"

+ 13 - 0
frameworks/Java/isocket-nio/isocket-nio.dockerfile

@@ -0,0 +1,13 @@
+FROM maven:3.6.1-jdk-11-slim as maven
+WORKDIR /isocket
+COPY pom.xml pom.xml
+COPY src src
+RUN mvn clean compile assembly:single -q
+
+FROM openjdk:11.0.3-jdk-slim
+WORKDIR /isocket
+COPY --from=maven /isocket/target/isocket-nio-benchmark-1.0-jar-with-dependencies.jar app.jar
+
+EXPOSE 8080
+
+CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-cp", "app.jar", "cn.ibaijia.tfb.HttpBootstrap"]

+ 126 - 0
frameworks/Java/isocket-nio/pom.xml

@@ -0,0 +1,126 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>cn.ibaijia</groupId>
+    <artifactId>isocket-nio-benchmark</artifactId>
+    <version>1.0</version>
+    <packaging>jar</packaging>
+    <properties>
+        <slf4j.version>1.7.7</slf4j.version>
+        <log4j.version>1.2.17</log4j.version>
+        <log4j2.version>2.7</log4j2.version>
+        <isocket.version>1.0.3-SNAPSHOT</isocket.version>
+        <fastjson.version>1.2.44</fastjson.version>
+    </properties>
+
+    <repositories><!-- 代码库 -->
+        <repository>
+            <id>ossrh</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <snapshots>
+                <enabled>true</enabled>
+                <updatePolicy>always</updatePolicy>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>cn.ibaijia</groupId>
+            <artifactId>isocket-nio</artifactId>
+            <version>${isocket.version}</version>
+        </dependency>
+        <!-- 格式化对象 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+            <!--<scope>provided</scope>-->
+        </dependency>
+        <!-- log start -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <version>${log4j2.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>${log4j2.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>${log4j2.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.lmax</groupId>
+            <artifactId>disruptor</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity -->
+    </dependencies>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>central</id>
+            <name>Central Repository</name>
+            <url>https://repo.maven.apache.org/maven2</url>
+        </pluginRepository>
+        <pluginRepository>
+            <id>sonatype-nexus-snapshots</id>
+            <name>Sonatype Nexus Snapshots</name>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+                <updatePolicy>always</updatePolicy>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <failOnError>true</failOnError>
+                    <verbose>true</verbose>
+                    <fork>true</fork>
+                    <compilerArgument>-nowarn</compilerArgument>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                    <encoding>UTF-8</encoding>
+                    <debug>false</debug>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 28 - 0
frameworks/Java/isocket-nio/src/main/java/cn/ibaijia/tfb/HttpBootstrap.java

@@ -0,0 +1,28 @@
+package cn.ibaijia.tfb;
+
+import cn.ibaijia.isocket.Server;
+import cn.ibaijia.isocket.listener.SessionProcessErrorListener;
+import cn.ibaijia.isocket.session.Session;
+import cn.ibaijia.tfb.processor.PlanTextProcessor;
+import cn.ibaijia.tfb.protocol.SimpleHttpProtocol;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HttpBootstrap {
+    private static final Logger logger = LoggerFactory.getLogger(HttpBootstrap.class);
+
+    public static void main(String[] args) {
+        Server server = new Server("0.0.0.0", 8080);
+        server.addProtocol(new SimpleHttpProtocol());
+        server.setProcessor(new PlanTextProcessor());
+        server.setSessionProcessErrorListener(new SessionProcessErrorListener() {
+            @Override
+            public void run(Session session, Object o, Throwable throwable) {
+                logger.error("session on process error.", throwable);
+            }
+        });
+//        server.setThreadNumber(16);
+        server.start();
+    }
+
+}

+ 12 - 0
frameworks/Java/isocket-nio/src/main/java/cn/ibaijia/tfb/http/Header.java

@@ -0,0 +1,12 @@
+package cn.ibaijia.tfb.http;
+
+public class Header {
+
+    public String name;
+    public String value;
+
+    public Header(String name, String value) {
+        this.name = name;
+        this.value = value;
+    }
+}

+ 10 - 0
frameworks/Java/isocket-nio/src/main/java/cn/ibaijia/tfb/http/HttpEntity.java

@@ -0,0 +1,10 @@
+package cn.ibaijia.tfb.http;
+
+public abstract class HttpEntity {
+
+    public String charset = "UTF-8";
+
+    public abstract String getHeader(String name);
+    public abstract void setHeader(String name,String value);
+
+}

+ 99 - 0
frameworks/Java/isocket-nio/src/main/java/cn/ibaijia/tfb/http/HttpRequestEntity.java

@@ -0,0 +1,99 @@
+package cn.ibaijia.tfb.http;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpRequestEntity extends HttpEntity {
+
+    public ByteBuffer headerBuffer = ByteBuffer.allocate(4 * 1024);
+    public ByteBuffer bodyBuffer = null;
+    public boolean chunked = false;
+    public int contentLength = -1;
+    public int crlfNum = 0;
+
+    private static final String CONTENT_LENGTH = "CONTENT-LENGTH";
+    private static final String TRANSFER_ENCODING = "TRANSFER-ENCODING";
+    private static final String CHUNKED = "CHUNKED";
+
+    //请求行
+    private String headLine;
+    public String method;
+    public String url;
+    public String protocol;
+
+    //请求体
+    public String body;
+    //第一次 请求header时解析 第一行不要
+    private String[] headersArr;
+    private Map<String, String> headers;
+
+    public boolean headerComplete() {
+        return crlfNum == 4;
+    }
+
+    public void processHeader() {
+        headerBuffer.flip();
+        byte[] bytes = new byte[headerBuffer.remaining()];
+        headerBuffer.get(bytes);
+        String str = new String(bytes);
+        headersArr = str.split("\r\n");
+        if (headersArr.length > 0) {
+            headLine = headersArr[0];
+            String[] arr = headLine.split(" ");
+            method = arr[0];
+            url = arr[1];
+            protocol = arr[2];
+            //
+            String lengthStr = getHeader(CONTENT_LENGTH);
+            contentLength = lengthStr == null ? 0 : Integer.valueOf(lengthStr);
+            chunked = CHUNKED.equalsIgnoreCase(getHeader(TRANSFER_ENCODING));
+            if (chunked) {
+                //TODO
+                throw new RuntimeException("not support chunked");
+            }
+            if (contentLength > 0) {
+                bodyBuffer = ByteBuffer.allocate(contentLength);
+            }
+        }
+    }
+
+    private Map<String, String> getHeaders() {
+        if (headers == null) {
+            headers = new HashMap<>();
+            boolean firstLine = true;
+            for (String header : headersArr) {
+                if (firstLine) {
+                    continue;
+                }
+                String[] arr = header.split(":", 2);
+                headers.put(arr[0], arr[1]);
+            }
+        }
+        return headers;
+    }
+
+    public String getHeader(String name) {
+        return getHeaders().get(name);
+    }
+
+    @Override
+    public void setHeader(String name, String value) {
+        // TODO
+    }
+
+    public void processBody() {
+        bodyBuffer.flip();
+        byte[] bytes = new byte[bodyBuffer.remaining()];
+        bodyBuffer.get(bytes);
+        body = new String(bytes);
+    }
+
+    public boolean complete() {
+        if (contentLength == 0) {
+            return true;
+        } else {
+            return body != null;
+        }
+    }
+}

+ 54 - 0
frameworks/Java/isocket-nio/src/main/java/cn/ibaijia/tfb/http/HttpResponseEntity.java

@@ -0,0 +1,54 @@
+package cn.ibaijia.tfb.http;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpResponseEntity extends HttpEntity {
+    public static final String protocol = "HTTP/1.1";
+    public int statusCode = 200;
+    public String status = "OK";
+
+    //响应体
+    public String body = "";
+
+    //请求头 或者 响应头
+    public Map<String, String> headers = new HashMap<>();
+
+    @Override
+    public String getHeader(String name) {
+        return headers.get(name);
+    }
+
+    @Override
+    public void setHeader(String name, String value) {
+        headers.put(name, value);
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    public void setStatusCode(int statusCode) {
+        this.statusCode = statusCode;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public ByteBuffer toBuffer() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(protocol).append(" ").append(statusCode).append(" ").append(status).append("\r\n");
+        sb.append("Content-Length:" + body.length()).append("\r\n");
+        for (Map.Entry<String, String> header : headers.entrySet()) {
+            sb.append(header.getKey()).append(":").append(header.getValue()).append("\r\n");
+        }
+        sb.append("\r\n").append(body);
+        return ByteBuffer.wrap(sb.toString().getBytes());
+    }
+}

+ 10 - 0
frameworks/Java/isocket-nio/src/main/java/cn/ibaijia/tfb/processor/Message.java

@@ -0,0 +1,10 @@
+package cn.ibaijia.tfb.processor;
+
+public class Message {
+
+    public String message;
+
+    public Message(String message) {
+        this.message = message;
+    }
+}

+ 68 - 0
frameworks/Java/isocket-nio/src/main/java/cn/ibaijia/tfb/processor/PlanTextProcessor.java

@@ -0,0 +1,68 @@
+package cn.ibaijia.tfb.processor;
+
+import cn.ibaijia.isocket.processor.Processor;
+import cn.ibaijia.isocket.session.Session;
+import cn.ibaijia.tfb.http.HttpEntity;
+import cn.ibaijia.tfb.http.HttpRequestEntity;
+import cn.ibaijia.tfb.http.HttpResponseEntity;
+import cn.ibaijia.tfb.protocol.SimpleHttpProtocol;
+import com.alibaba.fastjson.JSON;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class PlanTextProcessor implements Processor<HttpEntity> {
+    private static final Logger logger = LoggerFactory.getLogger(PlanTextProcessor.class);
+    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
+    private static final String SERVER_NAME = "isocket-nio-tfb";
+
+    @Override
+    public boolean process(Session session, HttpEntity httpEntity) {
+        HttpRequestEntity httpRequestEntity = (HttpRequestEntity) httpEntity;
+        logger.trace("url:{}", httpRequestEntity.url);
+        if (httpRequestEntity.url.contains("/plaintext")) {
+            HttpResponseEntity httpResponseEntity = new HttpResponseEntity();
+            httpResponseEntity.setHeader("Content-Type", "text/plain; charset=UTF-8");
+            httpResponseEntity.setHeader("Server", SERVER_NAME);
+            httpResponseEntity.setHeader("Date", dateFormat.format(new Date()));
+            httpResponseEntity.body = "Hello, World!";
+            session.write(httpResponseEntity);
+        } else if (httpRequestEntity.url.contains("/json")) {
+            HttpResponseEntity httpResponseEntity = new HttpResponseEntity();
+            httpResponseEntity.setHeader("Content-Type", "application/json; charset=UTF-8");
+            httpResponseEntity.setHeader("Server", SERVER_NAME);
+            httpResponseEntity.setHeader("Date", dateFormat.format(new Date()));
+            httpResponseEntity.body = JSON.toJSONString(new Message("Hello, World!"));
+            session.write(httpResponseEntity);
+        } else {
+            HttpResponseEntity httpResponseEntity = new HttpResponseEntity();
+            httpResponseEntity.setHeader("Content-Type", "text/plain");
+            httpResponseEntity.setHeader("Server", SERVER_NAME);
+            httpResponseEntity.setHeader("Date", dateFormat.format(new Date()));
+            httpResponseEntity.body = "hi";
+            session.write(httpResponseEntity);
+        }
+//        String connection = httpRequestEntity.getHeader("Connection");
+//        logger.trace("Connection:{}", connection);
+//        if (connection == null || "close".equals(connection)) {
+//            session.close(false); //TODO
+//        }
+        return true;
+    }
+
+    @Override
+    public void processError(Session session, HttpEntity httpEntity, Throwable throwable) {
+        logger.error("processError:", throwable);
+        HttpResponseEntity httpResponseEntity = new HttpResponseEntity();
+        httpResponseEntity.setHeader("Content-Type", "text/plain");
+        httpResponseEntity.setHeader("Server", SERVER_NAME);
+        httpResponseEntity.setHeader("Date", dateFormat.format(new Date()));
+        httpResponseEntity.body = "hi";
+        httpResponseEntity.statusCode = 500;
+        httpResponseEntity.status = "Internal Server Error";
+        session.write(httpResponseEntity);
+    }
+}

+ 100 - 0
frameworks/Java/isocket-nio/src/main/java/cn/ibaijia/tfb/protocol/SimpleHttpProtocol.java

@@ -0,0 +1,100 @@
+package cn.ibaijia.tfb.protocol;
+
+import cn.ibaijia.isocket.Server;
+import cn.ibaijia.isocket.protocol.Protocol;
+import cn.ibaijia.isocket.session.Session;
+import cn.ibaijia.tfb.http.HttpEntity;
+import cn.ibaijia.tfb.http.HttpRequestEntity;
+import cn.ibaijia.tfb.http.HttpResponseEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.ByteBuffer;
+
+public class SimpleHttpProtocol implements Protocol<ByteBuffer, HttpEntity> {
+
+    private static final Logger logger = LoggerFactory.getLogger(SimpleHttpProtocol.class);
+
+    private static final byte CRLF13 = (byte) 13; // \r
+    private static final byte CRLF10 = (byte) 10; // \n
+
+    private static final String httpEntityKey = "httpEntity";
+
+    /**
+     * 解析HTTP请求
+     *
+     * @param byteBuffer
+     * @param session
+     * @return
+     */
+    @Override
+    public HttpEntity decode(ByteBuffer byteBuffer, Session session) {
+        HttpRequestEntity httpEntity = (HttpRequestEntity) session.getAttribute(httpEntityKey);
+        if (httpEntity == null) {
+            httpEntity = new HttpRequestEntity();
+            session.setAttribute(httpEntityKey, httpEntity);
+        }
+
+        if (byteBuffer.hasRemaining() && !httpEntity.headerComplete()) { //解析header
+            readHeader(byteBuffer, session, httpEntity);
+        }
+
+        if (httpEntity.bodyBuffer != null && byteBuffer.hasRemaining() && httpEntity.headerComplete()) {// 解析body
+            readBody(byteBuffer, session, httpEntity);
+        }
+
+        if (httpEntity.complete()) {
+            session.setAttribute(httpEntityKey, null);
+            return httpEntity;
+        }
+
+        return null;
+    }
+
+    private void readHeader(ByteBuffer byteBuffer, Session session, HttpRequestEntity httpEntity) {
+        try {
+            while (byteBuffer.hasRemaining()) {
+                byte b = byteBuffer.get();
+                if (b == CRLF10 || b == CRLF13) {
+                    httpEntity.crlfNum++;
+                } else {
+                    httpEntity.crlfNum = 0;
+                }
+                httpEntity.headerBuffer.put(b);
+                if (httpEntity.crlfNum == 4) {
+                    //处理header
+                    httpEntity.processHeader();
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            logger.error("readHeader error.", e);
+        }
+    }
+
+    private void readBody(ByteBuffer byteBuffer, Session session, HttpRequestEntity httpEntity) {
+        try {
+            if (httpEntity.bodyBuffer.hasRemaining()) {
+                if (byteBuffer.remaining() <= httpEntity.bodyBuffer.remaining()) {
+                    httpEntity.bodyBuffer.put(byteBuffer);
+                } else {
+                    byte[] bytes = new byte[httpEntity.bodyBuffer.remaining()];
+                    byteBuffer.get(bytes);
+                    httpEntity.bodyBuffer.put(bytes);
+                }
+            }
+            if (!httpEntity.bodyBuffer.hasRemaining()) {
+                httpEntity.processBody();
+            }
+        } catch (Exception e) {
+            logger.error("readHeader error.", e);
+        }
+    }
+
+    @Override
+    public ByteBuffer encode(HttpEntity httpEntity, Session session) {
+        HttpResponseEntity httpResponseEntity = (HttpResponseEntity) httpEntity;
+
+        return httpResponseEntity.toBuffer();
+    }
+}

+ 35 - 0
frameworks/Java/isocket-nio/src/main/resources/log4j2.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="info">
+    <Properties>
+        <Property name="logName">isocket-nio-tfb</Property>
+    </Properties>
+    <Appenders>
+        <Console name="console" target="SYSTEM_OUT">
+            <PatternLayout pattern="[%d{MM-dd HH:mm:ss}] %p [%t] %c - %m%n"/>
+        </Console>
+        <RollingFile name="file" fileName="logs/${logName}.log"  filePattern="logs/${logName}.log.%d{yyyy-MM-dd}">
+            <PatternLayout>
+                <Pattern>[%d{MM-dd HH:mm:ss}] %p [%c][%t] - %m%n</Pattern>
+            </PatternLayout>
+            <Policies>
+                <!-- 每天滚存日志 -->
+                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
+            </Policies>
+            <DefaultRolloverStrategy>
+                <Delete basePath="logs" maxDepth="1">
+                    <IfFileName glob="*.log.*"/>
+                    <!-- 日志保存时间 -->
+                    <IfLastModified age="10d"/>
+                </Delete>
+            </DefaultRolloverStrategy>
+        </RollingFile>
+    </Appenders>
+    <Loggers>
+        <logger name="cn.ibaijia.tfb" level="info"/>
+        <logger name="cn.ibaijia.isocket" level="info"/>
+        <Root level="info">
+            <AppenderRef ref="console"/>
+            <AppenderRef ref="file"/>
+        </Root>
+    </Loggers>
+</Configuration>