Skip to content

Server

Tổng quan

Fountain cung cấp các cài đặt server đa giao thức dưới libs/fnet. Mỗi server triển khai vòng đời AppInstance (Initialize / Serving / Destroy) và được kết nối vào framework thông qua fountain.New().WithAppInstances(...).

Các server hiện có:

  • fhttp — HTTP server xây dựng trên Fiber, với routing, middleware và tùy chọn mã hóa payload.
  • fgrpc — gRPC server với interceptor, metadata và tích hợp service discovery.
  • ftcp — TCP server dạng raw và có wrap.
  • fudp — UDP server.
  • fquic — QUIC server hỗ trợ stream và datagram.

Ví dụ

Một gRPC server instance:

go
/* !!
 * File: server.go
 * File Created: Monday, 6th June 2022 10:07:23 am
 * Author: Kim Ericko ([email protected])
 * -----
 * Last Modified: Monday, 6th June 2022 10:07:23 am
 * Modified By: Kim Ericko ([email protected])
 * -----
 * Copyright 2022 Soludian, soludian.com
 * All rights reserved.
 *
 * Licensed under the SOLUDIAN TECHNOLOGY SOLUTION CO., LTD Software License Agreement.
 * Unauthorized use, reproduction, or distribution is prohibited (the "License");
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * [email protected] / https://www.soludian.com/license
 *
 * 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.
 * -----
 *
 * HISTORY:
 *
 * Date      	By	Comments
 * ----------	---	---------------------------------------------------------
 */

package main

import (
	"context"
	"fmt"
	"log"
	"net"

	"gitlab.soludian.com/soludian/fountain/examples/grpc/chat"
	"google.golang.org/grpc"
)

func main() {
	fmt.Println("Go gRPC Beginners Tutorial!")

	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 9000))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}

	s := &ChatService{}

	grpcServer := grpc.NewServer()

	chat.RegisterChatServiceServer(grpcServer, s)

	if err := grpcServer.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %s", err)
	}
}

type ChatService struct {
	chat.UnimplementedChatServiceServer
}

func (s *ChatService) SayHello(ctx context.Context, req *chat.Message) (*chat.Message, error) {
	log.Printf("Receive message body from client: %s", req.Body)
	return &chat.Message{Body: "Hello From the Server!"}, nil
}

Một HTTP server với mã hóa payload:

go
/* !!
 * File: main.go
 * File Created: Friday, 28th October 2022 5:19:38 pm
 * Author: Kim Ericko ([email protected])
 * -----
 * Last Modified: Wednesday, 8th March 2023 4:40:18 pm
 * Modified By: Kim Ericko ([email protected])
 * -----
 * Copyright 2022 Soludian, soludian.com
 * All rights reserved.
 *
 * Licensed under the SOLUDIAN TECHNOLOGY SOLUTION CO., LTD Software License Agreement.
 * Unauthorized use, reproduction, or distribution is prohibited (the "License");
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * [email protected] / https://www.soludian.com/license
 *
 * 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.
 * -----
 *
 * HISTORY:
 *
 * Date      	By	Comments
 * ----------	---	---------------------------------------------------------
 */

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/gofiber/fiber/v3"
	"gitlab.soludian.com/soludian/fountain"
	"gitlab.soludian.com/soludian/fountain/biz/core"
	"gitlab.soludian.com/soludian/fountain/libs/base/lib_3rd"
	"gitlab.soludian.com/soludian/fountain/libs/crypto"
	"gitlab.soludian.com/soludian/fountain/libs/flog"
	"gitlab.soludian.com/soludian/fountain/libs/fnet/fhttp"
)

var logger = flog.NewFountainLoggerOnce()

type NoModule struct {
}

func (NoModule) Liveness() bool {
	return true
}

func (NoModule) Readiness() bool {
	return false
}

type APIServer struct {
	*fhttp.Server
}

func (s *APIServer) Initialize() error {
	s.Server = fhttp.WithConfigKey("server.fhttp").InstallFountainInstance()

	core.InstallCoreControllers()

	cr := crypto.InstallFountainInstances()
	log.Printf("Initializing: %+v", cr.GetFountainInstanceNames())

	s.Server.Get("/panic", func(ctx fiber.Ctx) error {
		err := fmt.Errorf("route panic")
		logger.WErr(err).Panicf(err.Error())
		return err
	})

	s.Server.Get("/200", func(ctx fiber.Ctx) error {
		return ctx.SendString("hello")
	})

	s.Server.Get("/hello", func(ctx fiber.Ctx) error {
		logger.Infof(ctx.Route().Path)
		return ctx.JSON("Hello client: " + ctx.Get("app"))
	})

	s.Server.Get("/encrypt", func(ctx fiber.Ctx) error {
		logger.Infof(ctx.Route().Path)
		return fhttp.WithContext(ctx).WithEncryption().WithStatus(200).WriteSuccess("Hello client: " + ctx.Get("app"))
	})

	s.Server.Get("/encrypt-cbc", func(ctx fiber.Ctx) error {
		data := make(map[string]any)
		data["server"] = "encrypt-cbc"
		data["time"] = time.Now().String()

		logger.Infof(ctx.Route().Path)
		return fhttp.WithContext(ctx).WithEncryptionFunc(crypto.GetFountainInstance("AES-CBC")).WithStatus(200).WriteSuccess(data)
	})

	s.Server.Get("/encrypt-ctr", func(ctx fiber.Ctx) error {
		data := make(map[string]any)
		data["server"] = "encrypt-ctr"
		data["time"] = time.Now().String()

		logger.Infof(ctx.Route().Path)
		return fhttp.WithContext(ctx).WithEncryptionFunc(crypto.GetFountainInstance("AES-CTR")).WithStatus(200).WriteSuccess(data)
	})

	s.Server.Get("/500", func(ctx fiber.Ctx) error {
		return ctx.Status(500).JSON("Hello client: " + ctx.Get("app"))
	})

	lib_3rd.RegisterHealthCheck("NoModule", &NoModule{})
	s.Server.InitHealthCheckPath("/")

	return nil
}

func main() {
	server := &APIServer{}
	fountain.WithAppInstances(server).Serving()
}

Xem thêm