mirror of
https://github.com/criyle/go-judge.git
synced 2025-11-04 14:50:02 +08:00
Add environment variable controls
This commit is contained in:
parent
d6f5660d6c
commit
140aeffcd9
22
README.md
22
README.md
@ -28,7 +28,8 @@ A rest service to run program in restricted environment and it is basically a wr
|
||||
- /file/:fileId GET downloads file from executor service (in memory), returns file content
|
||||
- /file/:fileId DELETE delete file specified by fileId
|
||||
- /ws WebSocket for /run
|
||||
- /metrics prometheus metrics
|
||||
- /metrics prometheus metrics (specifies `METRICS=1` environment variable to enable metrics)
|
||||
- /debug (specifies `DEBUG=1` environment variable to enable go runtime debug endpoint)
|
||||
|
||||
### Install & Run Developing Server
|
||||
|
||||
@ -49,15 +50,22 @@ Build by your own `docker build -t executorserver -f Dockerfile.exec .`
|
||||
|
||||
The `executorserver` need root privilege to create `cgroup`. Either creates sub-directory `/sys/fs/cgroup/cpuacct/go-judger`, `/sys/fs/cgroup/memory/go-judger`, `/sys/fs/cgroup/pids/go-judger` and make execution user readable or use `sudo` to run it.
|
||||
|
||||
The default binding address for the executor server is `:5050`. Can be specified with `-http` flag.
|
||||
#### Command Line Arguments
|
||||
|
||||
The default binding address for the gRPC executor server is `:5051`. Can be specified with `-grpc` flag.
|
||||
- The default binding address for the executor server is `:5050`. Can be specified with `-http` flag.
|
||||
- The default binding address for the gRPC executor server is `:5051`. Can be specified with `-grpc` flag. (Notice: need to set `GRPC=1` environment variable to enable GRPC endpoint)
|
||||
- The default concurrency is `4`, Can be specified with `-parallism` flag.
|
||||
- The default file store is in memory, local cache can be specified with `-dir` flag.
|
||||
- The default log level is debug, use `-silent` to disable logs.
|
||||
|
||||
The default concurrency is `4`, Can be specified with `-parallism` flag.
|
||||
#### Environment Variables
|
||||
|
||||
The default file store is in memory, local cache can be specified with `-dir` flag.
|
||||
|
||||
The default log level is debug, use `-silent` to disable logs.
|
||||
- The http binding address specifies as `HTTP_ADDR=addr`
|
||||
- The grpc binding address specifies as `GRPC_ADDR=addr`
|
||||
- The parallism specifies as `PARALLISM=4`
|
||||
- `GRPC=1` enables gRPC
|
||||
- `METRICS=1` enables metrics
|
||||
- `DEBUG=1` enables debug
|
||||
|
||||
### Build Shared object
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -27,6 +27,16 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
const (
|
||||
envDebug = "DEBUG"
|
||||
envMetrics = "METRICS"
|
||||
|
||||
envAddr = "HTTP_ADDR"
|
||||
envGRPC = "GRPC"
|
||||
envGRPCAddr = "GRPC_ADDR"
|
||||
envParallism = "PARALLISM"
|
||||
)
|
||||
|
||||
var (
|
||||
addr = flag.String("http", ":5050", "specifies the http binding address")
|
||||
grpcAddr = flag.String("grpc", ":5051", "specifies the grpc binding address")
|
||||
@ -38,8 +48,6 @@ var (
|
||||
mountConf = flag.String("mount", "mount.yaml", "specifics mount configuration file")
|
||||
cinitPath = flag.String("cinit", "", "container init absolute path")
|
||||
|
||||
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
|
||||
|
||||
printLog = func(v ...interface{}) {}
|
||||
|
||||
work *worker.Worker
|
||||
@ -56,25 +64,39 @@ func newFilsStore(dir string) filestore.FileStore {
|
||||
return fs
|
||||
}
|
||||
|
||||
func initEnv() (bool, error) {
|
||||
eneableGRPC := false
|
||||
if s := os.Getenv(envAddr); s != "" {
|
||||
addr = &s
|
||||
}
|
||||
if os.Getenv(envGRPC) == "1" {
|
||||
eneableGRPC = true
|
||||
}
|
||||
if s := os.Getenv(envGRPCAddr); s != "" {
|
||||
eneableGRPC = true
|
||||
grpcAddr = &s
|
||||
}
|
||||
if s := os.Getenv(envParallism); s != "" {
|
||||
p, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
parallism = &p
|
||||
}
|
||||
return eneableGRPC, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if *cpuprofile != "" {
|
||||
f, err := os.Create(*cpuprofile)
|
||||
if err != nil {
|
||||
log.Fatal("could not create CPU profile: ", err)
|
||||
}
|
||||
defer f.Close() // error handling omitted for example
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
log.Fatal("could not start CPU profile: ", err)
|
||||
}
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
if !*silent {
|
||||
printLog = log.Println
|
||||
}
|
||||
enableGRPC, err := initEnv()
|
||||
if err != nil {
|
||||
log.Fatalln("init environment variable failed", err)
|
||||
}
|
||||
|
||||
// Init environment pool
|
||||
fs := newFilsStore(*dir)
|
||||
b, err := env.NewBuilder(*cinitPath, *mountConf, *tmpFsParam, *netShare, printLog)
|
||||
if err != nil {
|
||||
@ -95,17 +117,19 @@ func main() {
|
||||
}
|
||||
|
||||
// Metrics Handle
|
||||
p := ginprometheus.NewPrometheus("gin")
|
||||
p.ReqCntURLLabelMappingFn = func(c *gin.Context) string {
|
||||
url := c.Request.URL.Path
|
||||
for _, p := range c.Params {
|
||||
if p.Key == "fid" {
|
||||
url = strings.Replace(url, p.Value, ":fid", 1)
|
||||
if os.Getenv(envMetrics) == "1" {
|
||||
p := ginprometheus.NewPrometheus("gin")
|
||||
p.ReqCntURLLabelMappingFn = func(c *gin.Context) string {
|
||||
url := c.Request.URL.Path
|
||||
for _, p := range c.Params {
|
||||
if p.Key == "fid" {
|
||||
url = strings.Replace(url, p.Value, ":fid", 1)
|
||||
}
|
||||
}
|
||||
return url
|
||||
}
|
||||
return url
|
||||
p.Use(r)
|
||||
}
|
||||
p.Use(r)
|
||||
|
||||
// File Handles
|
||||
fh := &fileHandle{fs: fs}
|
||||
@ -121,20 +145,29 @@ func main() {
|
||||
r.GET("/ws", handleWS)
|
||||
|
||||
// pprof
|
||||
ginpprof.Register(r)
|
||||
if os.Getenv(envDebug) != "" {
|
||||
ginpprof.Register(r)
|
||||
}
|
||||
|
||||
// gRPC server
|
||||
grpcServer := grpc.NewServer(
|
||||
grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor),
|
||||
grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor),
|
||||
)
|
||||
pb.RegisterExecutorServer(grpcServer, &execServer{fs: fs})
|
||||
grpc_prometheus.Register(grpcServer)
|
||||
grpc_prometheus.EnableHandlingTimeHistogram()
|
||||
var grpcServer *grpc.Server
|
||||
if enableGRPC {
|
||||
grpcServer = grpc.NewServer(
|
||||
grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor),
|
||||
grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor),
|
||||
)
|
||||
pb.RegisterExecutorServer(grpcServer, &execServer{fs: fs})
|
||||
grpc_prometheus.Register(grpcServer)
|
||||
grpc_prometheus.EnableHandlingTimeHistogram()
|
||||
|
||||
lis, err := net.Listen("tcp", *grpcAddr)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
lis, err := net.Listen("tcp", *grpcAddr)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
go func() {
|
||||
printLog("Starting grpc server at", *grpcAddr)
|
||||
printLog("GRPC serve", grpcServer.Serve(lis))
|
||||
}()
|
||||
}
|
||||
|
||||
srv := http.Server{
|
||||
@ -142,11 +175,6 @@ func main() {
|
||||
Handler: r,
|
||||
}
|
||||
|
||||
go func() {
|
||||
printLog("Starting grpc server at", *grpcAddr)
|
||||
printLog("GRPC serve", grpcServer.Serve(lis))
|
||||
}()
|
||||
|
||||
go func() {
|
||||
printLog("Starting http server at", *addr)
|
||||
printLog("Http serve", srv.ListenAndServe())
|
||||
@ -174,11 +202,13 @@ func main() {
|
||||
return nil
|
||||
})
|
||||
|
||||
eg.Go(func() error {
|
||||
grpcServer.GracefulStop()
|
||||
printLog("GRPC server shutdown")
|
||||
return nil
|
||||
})
|
||||
if grpcServer != nil {
|
||||
eg.Go(func() error {
|
||||
grpcServer.GracefulStop()
|
||||
printLog("GRPC server shutdown")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
go func() {
|
||||
printLog("Shutdown Finished", eg.Wait())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user