You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by to...@apache.org on 2021/06/30 11:12:51 UTC
[apisix-dashboard] branch master updated: refactor: server manager
(#1956)
This is an automated email from the ASF dual-hosted git repository.
tokers pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new 3cfc327 refactor: server manager (#1956)
3cfc327 is described below
commit 3cfc32761122ad7f15f67edcfc251d0bed2e7538
Author: bzp2010 <bz...@apache.org>
AuthorDate: Wed Jun 30 19:12:42 2021 +0800
refactor: server manager (#1956)
---
api/cmd/root.go | 137 ++------------------
api/cmd/version.go | 11 +-
api/internal/core/server/http.go | 72 +++++++++++
api/internal/core/server/server.go | 144 +++++++++++++++++++++
.../version.go => internal/core/server/store.go} | 34 ++---
api/internal/utils/version.go | 14 +-
api/test/shell/cli_test.sh | 2 +-
7 files changed, 259 insertions(+), 155 deletions(-)
diff --git a/api/cmd/root.go b/api/cmd/root.go
index 05e16a2..b9d2aa4 100644
--- a/api/cmd/root.go
+++ b/api/cmd/root.go
@@ -17,28 +17,16 @@
package cmd
import (
- "context"
- "crypto/tls"
"fmt"
- "net"
- "net/http"
"os"
"os/signal"
- "strconv"
"syscall"
- "time"
- "github.com/shiningrush/droplet"
"github.com/spf13/cobra"
- "github.com/apisix/manager-api/internal"
"github.com/apisix/manager-api/internal/conf"
- "github.com/apisix/manager-api/internal/core/storage"
- "github.com/apisix/manager-api/internal/core/store"
- "github.com/apisix/manager-api/internal/filter"
- "github.com/apisix/manager-api/internal/handler"
+ "github.com/apisix/manager-api/internal/core/server"
"github.com/apisix/manager-api/internal/log"
- "github.com/apisix/manager-api/internal/utils"
)
var (
@@ -88,126 +76,29 @@ func manageAPI() error {
conf.InitConf()
log.InitLogger()
- if err := utils.WritePID(conf.PIDPath, forceStart); err != nil {
- log.Errorf("failed to write pid: %s", err)
+ s, err := server.NewServer(&server.Options{
+ ForceStart: forceStart,
+ })
+ if err != nil {
return err
}
- utils.AppendToClosers(func() error {
- if err := os.Remove(conf.PIDPath); err != nil {
- log.Errorf("failed to remove pid path: %s", err)
- return err
- }
- return nil
- })
+
+ // start Manager API server
+ errSig := make(chan error, 5)
+ s.Start(errSig)
// Signal received to the process externally.
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
- defer func() {
- utils.CloseAll()
- signal.Stop(quit)
- }()
-
- droplet.Option.Orchestrator = func(mws []droplet.Middleware) []droplet.Middleware {
- var newMws []droplet.Middleware
- // default middleware order: resp_reshape, auto_input, traffic_log
- // We should put err_transform at second to catch all error
- newMws = append(newMws, mws[0], &handler.ErrorTransformMiddleware{}, &filter.AuthenticationMiddleware{})
- newMws = append(newMws, mws[1:]...)
- return newMws
- }
-
- if err := storage.InitETCDClient(conf.ETCDConfig); err != nil {
- log.Errorf("init etcd client fail: %w", err)
- return err
- }
- if err := store.InitStores(); err != nil {
- log.Errorf("init stores fail: %w", err)
- return err
- }
-
- var server, serverSSL *http.Server
- // For internal error handling across multiple goroutines.
- errsig := make(chan error, 1)
-
- // routes
- r := internal.SetUpRouter()
- addr := net.JoinHostPort(conf.ServerHost, strconv.Itoa(conf.ServerPort))
- server = &http.Server{
- Addr: addr,
- Handler: r,
- ReadTimeout: time.Duration(1000) * time.Millisecond,
- WriteTimeout: time.Duration(5000) * time.Millisecond,
- }
-
- log.Infof("The Manager API is listening on %s", addr)
-
- go func() {
- if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
- log.Errorf("listen and serv fail: %s", err)
- errsig <- err
- }
- }()
-
- // HTTPS
- if conf.SSLCert != "" && conf.SSLKey != "" {
- addrSSL := net.JoinHostPort(conf.ServerHost, strconv.Itoa(conf.SSLPort))
- serverSSL = &http.Server{
- Addr: addrSSL,
- Handler: r,
- ReadTimeout: time.Duration(1000) * time.Millisecond,
- WriteTimeout: time.Duration(5000) * time.Millisecond,
- TLSConfig: &tls.Config{
- // Causes servers to use Go's default ciphersuite preferences,
- // which are tuned to avoid attacks. Does nothing on clients.
- PreferServerCipherSuites: true,
- },
- }
- go func() {
- err := serverSSL.ListenAndServeTLS(conf.SSLCert, conf.SSLKey)
- if err != nil && err != http.ErrServerClosed {
- log.Errorf("listen and serve for HTTPS failed: %s", err)
- errsig <- err
- }
- }()
- }
-
- printInfo()
-
select {
- case err := <-errsig:
- return err
-
case sig := <-quit:
log.Infof("The Manager API server receive %s and start shutting down", sig.String())
-
- shutdownServer(server)
- shutdownServer(serverSSL)
+ s.Stop()
log.Infof("The Manager API server exited")
- return nil
- }
-}
-
-func shutdownServer(server *http.Server) {
- if server != nil {
- ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
- defer cancel()
-
- if err := server.Shutdown(ctx); err != nil {
- log.Errorf("Shutting down server error: %s", err)
- }
- }
-}
-
-func printInfo() {
- fmt.Fprint(os.Stdout, "The manager-api is running successfully!\n\n")
- printVersion()
- fmt.Fprintf(os.Stdout, "%-8s: %s:%d\n", "Listen", conf.ServerHost, conf.ServerPort)
- if conf.SSLCert != "" && conf.SSLKey != "" {
- fmt.Fprintf(os.Stdout, "%-8s: %s:%d\n", "HTTPS Listen", conf.SSLHost, conf.SSLPort)
+ case err := <-errSig:
+ log.Errorf("The Manager API server start failed: %s", err.Error())
+ return err
}
- fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Loglevel", conf.ErrorLogLevel)
- fmt.Fprintf(os.Stdout, "%-8s: %s\n", "ErrorLogFile", conf.ErrorLogPath)
- fmt.Fprintf(os.Stdout, "%-8s: %s\n\n", "AccessLogFile", conf.AccessLogPath)
+ return nil
}
diff --git a/api/cmd/version.go b/api/cmd/version.go
index df7abc1..c064502 100644
--- a/api/cmd/version.go
+++ b/api/cmd/version.go
@@ -17,9 +17,6 @@
package cmd
import (
- "fmt"
- "os"
-
"github.com/spf13/cobra"
"github.com/apisix/manager-api/internal/utils"
@@ -30,13 +27,7 @@ func newVersionCommand() *cobra.Command {
Use: "version",
Short: "show manager-api version",
Run: func(cmd *cobra.Command, args []string) {
- printVersion()
+ utils.PrintVersion()
},
}
}
-
-func printVersion() {
- gitHash, version := utils.GetHashAndVersion()
- fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Version", version)
- fmt.Fprintf(os.Stdout, "%-8s: %s\n", "GitHash", gitHash)
-}
diff --git a/api/internal/core/server/http.go b/api/internal/core/server/http.go
new file mode 100644
index 0000000..53a4216
--- /dev/null
+++ b/api/internal/core/server/http.go
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package server
+
+import (
+ "crypto/tls"
+ "net"
+ "net/http"
+ "strconv"
+ "time"
+
+ "github.com/shiningrush/droplet"
+
+ "github.com/apisix/manager-api/internal"
+ "github.com/apisix/manager-api/internal/conf"
+ "github.com/apisix/manager-api/internal/filter"
+ "github.com/apisix/manager-api/internal/handler"
+)
+
+func (s *server) setupAPI() {
+ // orchestrator
+ droplet.Option.Orchestrator = func(mws []droplet.Middleware) []droplet.Middleware {
+ var newMws []droplet.Middleware
+ // default middleware order: resp_reshape, auto_input, traffic_log
+ // We should put err_transform at second to catch all error
+ newMws = append(newMws, mws[0], &handler.ErrorTransformMiddleware{}, &filter.AuthenticationMiddleware{})
+ newMws = append(newMws, mws[1:]...)
+ return newMws
+ }
+
+ // routes
+ r := internal.SetUpRouter()
+
+ // HTTP
+ addr := net.JoinHostPort(conf.ServerHost, strconv.Itoa(conf.ServerPort))
+ s.server = &http.Server{
+ Addr: addr,
+ Handler: r,
+ ReadTimeout: time.Duration(1000) * time.Millisecond,
+ WriteTimeout: time.Duration(5000) * time.Millisecond,
+ }
+
+ // HTTPS
+ if conf.SSLCert != "" && conf.SSLKey != "" {
+ addrSSL := net.JoinHostPort(conf.SSLHost, strconv.Itoa(conf.SSLPort))
+ s.serverSSL = &http.Server{
+ Addr: addrSSL,
+ Handler: r,
+ ReadTimeout: time.Duration(1000) * time.Millisecond,
+ WriteTimeout: time.Duration(5000) * time.Millisecond,
+ TLSConfig: &tls.Config{
+ // Causes servers to use Go's default ciphersuite preferences,
+ // which are tuned to avoid attacks. Does nothing on clients.
+ PreferServerCipherSuites: true,
+ },
+ }
+ }
+}
diff --git a/api/internal/core/server/server.go b/api/internal/core/server/server.go
new file mode 100644
index 0000000..07c4b1c
--- /dev/null
+++ b/api/internal/core/server/server.go
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package server
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "os"
+ "time"
+
+ "github.com/apisix/manager-api/internal/conf"
+ "github.com/apisix/manager-api/internal/log"
+ "github.com/apisix/manager-api/internal/utils"
+)
+
+// server is the manager of Manager API, which is responsible for managing the life cycle of Manager API, including initialization, start, stop and so on
+type server struct {
+ server *http.Server
+ serverSSL *http.Server
+ options *Options
+}
+
+type Options struct {
+ ForceStart bool // force start new instance
+}
+
+// NewServer Create a server manager
+func NewServer(options *Options) (*server, error) {
+ return &server{options: options}, nil
+}
+
+func (s *server) Start(errSig chan error) {
+ // initialize server
+ err := s.init()
+ if err != nil {
+ errSig <- err
+ return
+ }
+
+ // write daemon pid file
+ err = s.writePID()
+ if err != nil {
+ errSig <- err
+ return
+ }
+
+ // print server info to stdout
+ s.printInfo()
+
+ // start HTTP server
+ log.Infof("The Manager API is listening on %s", s.server.Addr)
+ go func() {
+ err := s.server.ListenAndServe()
+ if err != nil && err != http.ErrServerClosed {
+ log.Errorf("listen and serv fail: %s", err)
+ errSig <- err
+ }
+ }()
+
+ // start HTTPs server
+ if conf.SSLCert != "" && conf.SSLKey != "" {
+ go func() {
+ err := s.serverSSL.ListenAndServeTLS(conf.SSLCert, conf.SSLKey)
+ if err != nil && err != http.ErrServerClosed {
+ log.Errorf("listen and serve for HTTPS failed: %s", err)
+ errSig <- err
+ }
+ }()
+ }
+}
+
+func (s *server) Stop() {
+ utils.CloseAll()
+
+ s.shutdownServer(s.server)
+ s.shutdownServer(s.serverSSL)
+}
+
+func (s *server) init() error {
+ log.Info("Initialize Manager API store")
+ err := s.setupStore()
+ if err != nil {
+ return err
+ }
+
+ log.Info("Initialize Manager API server")
+ s.setupAPI()
+
+ return nil
+}
+
+func (s *server) writePID() error {
+ if err := utils.WritePID(conf.PIDPath, s.options.ForceStart); err != nil {
+ log.Errorf("failed to write pid: %s", err)
+ return err
+ }
+ utils.AppendToClosers(func() error {
+ if err := os.Remove(conf.PIDPath); err != nil {
+ log.Errorf("failed to remove pid path: %s", err)
+ return err
+ }
+ return nil
+ })
+
+ return nil
+}
+
+func (s *server) shutdownServer(server *http.Server) {
+ if server != nil {
+ ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
+ defer cancel()
+
+ if err := server.Shutdown(ctx); err != nil {
+ log.Errorf("Shutting down server error: %s", err)
+ }
+ }
+}
+
+func (s *server) printInfo() {
+ fmt.Fprint(os.Stdout, "The manager-api is running successfully!\n\n")
+ utils.PrintVersion()
+ fmt.Fprintf(os.Stdout, "%-8s: %s:%d\n", "Listen", conf.ServerHost, conf.ServerPort)
+ if conf.SSLCert != "" && conf.SSLKey != "" {
+ fmt.Fprintf(os.Stdout, "%-8s: %s:%d\n", "HTTPS Listen", conf.SSLHost, conf.SSLPort)
+ }
+ fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Loglevel", conf.ErrorLogLevel)
+ fmt.Fprintf(os.Stdout, "%-8s: %s\n", "ErrorLogFile", conf.ErrorLogPath)
+ fmt.Fprintf(os.Stdout, "%-8s: %s\n\n", "AccessLogFile", conf.AccessLogPath)
+}
diff --git a/api/cmd/version.go b/api/internal/core/server/store.go
similarity index 62%
copy from api/cmd/version.go
copy to api/internal/core/server/store.go
index df7abc1..6130a19 100644
--- a/api/cmd/version.go
+++ b/api/internal/core/server/store.go
@@ -14,29 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package cmd
+package server
import (
- "fmt"
- "os"
-
- "github.com/spf13/cobra"
-
- "github.com/apisix/manager-api/internal/utils"
+ "github.com/apisix/manager-api/internal/conf"
+ "github.com/apisix/manager-api/internal/core/storage"
+ "github.com/apisix/manager-api/internal/core/store"
+ "github.com/apisix/manager-api/internal/log"
)
-func newVersionCommand() *cobra.Command {
- return &cobra.Command{
- Use: "version",
- Short: "show manager-api version",
- Run: func(cmd *cobra.Command, args []string) {
- printVersion()
- },
+func (s *server) setupStore() error {
+ if err := storage.InitETCDClient(conf.ETCDConfig); err != nil {
+ log.Errorf("init etcd client fail: %w", err)
+ return err
}
-}
-
-func printVersion() {
- gitHash, version := utils.GetHashAndVersion()
- fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Version", version)
- fmt.Fprintf(os.Stdout, "%-8s: %s\n", "GitHash", gitHash)
+ if err := store.InitStores(); err != nil {
+ log.Errorf("init stores fail: %w", err)
+ return err
+ }
+ return nil
}
diff --git a/api/internal/utils/version.go b/api/internal/utils/version.go
index d4bec4a..c061156 100644
--- a/api/internal/utils/version.go
+++ b/api/internal/utils/version.go
@@ -16,12 +16,24 @@
*/
package utils
+import (
+ "fmt"
+ "os"
+)
+
var (
gitHash string
version string
)
-// get the hash and version
+// GetHashAndVersion get the hash and version
func GetHashAndVersion() (string, string) {
return gitHash, version
}
+
+// PrintVersion print version and git hash to stdout
+func PrintVersion() {
+ gitHash, version := GetHashAndVersion()
+ fmt.Fprintf(os.Stdout, "%-8s: %s\n", "Version", version)
+ fmt.Fprintf(os.Stdout, "%-8s: %s\n", "GitHash", gitHash)
+}
diff --git a/api/test/shell/cli_test.sh b/api/test/shell/cli_test.sh
index 325b0a4..1bbb66f 100755
--- a/api/test/shell/cli_test.sh
+++ b/api/test/shell/cli_test.sh
@@ -223,7 +223,7 @@ sleep 6
cat ${logfile}
-if [[ `grep -c "cmd/root.go" ${logfile}` -ne '1' ]]; then
+if [[ `grep -c "server/store.go" ${logfile}` -ne '1' ]]; then
echo "failed: failed to write the correct caller"
exit 1
fi