顯示具有 spring boot 標籤的文章。 顯示所有文章
顯示具有 spring boot 標籤的文章。 顯示所有文章

Sprint Boot - List files to Flux

Books suggestion
@GetMapping("/unable_files")
public Flux<FileInfo> wrongListFiles() throws IOException {
    return Flux.fromIterable(Files.newDirectoryStream(Paths.get("C:/Python33")))
            .map(path -> new FileInfo(path.getFileName().toString(), path.toAbsolutePath().toString()));
}

But it always encounter error
2020-05-17 02:45:23.134 ERROR 6980 --- [ctor-http-nio-2] a.w.r.e.AbstractErrorWebExceptionHandler : [3b6f7b07-1]  500 Server Error for HTTP GET "/unable_files"

java.lang.IllegalStateException: Iterator already obtained
    at sun.nio.fs.WindowsDirectoryStream.iterator(WindowsDirectoryStream.java:117) ~[na:1.8.0_92]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
    |_ checkpoint ? Handler com.example.demo.FileController#wrongListFiles() [DispatcherHandler]
    |_ checkpoint ? HTTP GET "/unable_files" [ExceptionHandlingWebHandler]
Stack trace:
        at sun.nio.fs.WindowsDirectoryStream.iterator(WindowsDirectoryStream.java:117) ~[na:1.8.0_92]
        at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:79) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]

Fixed
  • FIleInfo.java 
package com.example.demo;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class FileInfo {

    private String name;
    private String path;

}
  • list files
@GetMapping("/files")
public Flux<FileInfo> listFiles() throws IOException {
    return Flux.fromStream(Files.list(Paths.get("C:/Python33")))
            .map(path -> new FileInfo(path.getFileName().toString(), path.toAbsolutePath().toString()));
}

Client
$ curl -s http://localhost:8080/files
[{"name":"DLLs","path":"C:\\Python33\\DLLs"},{"name":"Doc","path":"C:\\Python33\\Doc"},{"name":"include","path":"C:\\Python33\\include"},{"name":"isaac","path":"C:\\Python33\\isaac"},{"name":"Lib","path":"C:\\Python33\\Lib"},{"name":"libs","path":"C:\\Python33\\libs"},{"name":"LICENSE.txt","path":"C:\\Python33\\LICENSE.txt"},{"name":"NEWS.txt","path":"C:\\Python33\\NEWS.txt"},{"name":"python.exe","path":"C:\\Python33\\python.exe"},{"name":"pythonw.exe","path":"C:\\Python33\\pythonw.exe"},{"name":"q.py","path":"C:\\Python33\\q.py"},{"name":"README.txt","path":"C:\\Python33\\README.txt"},{"name":"say.py","path":"C:\\Python33\\say.py"},{"name":"Scripts","path":"C:\\Python33\\Scripts"},{"name":"tcl","path":"C:\\Python33\\tcl"},{"name":"test.py","path":"C:\\Python33\\test.py"},{"name":"Tools","path":"C:\\Python33\\Tools"},{"name":"__pycache__","path":"C:\\Python33\\__pycache__"}]

Spring Boot - Flux and RequestBody

  • Controller
  • @RestController
    public class RequestBodyController {

        @PostMapping("/requestBodyFlux")
        public Mono<Void> postFlux(@RequestBody Flux<String> ids) {
            return ids.map(id -> {
                String s = "id:" + id;
                System.out.println(s);
                return s;
            }).then();
        }

    }

  • Client
  • isaac@isaac-PC MINGW64 ~/workspace_github
    $ curl -s -v -H 'Content-Type:application/json' -X POST -d '["a","b","c"]'  http://localhost:8080/requestBodyFlux
    *   Trying ::1...
    * TCP_NODELAY set
    * Connected to localhost (::1) port 8080 (#0)
    > POST /requestBodyFlux HTTP/1.1
    > Host: localhost:8080
    > User-Agent: curl/7.60.0
    > Accept: */*
    > Content-Type:application/json
    > Content-Length: 13
    >
    } [13 bytes data]
    * upload completely sent off: 13 out of 13 bytes
    < HTTP/1.1 200 OK
    < content-length: 0
    <
    * Connection #0 to host localhost left intact

  • Server
  • C:\Users\isaac\workspace_github\spring-boot-study>gradle bootRun
    Starting a Gradle Daemon, 4 busy Daemons could not be reused, use --status for details

    > Task :bootRun

      .   ____          _            __ _ _
    /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
    \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
    =========|_|==============|___/=/_/_/_/
    :: Spring Boot ::        (v2.2.7.RELEASE)

    2020-05-17 01:51:11.297  INFO 4060 --- [  restartedMain] com.example.demo.DemoApplication         : Starting DemoApplication on isaac-PC with PID 4060 (C:\Users\isaac\workspace_github\spring-boot-study\build\classes\java\main started by isaac in C:\Users\
    isaac\workspace_github\spring-boot-study)
    2020-05-17 01:51:11.300  INFO 4060 --- [  restartedMain] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
    2020-05-17 01:51:11.364  INFO 4060 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
    2020-05-17 01:51:11.364  INFO 4060 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
    2020-05-17 01:51:14.302  INFO 4060 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
    2020-05-17 01:51:14.634  INFO 4060 --- [  restartedMain] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
    2020-05-17 01:51:14.638  INFO 4060 --- [  restartedMain] com.example.demo.DemoApplication         : Started DemoApplication in 3.781 seconds (JVM running for 4.585)
    id:["a","b","c"]


Spring Boot - Helloworld

Download Spring Initializer

HelloController.java
package com.example.demo;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;


@RestController
public class HelloController {

    @GetMapping
    public String hello(@RequestParam(defaultValue = "", required = false) String name) {
        return "hello " + name;
    }

    @GetMapping("/ids")
    public Flux<String> ids() {
        return Flux.just("1","2","3");
    }
}

Run bootRun
gradle bootRun
Starting a Gradle Daemon, 1 busy and 1 incompatible and 1 stopped Daemons could not be reused, use --status for details

> Task :bootRun

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::        (v2.2.7.RELEASE)


2020-05-12 23:30:11.100  INFO 6864 --- [  restartedMain] com.example.demo.DemoApplication         : Starting DemoApplication on isaac-PC with PID 6864 (C:\Users\isaac\workspace_github\study-practice\build\classes\java\main started by isaac in C:\Users\isa
ac\workspace_github\study-practice)
2020-05-12 23:30:11.103  INFO 6864 --- [  restartedMain] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2020-05-12 23:30:11.150  INFO 6864 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-05-12 23:30:11.150  INFO 6864 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2020-05-12 23:30:12.218  INFO 6864 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2020-05-12 23:30:12.470  INFO 6864 --- [  restartedMain] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2020-05-12 23:30:12.475  INFO 6864 --- [  restartedMain] com.example.demo.DemoApplication         : Started DemoApplication in 1.683 seconds (JVM running for 2.171)
<=========----> 75% EXECUTING [52s]
> :bootRun

Curl example
$ curl -s http://localhost:8080/ids
123

$ curl -s http://localhost:8080
hello

$ curl -s http://localhost:8080?name=QQQ
hello QQQ



Lessons Learned While Benchmarking vLLM with GPU

Recently, I benchmarked vLLM on a GPU to better understand how much throughput can realistically be expected in an LLM serving setup. One ...