Exemple #1
0
func (b *Broker) HandleTaskResult(uuid string) (*task.Reply, error) {
	if len(uuid) == 0 {
		return nil, errors.ErrInvalidArgument
	}
	key := fmt.Sprintf("r_%s", uuid)
	result, err := b.redisClient.HMGet(key,
		"is_success",
		"result",
	).Result()
	if err != nil {
		golog.Error("Broker", "HandleFailTask", err.Error(), 0, "key", key)
		return nil, err
	}

	//key不存在
	if result[0] == nil {
		return nil, errors.ErrResultNotExist
	}
	isSuccess, err := strconv.Atoi(result[0].(string))
	if err != nil {
		return nil, err
	}
	ret := result[1].(string)
	return &task.Reply{
		IsResultExist: 1,
		IsSuccess:     isSuccess,
		Result:        ret,
	}, nil
}
Exemple #2
0
func (b *Broker) resetTaskRequest(args []interface{}) error {
	var err error
	if len(args) == 0 || len(args) != config.TaskRequestItemCount {
		return errors.ErrInvalidArgument
	}
	request := new(task.TaskRequest)
	request.Uuid = args[0].(string)
	request.BinName = args[1].(string)
	request.Args = args[2].(string)
	request.StartTime, err = strconv.ParseInt(args[3].(string), 10, 64)
	if err != nil {
		return err
	}
	request.TimeInterval = args[4].(string)
	request.Index, err = strconv.Atoi(args[5].(string))
	if err != nil {
		return err
	}
	vec := strings.Split(request.TimeInterval, " ")
	request.Index++
	if request.Index < len(vec) {
		timeLater, err := strconv.Atoi(vec[request.Index])
		if err != nil {
			return err
		}
		afterTime := time.Second * time.Duration(timeLater)
		b.timer.NewTimer(afterTime, b.AddRequestToRedis, request)
	} else {
		golog.Error("Broker", "HandleFailTask", "retry max time", 0,
			"key", fmt.Sprintf("t_%s", request.Uuid))
		return errors.ErrTryMaxTimes
	}
	return nil
}
Exemple #3
0
func NewWorker(cfg *config.WorkerConfig) (*Worker, error) {
	var err error
	w := new(Worker)
	w.cfg = cfg

	vec := strings.SplitN(cfg.RedisAddr, "/", 2)
	if len(vec) == 2 {
		w.redisAddr = vec[0]
		w.redisDB, err = strconv.Atoi(vec[1])
		if err != nil {
			return nil, err
		}
	} else {
		w.redisAddr = vec[0]
		w.redisDB = config.DefaultRedisDB
	}

	w.redisClient = redis.NewClient(
		&redis.Options{
			Addr:     w.redisAddr,
			Password: "", // no password set
			DB:       int64(w.redisDB),
		},
	)
	_, err = w.redisClient.Ping().Result()
	if err != nil {
		golog.Error("worker", "NewWorker", "ping redis fail", 0, "err", err.Error())
		return nil, err
	}

	return w, nil
}
Exemple #4
0
func (w *Worker) DoScriptTaskRequest(req *task.TaskRequest) (string, error) {
	var output string
	var err error
	var maxRunTime int64

	binPath := path.Clean(w.cfg.BinPath + "/" + req.BinName)
	_, err = os.Stat(binPath)
	if err != nil && os.IsNotExist(err) {
		golog.Error("worker", "DoScrpitTaskRequest", "File not exist", 0,
			"key", fmt.Sprintf("t_%s", req.Uuid),
			"bin_path", binPath,
		)
		return "", errors.ErrFileNotExist
	}
	if req.MaxRunTime == 0 {
		maxRunTime = w.cfg.TaskRunTime
	} else {
		maxRunTime = req.MaxRunTime
	}
	if len(req.Args) == 0 {
		output, err = w.ExecBin(binPath, nil, maxRunTime)
	} else {
		argsVec := strings.Split(req.Args, " ")
		output, err = w.ExecBin(binPath, argsVec, maxRunTime)
	}
	return output, err
}
Exemple #5
0
func (w *Worker) CmdRunWithTimeout(cmd *exec.Cmd, timeout time.Duration) (error, bool) {
	done := make(chan error)
	go func() {
		done <- cmd.Wait()
	}()

	var err error
	select {
	case <-time.After(timeout):
		// timeout
		if err = cmd.Process.Kill(); err != nil {
			golog.Error("worker", "CmdRunTimeout", "kill error", 0,
				"path", cmd.Path,
				"error", err.Error(),
			)
		}
		golog.Info("worker", "CmdRunWithTimeout", "kill process", 0,
			"path", cmd.Path,
			"error", errors.ErrExecTimeout.Error(),
		)
		go func() {
			<-done // allow goroutine to exit
		}()
		return errors.ErrExecTimeout, true
	case err = <-done:
		return err, false
	}
}
Exemple #6
0
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()

	if len(*configFile) == 0 {
		fmt.Println("must use a config file")
		return
	}

	cfg, err := config.ParseWorkerConfigFile(*configFile)
	if err != nil {
		fmt.Printf("parse config file error:%v\n", err.Error())
		return
	}

	//when the log file size greater than 1GB, kingtask will generate a new file
	if len(cfg.LogPath) != 0 {
		sysFilePath := path.Join(cfg.LogPath, sysLogName)
		sysFile, err := golog.NewRotatingFileHandler(sysFilePath, MaxLogSize, 1)
		if err != nil {
			fmt.Printf("new log file error:%v\n", err.Error())
			return
		}
		golog.GlobalLogger = golog.New(sysFile, golog.Lfile|golog.Ltime|golog.Llevel)
	}

	if *logLevel != "" {
		setLogLevel(*logLevel)
	} else {
		setLogLevel(cfg.LogLevel)
	}

	var w *worker.Worker
	w, err = worker.NewWorker(cfg)
	if err != nil {
		golog.Error("main", "main", err.Error(), 0)
		golog.GlobalLogger.Close()
		w.Close()
		return
	}

	sc := make(chan os.Signal, 1)
	signal.Notify(sc,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	go func() {
		sig := <-sc
		golog.Info("main", "main", "Got signal", 0, "signal", sig)
		golog.GlobalLogger.Close()
		w.Close()
	}()
	golog.Info("main", "main", "Worker start!", 0)
	w.Run()
}
Exemple #7
0
func (b *Broker) handleConn(c net.Conn) error {
	defer func() {
		r := recover()
		if err, ok := r.(error); ok {
			const size = 4096
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]

			golog.Error("Broker", "handleConn",
				err.Error(), 0,
				"stack", string(buf))
		}
		c.Close()
	}()

	var CloseConn bool
	reader := bufio.NewReaderSize(c, 1024)
	for {
		msgType := []byte{0}
		if _, err := io.ReadFull(reader, msgType); err != nil {
			return errors.ErrBadConn
		}

		switch msgType[0] {
		case config.TypeRequestTask:
			b.HandleRequest(reader, c)
		case config.TypeGetTaskResult:
			b.HandleTaskResult(reader, c)
		case config.TypeCloseConn:
			CloseConn = true
		default:
			golog.Error("Broker", "handleConn", "msgType error", 0, "msg_type", msgType[0])
			CloseConn = true
		}
		if CloseConn {
			break
		}
	}
	return nil
}
Exemple #8
0
//处理失败的任务
func (b *Broker) HandleFailTask() error {
	var uuid string
	var err error
	for b.running {
		uuid, err = b.redisClient.SPop(config.FailResultUuidSet).Result()
		//没有结果,直接返回
		if err == redis.Nil {
			time.Sleep(time.Second)
			continue
		}
		if err != nil {
			golog.Error("Broker", "HandleFailTask", "spop error", 0, "error", err.Error())
			continue
		}

		key := fmt.Sprintf("r_%s", uuid)
		timeInterval, err := b.redisClient.HGet(key, "time_interval").Result()
		if err != nil {
			golog.Error("Broker", "HandleFailTask", err.Error(), 0, "key", key)
			continue
		}
		//没有超时重试机制
		if len(timeInterval) == 0 {
			b.SetFailTaskCount(fmt.Sprintf("t_%s", uuid))
			continue
		}
		//获取结果中所有值,改为逐个获取
		results, err := b.redisClient.HMGet(key,
			"uuid",
			"bin_name",
			"args",
			"start_time",
			"time_interval",
			"index",
			"max_run_time",
			"task_type",
		).Result()
		if err != nil {
			golog.Error("Broker", "HandleFailTask", err.Error(), 0, "key", key)
			continue
		}
		//key已经过期
		if results[0] == nil {
			golog.Error("Broker", "HandleFailTask", "result expired", 0, "key", key)
			continue
		}
		//删除结果
		_, err = b.redisClient.Del(key).Result()
		if err != nil {
			golog.Error("Broker", "HandleFailTask", "delete result failed", 0, "key", key)
		}
		err = b.resetTaskRequest(results)
		if err != nil {
			golog.Error("Broker", "HandleFailTask", err.Error(), 0, "key", key)
			b.SetFailTaskCount(fmt.Sprintf("t_%s", uuid))
		}
	}

	return nil
}
Exemple #9
0
func (w *Worker) SetSuccessTaskCount(reqKey string) error {
	successTaskKey := fmt.Sprintf(config.SuccessTaskKey,
		time.Now().Format(config.TimeFormat))
	count, err := w.redisClient.Incr(successTaskKey).Result()
	if err != nil {
		golog.Error("Worker", "SetSuccessTaskCount", "Incr", 0, "err", err.Error(),
			"req_key", reqKey)
		return err
	}
	//第一次设置该key
	if count == 1 {
		//保存一个月
		expireTime := time.Second * time.Duration(60*60*24*30)
		_, err = w.redisClient.Expire(successTaskKey, expireTime).Result()
		if err != nil {
			golog.Error("Worker", "SetSuccessTaskCount", "Expire", 0, "err", err.Error(),
				"req_key", reqKey)
			return err
		}
	}
	return nil
}
Exemple #10
0
func (w *Worker) Run() error {
	w.running = true
	for w.running {
		uuid, err := w.redisClient.SPop(config.RequestUuidSet).Result()
		//没有请求
		if err == redis.Nil {
			time.Sleep(time.Second)
			continue
		}
		if err != nil {
			golog.Error("Worker", "run", "spop error", 0, "error", err.Error())
			continue
		}
		reqKey := fmt.Sprintf("t_%s", uuid)

		//获取请求中所有值
		request, err := w.redisClient.HMGet(reqKey,
			"uuid",
			"bin_name",
			"args",
			"start_time",
			"time_interval",
			"index",
		).Result()
		if err != nil {
			golog.Error("Worker", "run", err.Error(), 0, "req_key", reqKey)
			continue
		}
		//key不存在
		if request[0] == nil {
			golog.Error("Worker", "run", "Key is not exist", 0, "req_key", reqKey)
			continue
		}
		_, err = w.redisClient.Del(reqKey).Result()
		if err != nil {
			golog.Error("Worker", "run", "delete result failed", 0, "req_key", reqKey)
		}
		taskResult, err := w.DoTaskRequest(request)
		if err != nil {
			golog.Error("Worker", "run", "DoTaskRequest", 0, "err", err.Error(),
				"req_key", reqKey)
		}

		if taskResult != nil {
			err = w.SetTaskResult(taskResult)
			if err != nil {
				golog.Error("Worker", "run", "DoTaskRequest", 0,
					"err", err.Error(), "req_key", reqKey)
			}
			golog.Info("worker", "run", "do task success", 0, "req_key", reqKey,
				"result", taskResult.Result)
		}

		if w.cfg.Peroid != 0 {
			time.Sleep(time.Second * time.Duration(w.cfg.Peroid))
		}
	}
	return nil
}
Exemple #11
0
func (b *Broker) AddRequestToRedis(tr interface{}) error {
	r, ok := tr.(*task.TaskRequest)
	if !ok {
		return errors.ErrInvalidArgument
	}
	key := fmt.Sprintf("t_%s", r.Uuid)
	setCmd := b.redisClient.HMSet(key,
		"uuid", r.Uuid,
		"bin_name", r.BinName,
		"args", r.Args,
		"start_time", strconv.FormatInt(r.StartTime, 10),
		"time_interval", r.TimeInterval,
		"index", strconv.Itoa(r.Index),
		"max_run_time", strconv.FormatInt(r.MaxRunTime, 10),
		"task_type", strconv.Itoa(r.TaskType),
	)
	err := setCmd.Err()
	if err != nil {
		golog.Error("Broker", "AddRequestToRedis", "HMSET error", 0,
			"set", config.RequestUuidSet,
			"uuid", r.Uuid,
			"err", err.Error(),
		)
		return err
	}
	saddCmd := b.redisClient.SAdd(config.RequestUuidSet, r.Uuid)
	err = saddCmd.Err()
	if err != nil {
		golog.Error("Broker", "AddRequestToRedis", "SADD error", 0,
			"set", config.RequestUuidSet,
			"uuid", r.Uuid,
			"err", err.Error(),
		)
		return err
	}

	return nil
}
Exemple #12
0
func (w *Worker) DoTaskRequest(args []interface{}) (*task.TaskResult, error) {
	var err error
	var output string

	req := new(task.TaskRequest)
	ret := new(task.TaskResult)

	req.Uuid = args[0].(string)
	req.BinName = args[1].(string)
	req.Args = args[2].(string)
	req.StartTime, err = strconv.ParseInt(args[3].(string), 10, 64)
	if err != nil {
		return nil, err
	}
	req.TimeInterval = args[4].(string)
	req.Index, err = strconv.Atoi(args[5].(string))
	if err != nil {
		return nil, err
	}
	req.MaxRunTime, err = strconv.ParseInt(args[6].(string), 10, 64)
	if err != nil {
		return nil, err
	}
	req.TaskType, err = strconv.Atoi(args[7].(string))
	if err != nil {
		return nil, err
	}
	switch req.TaskType {
	case task.ScriptTask:
		output, err = w.DoScriptTaskRequest(req)
	case task.RpcTaskGET, task.RpcTaskPOST, task.RpcTaskPUT, task.RpcTaskDELETE:
		output, err = w.DoRpcTaskRequest(req)
	default:
		err = errors.ErrInvalidArgument
		golog.Error("Worker", "DoTaskRequest", "task type error", 0, "task_type", req.TaskType)
	}
	ret.TaskRequest = *req
	//执行任务失败,
	if err != nil {
		ret.IsSuccess = int64(0)
		ret.Result = err.Error()
		return ret, nil
	}
	ret.IsSuccess = int64(1)
	ret.Result = output

	return ret, nil
}
Exemple #13
0
func (b *Broker) Run() error {
	b.running = true

	go b.HandleFailTask()
	for b.running {
		conn, err := b.listener.Accept()
		if err != nil {
			golog.Error("server", "Run", err.Error(), 0)
			continue
		}
		//处理客户端请求
		go b.handleConn(conn)
	}

	return nil
}
Exemple #14
0
func (w *Worker) DoTaskRequest(args []interface{}) (*task.TaskResult, error) {
	var err error
	var output string
	req := new(task.TaskRequest)
	ret := new(task.TaskResult)

	req.Uuid = args[0].(string)
	req.BinName = args[1].(string)
	req.Args = args[2].(string)
	req.StartTime, err = strconv.ParseInt(args[3].(string), 10, 64)
	if err != nil {
		return nil, err
	}
	req.TimeInterval = args[4].(string)
	req.Index, err = strconv.Atoi(args[5].(string))
	if err != nil {
		return nil, err
	}
	binPath := path.Clean(w.cfg.BinPath + "/" + req.BinName)
	_, err = os.Stat(binPath)
	if err != nil && os.IsNotExist(err) {
		golog.Error("worker", "DoTaskRequest", "File not exist", 0,
			"key", fmt.Sprintf("t_%s", req.Uuid),
			"bin_path", binPath,
		)
		return nil, errors.ErrFileNotExist
	}
	if len(req.Args) == 0 {
		output, err = w.ExecBin(binPath, nil)
	} else {
		argsVec := strings.Split(req.Args, " ")
		output, err = w.ExecBin(binPath, argsVec)
	}

	ret.TaskRequest = *req
	//执行任务失败
	if err != nil {
		ret.IsSuccess = int64(0)
		ret.Result = err.Error()
		return ret, nil
	}
	ret.IsSuccess = int64(1)
	ret.Result = output

	return ret, nil
}
Exemple #15
0
func NewBroker(cfg *config.BrokerConfig) (*Broker, error) {
	var err error

	broker := new(Broker)
	broker.cfg = cfg
	broker.addr = cfg.Addr
	if len(broker.addr) == 0 {
		return nil, errors.ErrInvalidArgument
	}

	vec := strings.SplitN(cfg.RedisAddr, "/", 2)
	if len(vec) == 2 {
		broker.redisAddr = vec[0]
		broker.redisDB, err = strconv.Atoi(vec[1])
		if err != nil {
			return nil, err
		}
	} else {
		broker.redisAddr = vec[0]
		broker.redisDB = config.DefaultRedisDB
	}

	broker.web = echo.New()

	broker.timer = timer.New(time.Millisecond * 10)
	go broker.timer.Start()

	broker.redisClient = redis.NewClient(
		&redis.Options{
			Addr:     broker.redisAddr,
			Password: "", // no password set
			DB:       int64(broker.redisDB),
		},
	)
	_, err = broker.redisClient.Ping().Result()
	if err != nil {
		golog.Error("broker", "NewBroker", "ping redis fail", 0, "err", err.Error())
		return nil, err
	}

	return broker, nil
}
Exemple #16
0
func (b *Broker) HandleTaskResult(rb *bufio.Reader, c net.Conn) error {
	args := struct {
		Key string `json:"key"`
	}{}
	buf := make([]byte, 128)
	readLen, err := rb.Read(buf)
	if err != nil {
		b.WriteError(err, c)
		return err
	}

	err = json.Unmarshal(buf[:readLen], &args)
	if err != nil {
		b.WriteError(err, c)
		return err
	}

	result, err := b.redisClient.HMGet(args.Key,
		"is_success",
		"result",
	).Result()
	if err != nil {
		golog.Error("Broker", "HandleFailTask", err.Error(), 0, "key", args.Key)
		b.WriteError(err, c)
		return err
	}

	//key不存在
	if result[0] == nil {
		err = b.WriteResult(config.ResultNotExist, "0", "", c)
		return err
	}
	isSuccess := result[0].(string)
	ret := result[1].(string)
	return b.WriteResult(config.ResultIsExist, isSuccess, ret, c)
}