Skip to content

Commit

Permalink
feat: add README.md and fix some problems (#20)
Browse files Browse the repository at this point in the history
* feat: add README.md and fix some problems

* fix: fix the spelling error

* modify readme.md

* add: doc/deploy.md

* Update Makefile

* Update deploy.md

* Update README.md

---------

Co-authored-by: ozlinex <[email protected]>
  • Loading branch information
SchwarzSail and ozline authored Oct 9, 2024
1 parent 74afdaf commit 5a31317
Show file tree
Hide file tree
Showing 11 changed files with 255 additions and 29 deletions.
39 changes: 24 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ OUTPUT_PATH = $(DIR)/output
SERVICES := api user classroom
service = $(word 1, $@)

PERFIX = "[Makefile]"
PREFIX = "[Makefile]"

.PHONY: help
help:
@echo "Available targets:"
@echo " {service name} : Build a specific service (e.g., make api). use BUILD_ONLY=1 to avoid auto bootstrap."
@echo " Available service list: [${SERVICES}]"
@echo " local : Build all services."
@echo " env-up : Start the docker-compose environment."
@echo " env-down : Stop the docker-compose environment."
@echo " kitex-gen-% : Generate Kitex service code for a specific service (e.g., make kitex-gen-user)."
Expand Down Expand Up @@ -78,7 +79,9 @@ kitex-update-%:
# TODO: 这个和 Kitex 的区别在于这个 update 实际上做了 gen 的工作,就直接这么用了
.PHONY: hertz-gen-api
hertz-gen-api:
hz update -idl ./idl/api.thrift
hz model -idl ./idl/api.thrift --out_dir ./cmd/api && \
hz update -idl ./idl/api.thrift --out_dir ./cmd/api --use ${MODULE}/cmd/api/biz/model && \
swag init --dir ./cmd/api --output ./docs/swagger --outputTypes "yaml"

# 单元测试
.PHONY: test
Expand All @@ -91,43 +94,50 @@ test:
.PHONY: $(SERVICES)
$(SERVICES):
@if [ -z "$(TMUX_EXISTS)" ]; then \
echo "$(PERFIX) tmux is not installed. Please install tmux first."; \
echo "$(PREFIX) tmux is not installed. Please install tmux first."; \
exit 1; \
fi
@if [ -z "$$TMUX" ]; then \
echo "$(PERFIX) you are not in tmux, press ENTER to start tmux environment."; \
echo "$(PREFIX) you are not in tmux, press ENTER to start tmux environment."; \
read -r; \
if tmux has-session -t fzuhelp 2>/dev/null; then \
echo "$(PERFIX) Tmux session 'fzuhelp' already exists. Attaching to session and running command."; \
echo "$(PREFIX) Tmux session 'fzuhelp' already exists. Attaching to session and running command."; \
tmux attach-session -t fzuhelp; \
tmux send-keys -t fzuhelp "make $(service)" C-m; \
else \
echo "$(PERFIX) No tmux session found. Creating a new session."; \
echo "$(PREFIX) No tmux session found. Creating a new session."; \
tmux new-session -s fzuhelp "make $(service); $$SHELL"; \
fi; \
else \
echo "$(PERFIX) Build $(service) target..."; \
echo "$(PREFIX) Build $(service) target..."; \
mkdir -p output; \
cd $(CMD)/$(service) && sh build.sh; \
cd $(CMD)/$(service)/output && cp -r . $(OUTPUT_PATH)/$(service); \
echo "$(PERFIX) Build $(service) target completed"; \
echo "$(PREFIX) Build $(service) target completed"; \
fi
ifndef BUILD_ONLY
@echo "$(PERFIX) Automatic run server"
@echo "$(PREFIX) Automatic run server"
@if tmux list-windows -F '#{window_name}' | grep -q "^fzuhelper-$(service)$$"; then \
echo "$(PERFIX) Window 'fzuhelper-$(service)' already exists. Reusing the window."; \
echo "$(PREFIX) Window 'fzuhelper-$(service)' already exists. Reusing the window."; \
tmux select-window -t "fzuhelper-$(service)"; \
else \
echo "$(PERFIX) Window 'fzuhelper-$(service)' does not exist. Creating a new window."; \
echo "$(PREFIX) Window 'fzuhelper-$(service)' does not exist. Creating a new window."; \
tmux new-window -n "fzuhelper-$(service)"; \
tmux split-window -h ; \
tmux select-layout -t "fzuhelper-$(service)" even-horizontal; \
fi
@echo "$(PERFIX) Running $(service) service in tmux..."
@echo "$(PREFIX) Running $(service) service in tmux..."
@tmux send-keys -t fzuhelper-$(service).0 'sh ./hack/entrypoint.sh $(service)' C-m
@tmux select-pane -t fzuhelper-$(service).1
endif

#在本地一键启动所有的服务
.PHONY: local
local:
@ for service in $(SERVICES); do \
make $$service; \
done

# 推送到镜像服务中,需要提前 docker login,否则会推送失败
# 不设置同时推送全部服务,这是一个非常危险的操作
.PHONY: push-%
Expand All @@ -137,8 +147,8 @@ push-%:
echo "Confirmation failed. Expected '$*', but got '$$CONFIRM_SERVICE'."; \
exit 1; \
fi; \
@if echo "$(SERVICES)" | grep -wq "$*"; then \
if [ "$(ARCH)" = "x86_64" ] || [ "$(ARCH)" = "amd64" ] ; then \
if echo "$(SERVICES)" | grep -wq "$*"; then \
if [ "$(ARCH)" = "x86_64" ] || [ "$(ARCH)" = "amd64" ]; then \
echo "Building and pushing $* for amd64 architecture..."; \
docker build --build-arg SERVICE=$* -t $(REMOTE_REPOSITORY):$* -f docker/Dockerfile .; \
docker push $(REMOTE_REPOSITORY):$*; \
Expand All @@ -150,7 +160,6 @@ push-%:
echo "Service '$*' is not a valid service. Available: [$(SERVICES)]"; \
exit 1; \
fi

## --------------------------------------
## 清理与校验
## --------------------------------------
Expand Down
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<div align="center">
<img src="/docs/img/appicon.png" width="80" style="vertical-align: middle; margin-right: 26px; margin-top: 5px;">
<h1 style="display: inline-block; vertical-align: middle; font-size: 2em;">fzuhelper-server</h1>
<h1 style="display: inline-block; vertical-align: middle;">fzuhelper-server</h1>
</div>

---

## Overview

fzuhelper-server is a distributed architecture-based server application for fzuhelper, which has been in use since 2024, serving **over 23,000 students** from Fuzhou University everyday ([Data source and introduction to fzuhelper](https://west2-online.feishu.cn/wiki/RG3UwWGqPig8lHk0mYsccKWRnrd)).
Expand All @@ -31,4 +28,4 @@ This project focuses on business implementation. To see how we interface with th
If you are interested in joining the maintenance of fzuhelper-server, please contact us on our [official website](https://site.west2.online)

## License
`fzuhelper-server` is under the Apache 2.0 license. See the LICENSE file for details.
`fzuhelper-server` is under the Apache 2.0 license. See the LICENSE file for details.
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func Init(path string, service string) {
if etcdAddr == "" {
logger.Fatalf("config.Init: etcd addr is empty")
}

logger.Infof("config.Init: etcd addr: %v", etcdAddr)
Etcd = &etcd{Addr: etcdAddr}

// use etcd for config save
Expand Down
7 changes: 2 additions & 5 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ FROM golang:1.23 AS builder
ARG SERVICE

# 设置环境变量
ENV TZ Asia=Shanghai
ENV TZ=Asia/Shanghai
ENV GO111MODULE=on
ENV CGO_ENABLED=0
ENV GOPROXY=https://goproxy.cn,direct
Expand All @@ -14,7 +14,6 @@ ENV GOARCH=amd64
RUN mkdir -p /app
RUN mkdir -p /app/output


WORKDIR /app

# 复制所有文件到工作目录
Expand All @@ -23,8 +22,6 @@ COPY . .
# 下载依赖
RUN go mod tidy

#RUN skywalking-go-agent -inject ./

# 编译应用程序
RUN cd ./cmd/${SERVICE} && sh ./build.sh

Expand All @@ -33,7 +30,7 @@ FROM alpine

ARG SERVICE

ENV TZ Asia=Shanghai
ENV TZ=Asia/Shanghai
# 安装必要的依赖
RUN apk --no-cache add ca-certificates

Expand Down
Empty file modified docker/script/etcd-monitor.sh
100644 → 100755
Empty file.
42 changes: 42 additions & 0 deletions docs/deploy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Deploy
target 请通过`make help`来显示可用的服务列表,后续的target指代我们的服务,例如api
## 本地部署
修改`./config/config.yaml`的配置,将数据库等配置的ip修改为localhost(如果没有请新增这个文件)
### 启动环境
#### 清理本地环境(optional)
```shell
make clean-all
```
#### 启动环境
```shell
make env-up
```
### 启动服务
#### 启动所有服务
> 可以使用"ctrl+b s"来切换终端
```shell
make local
```
#### 启动特定服务
```shell
make target #e.g. make api
```
使用make help获取更多信息
## 云服务部署
> 请保证已经使用docker login
### 构建镜像
```shell
make push-target
```
### 云服务器端

#### 环境搭建
```shell
docker compose up -d
```
#### 部署服务
```shell
sh image-refresh.sh target #更新镜像
sh docker-run.sh target #运行容器
```
101 changes: 101 additions & 0 deletions hack/docker-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Copyright 2024 The west2-online Authors.
#
# Licensed 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.

#!/bin/bash

# 这个脚本用于管理一组服务的Docker容器。
# 它允许使用单个Docker镜像启动特定服务或所有服务。

CONFIG_PATH="../config/config.yaml" # related to project folder

get_port() {
local server_name="$1"

port=$(awk -v name="$server_name" '
$0 ~ "name: " name {found=1}
found && $0 ~ "port:" {print $2; exit}
$0 ~ "services:" {found=0}
' "$CONFIG_PATH")


echo "$port"
}

# Docker容器的镜像名称
IMAGE_NAME="registry.cn-hangzhou.aliyuncs.com/west2-online/fzuhelper-server"

# 要启动的服务,默认为 "all" 如果没有提供参数
SERVICE_TO_START=${1:-all}

# 脚本所在的目录
DIR=$(cd "$(dirname "$0")" && pwd)

# 可用服务的列表。在真实场景中,这应该是服务名称的数组。
# 例如:SERVICES=("service1" "service2" "service3")
SERVICES=("api classroom user")
# 1. 编译镜像时将多个服务打包为单一镜像(当然不建议这么做,不过镜像小的且不需要频繁更新这么做很方便)
# 2. 启动时根据SERVICE_TO_START在SERVICES中查找对应服务名
# 3. 如果查找的到,则启动容器,查找不到则抛出错误

# 删除Docker容器的函数
remove_container() {
local container_name="$1"
local container_status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null)
echo "remove container $container_name"

if [ "$container_status" == "running" ]; then
docker stop "$container_name"
elif [ "$container_status" == "paused" ]; then
docker unpause "$container_name"
docker stop "$container_name"
fi

if [ -n "$container_status" ]; then
docker rm "$container_name"
fi
}

# 启动新Docker容器的函数
start_container() {
local service_name="$1"
local server_port=$(get_port "$service_name")
local image="$IMAGE_NAME:$service_name"

echo "port is $server_port"
echo "start container $service_name"
docker run -d --name $service_name \
--network fzu-helper \
-p $server_port:$server_port \
--restart always \
$image
}

# 停止当前运行的容器,匹配名称模式
containers_to_stop=$(docker ps -aq | grep -v "fzu-helper")
if [ "$SERVICE_TO_START" == "all" ]; then
for container_id in $containers_to_stop; do
remove_container "$container_id"
done
else
remove_container "$SERVICE_TO_START"
fi

# 启动新容器
if [ "$SERVICE_TO_START" == "all" ]; then
for service in "${SERVICES[@]}"; do
start_container "$service"
done
else
start_container "$SERVICE_TO_START"
fi
79 changes: 79 additions & 0 deletions hack/image-refresh.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Copyright 2024 The west2-online Authors.
#
# Licensed 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.

#!/bin/bash
# 使用脚本前请保证docker login

# 镜像名称和标签,请根据实际情况进行替换
IMAGE_NAME="registry.cn-hangzhou.aliyuncs.com/west2-online/fzuhelper-server"
IMAGE_TAG="$1"
FULL_IMAGE_NAME="${IMAGE_NAME}:${IMAGE_TAG}"

# 检查jq是否安装
if ! type jq > /dev/null; then
echo "错误:需要jq工具来解析JSON。请安装jq。 e.g: yum install jq"
exit 1
fi

# 获取远程镜像的摘要信息
get_remote_image_digest() {
docker manifest inspect "$FULL_IMAGE_NAME" 2>/dev/null | jq -r '.config.digest'
}

# 获取本地镜像的摘要信息
get_local_image_digest() {
docker image inspect --format='{{.Id}}' "$FULL_IMAGE_NAME" 2>/dev/null
}

# 拉取最新的Docker镜像
pull_new_image() {
echo "正在拉取最新镜像: $FULL_IMAGE_NAME..."
if docker pull "$FULL_IMAGE_NAME"; then
echo "镜像更新成功。"
else
echo "错误:无法拉取镜像。"
exit 1
fi
}

# 主流程
main() {
local remote_digest=$(get_remote_image_digest)
if [ -z "$remote_digest" ]; then
echo "错误:无法获取远程镜像的摘要信息。"
exit 1
fi

local local_digest=$(get_local_image_digest)
if [ -z "$local_digest" ]; then
echo "警告:未找到本地镜像 $FULL_IMAGE_NAME 或无法获取摘要。"
echo "尝试直接拉取远程镜像..."
pull_new_image
exit 0
fi

echo "本地镜像摘要: $local_digest"
echo "远程镜像摘要: $remote_digest"

if [ "$local_digest" != "$remote_digest" ]; then
echo "本地镜像与远程镜像不一致,需要更新。"
pull_new_image
else
echo "本地镜像已是最新。"
fi
}

# 执行主流程
main

File renamed without changes.
Loading

0 comments on commit 5a31317

Please sign in to comment.