不见他过: 职场经验

2022年9月20日 22:39

 

一、什么是不见他过

 
1. 见如不见,视而不见,保护自己的心念,不被污染。
 
2. 好坏、善恶都是过眼云烟,不断在变化。
 
3. 好坏、善恶同样因人而异。一个对你很好,对另一个人可能会很坏。
 
“过”是无常的、相对的。而心灵至少会跟着自己几十年,污染了它,让生活过得不愉快,不值得。
 

二、个人看法

 
1. 上面的看法很对,没什么毛病
 
2. 真的所有情况都适合吗?一直存有疑问。
 

三、职场案例

 
1. 当我是个管理者,带着一个团队,达成某个目标。
 
2. 依据价值交换的原则管理团队
 
3. 当遇到了,有人甩锅、出工不出力,占着茅坑了。
 
4. 他违反了基本原则,已经从心理上把他排除团队了。另需要造势,把他从茅坑上弄走。
 
5. 这个时候,就不得不讲人过失了。
 
6. 这个做法对不对?会造成什么后果?
 

四、造成的后果

 
1. 虽然是按照原则处理的。然后事情传递后,会变味,影响个人前途。
 
2. 当事人也会用自己的影响力,以他的逻辑讲你的过失,会让你丢掉部分人心。
 
 

五、最佳做法

 
1. 只做不说,该排除就排除。
2. 缺少资源,直接找领导要。
 

六、总结

 
1. 底层员工。讲人过失,无非是受气了。人微言轻,很容易惹麻烦。
2. 中层管理。讲人过失,是为了造势,达成目的。同样有副作用。
3. 高层管理。讲人过失。容易让团队离心。
4. 是不是不能讲人过失,其实也不是
 
把每一次讲人过失,都当着要惹一次大祸。
有什么值得我冒这个大的险,我才会讲。
一般情况都不讲。
坚持这种心态N年之后,也许才会领会到“不见他过”更深层次的含义

评论(0) 阅读(709)

viper监控文件变化出现两次事件

2022年9月17日 20:03

 
问题描述
 
监控配置文件变化,如果内容发生了修改,需要及时加载. 使用viper监控文件变化发现了, 对文件修改一次,会出发两次事件.
 

示例代码

 
viper.OnConfigChange(func(e fsnotify.Event) {
    if e.Op & fsnotify.Write != 0 {
        fmt.Println("Config file changed:", e.Name)
    }
})
viper.WatchConfig()
 

推测原因

 
* 检查viper的源码是否存在bug?
 
未发现异常
 
* 两次变化viper读到的内容返回值是否不一样? 
 
发现viper.AllKeys()返回值不一样, 一次为空, 一次正常.
 
* 换一个电脑试试?
 
发现了在公司办公电脑出现,家里电脑不会出现。
 

解决办法

 
//使用AllKeys进行过滤
viper.OnConfigChange(func(e fsnotify.Event) {
	if e.Op & fsnotify.Write != 0 && viper.AllKeys()>0{
		fmt.Println("Config file changed:", e.Name)
	}
})
viper.WatchConfig()
 
 

总结

 
公司的办公电脑安装了文件加密软件。我估摸着是它搞了个什么鬼.
 
 
 
 
 

Tags: viper golang
评论(1) 阅读(135)

tomli支持数组混合类型

2022年8月05日 13:57

起因

    
    使用python的toml包解析toml配置文件。配置文件中使用了混合类型数组,结果程序报错。
 

原因与解决方法

 
1. toml0.5规范不支持数组混合类型, toml1.0规范才支持数组混合类型。
 
2. python的toml解析包有多种,toml包不支持1.0,所以不支持混合类型
 
3. 建议使用rtoml, tomli等
 

混合类型示例

 
a=[1, 2.1]
b=["a", ["b", "c"]]
c=["a", {"b": 1}]
 

rtoml用法

obj = rtoml.load("""
a=[1, 2.1]
""")
print(obj)
 

Tags: toml
评论(14) 阅读(346)

gin支持prometheus

2022年8月03日 15:25

 

起因

 
gin使用了微服务架构, 如何将自己的服务都监控起来?
 

疑问列表

 
 
1. grafana是什么, 能做什么?
 
grafana是一个监控平台,支持不同数据源的可视化。也就是说支持从prometheuse,influxdb等数据源, 并将他们的数据形式可视化的图表.
 
2. prometheus能做什么?
prometheuse是一个监控系统,通过定时http pull采集数据. 并且支持http push.
 
3. prometheus和grafana是什么关系?
prometheuse是监控系统, 界面展示比较粗糙, grafana主要是可视化, 并且支持多种类型数据源。
 
4. gin如何与prometheuse结合?
见后面
 
5. gin如何与grafana?
grafana不支持直接接入gin服务。需要gin先接入prometheuse,再将prometheus接入grafana。
 
6. gin服务的metrics数据格式如何解析?
暂时未找到
 
7. gin自定义监控项
略. 不是本文主题
 
 

下载安装

 
grafana
https://github.com/grafana/grafana

prometheus
https://github.com/prometheus/prometheus
 

gin支持prometheuse

 
1. 修改gin服务代码
 
import (
    ...
"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus/promhttp"
    ...
)


//metrics, promhttp默认可以查看cpu,mem,线程等信息
router.GET("/metrics", gin.WrapH(promhttp.Handler()))
 
2.修改prometheuse配置(prometheuse.yml)
 
scrape_configs:
  - job_name: "prometheus-demo"
    static_configs:
      - targets: ["192.168.28.26:8011"]
 
3. 启动服务
 
a. 启动gin和prometheuse服务后, 访问localhost:9090
 
b. 在"Expression"输入框选择"go_goroutines", 点击"Execute"
 
c. 刚开始数据比较少,可以过一段时间后再刷新页面
 
净土大经科注2014-doc
此生必看的科学实验-水知道答案
印光大师十念法(胡小林主讲第1集)
 

Tags: go prometheus
评论(15) 阅读(206)

wikijs使用docker安装

2022年7月25日 11:32

 

描述

 
wikijs文档有docker-compose安装说明, 实际中会遇到几个问题
 

wikij官网

 
 

遇到问题

 
1. wikijs上传之后的问题如何备份?  需要将本地目录挂入docker, 并在wikijs存储中配置为上传路径.
 
2. docker volume如何备份与还原?  需要借助busybox镜像。如果直接从/var/lib/docker/volume目录拷贝会遇到很多问题.
 

修改之后的docker-compose.yaml

version: "3"
services:

  wikidb:
    image: postgres:11-alpine
    environment:
      POSTGRES_DB: wiki
      POSTGRES_PASSWORD: wikijsrocks
      POSTGRES_USER: wikijs
    logging:
      driver: "none"
    restart: unless-stopped
    volumes:
      - db-data:/var/lib/postgresql/data

  wiki:
    image: ghcr.io/requarks/wiki:2
    depends_on:
      - wikidb
    environment:
      DB_TYPE: postgres
      DB_HOST: wikidb
      DB_PORT: 5432
      DB_USER: wikijs
      DB_PASS: wikijsrocks
      DB_NAME: wiki
    restart: unless-stopped
    volumes:
      - ./backup:/opt/backup
    ports:
      - "80:3000"

volumes:
  db-data:
 

备份与还原

 
//备份
docker run --rm -it -v ~/volume-backup:/backup -v /var/lib/docker:/docker busybox tar cfz /backup/volume.tgz /docker/volumes/wikijs_db-data
//还原
docker run --rm -it -v /var/lib/docker:/docker -v ~/volume-backup/docker/volumes:/volume-backup busybox cp -rp /volume-backup/wikijs_db-data /docker/volumes
 

Tags: docker
评论(11) 阅读(222)

golang实现枚举类型

2022年7月25日 10:50

描述

 
golang无枚举类型, 但可以借助自定义类型实现
 

什么是枚举类型

 
枚举类型是一种类型, 它的值只有有限个. 换而言之, 枚举类型=一个类型+N个离散值
 
go的实现, 可以自定义一个类型, 把它作为枚举类型, 然后使用该类型定义N个常量.
 
 

示例

 
type FormatType int

const (
    FTByte FormatType = iota
    FTArray
    FTDefine
)

func (ft FormatType) String() string {
    switch ft{
    case FTByte:
        return "byte"
    case FTArray:
        return "array"
    case FTDefine:
        return "define"
    }
    return ""
}
 
 

Tags: golang
评论(13) 阅读(226)

celery5.2.1以下版本任务调用多耗费1秒

2021年12月28日 10:14

问题

 
    5.0.5版本celery存在一个缺陷, 调用任务耗时多用1秒
 
    这个问题在5.2.0, 5.1.2同样存在
 
    没理解为什么到5.2.1版本才解决,甚至一度把celery排除python技术栈
 

环境描述

 
 
python3.6
celery5.0.5
windows 32位
 
 

调用celery任务代码摘要

 
# 1.send_task返回AsyncResult
# 2.AsyncResult的get()等待返回结果
# 3.get()会比真实多耗费1秒,并且每次请求都会出现

from celery import Celery
class xxxCelery(Celery):
    def call_xxx(self, name, timeout=120, **kwargs):
        LOG.info("send_task: %s" % locals())
        start = time.time()
        r = self.send_task(name, **kwargs)
        g = eventlet.spawn(r.get, timeout=timeout)
        result = g.wait()
        print("cost: %s" % time.time()-start)
        return
 

两个版本比对

 
分析celery源码之后,可以知道问题在drain_events()内部, 比较5.2.0和5.2.1版本
 
#celery/backends/asynchronuse.py

class greenletDrainer(Drainer):
    ...
    def run(self):
        self._started.set()
        while not self._stopped.is_set():
            try:
                self.result_consumer.drain_events(timeout=1)
                # 新增了两句, 估摸着是这个问题
                self._send_drain_complete_event()
                self._create_drain_complete_event()
            except socket.timeout:
                pass
        self._shutdown.set()
 
 

解决办法

 
    celery升级到5.2.1
 
    python要升级到3.7以上版本(celery要求python3.7以上版本)
 

解决效果

 
    耗时从1000多ms变成了30ms
 

Tags: celery
评论(244) 阅读(1538)

openssh8.6默认不支持公钥ssh

2021年12月02日 21:51

 

 起因

 
    最近升级了自己的linux后, 更新gogs代码时,发现用不了了
 
    反复测试原因,发现是最新版本openssh8.6关闭了公钥登录
 
 

错误提示

 
尝试了各种办法,会发现始终提示ssh登录失败
 
username@ip: Permission denied (publickey).
 

查看ssh详细信息

 
输出ssh调试信息,查看失败的具体原因
 
ssh -Tv username@ip

#发现了一条提示,这就是登录失败的原因
...
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering public key: /home/xxx/.ssh/id_rsa RSA SHA256:0IxiHWniJDBbsM8x0zx+zliWrl7PINcALzFFqVgKX/M agent
debug1: send_pubkey_test: no mutual signature algorithm
...
 
 

解决办法

 
 
sudo vim /etc/ssh/ssh_config

#增加一条PubKeyAcceptedKeyTypes

 Host *
    PubKeyAcceptedKeyTypes +ssh-rsa
#   ForwardAgent no
#   ForwardX11 no
#   PasswordAuthentication yes
#   HostbasedAuthentication no
#   GSSAPIAuthentication no
#   GSSAPIDelegateCredentials no
#   GSSAPIKeyExchange no
#   GSSAPITrustDNS no
#   BatchMode no
 
 

问题原因

 
    rsa有安全问题,新版本openssh,默认不支持rsa公钥登录,需要自己打开
 
 

Tags: gogs
评论(141) 阅读(986)

基于ectd实现go的服务注册

2021年11月27日 18:42

 

描述

 
    基于etcd实现go程序的服务注册,所看的学习资料均比较简单, 实际中要经过反复测试,自己写了一个先用着,有坑再填.
 

需求

 
1. 注册一个服务: 程序启动时
2. 注销服务: a. 程序异常退出时, 自动注销, 有5秒TTL延迟; b. 调用Stop()接口主动注销
3. 健壮性: a.ectd单节点重启, ectd本身支持; b. etcd全部重启后, 能够恢复正常
4. key的格式: 前缀/ip/pid
5. value: 字符串.(可以先转为json, 再转string)
 
 

创建etcd客户端

 

	
//不是重点, 摘要如下代码
 
cli, err := clientv3.New(clientv3.Config{
Endpoints:   ec.Endpoints,
DialTimeout: 5 * time.Second,
})
if err != nil {
log.Fatal(err)
}
 

创建Service对象, 包含服务注册

 
package main

import (
	"context"
	"errors"
	"fmt"
	clientv3 "go.etcd.io/etcd/client/v3"
	"go.etcd.io/etcd/client/v3/clientv3util"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"net"
	"os"
	"strings"
	"sync"
	"test/etcd"
	"time"
)


var IP string
var PID int


func init(){
	//日志
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	encoder := zapcore.NewConsoleEncoder(encoderConfig)

	//创建
	var clevel zapcore.Level
	clevel.Set("debug")
	log := zap.New(zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), clevel))
	//设为全局
	zap.ReplaceGlobals(log)

	//
	IP, _ = GetLocalIP()
	PID = os.Getpid()
}

func GetLocalIP() (string,error){
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		zap.S().Warn(err)
		return "", err
	}
	for _, addr := range addrs{
		if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback(){
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String(), nil
			}
		}
	}
	return "", errors.New("unable to determine local ip")
}


func RegisterService(endpoints []string, key string, value string) *Service{
	s := &Service{
		Value: value,
		endpoints: endpoints,
	}

	s.TTL = 5
	s.Key = strings.Join([]string{key, IP, fmt.Sprintf("%d", PID)}, "/")

	s.init()

	return s
}


type Service struct{
	Key          	string		//key 格式: /前缀/名称/ip/pid
	Value           string		//存放信息
	endpoints    	[]string	//etcd地址
	//心跳
	IsAlive      	bool		//是否存活
	heartCancel 	context.CancelFunc	//取消心跳
	//租约
	TTL             int64		//租约(秒)
	grant			*clientv3.LeaseGrantResponse	//租约
}


func (s *Service) init(){
	//启用etcd连接
	etcd.EnableEtcd(s.endpoints)

	//心跳
	go s.start()
}

func (s *Service) start(){
	defer func(){
		s.IsAlive = false

		//注销服务
		s.deleteService()
		//关闭续约(如果共用会误关?)
		etcd.Cli().Lease.Close()
	}()

	var aliveRsp <-chan *clientv3.LeaseKeepAliveResponse
	var err error
	var ctx context.Context
	for{
		if !s.IsAlive{
			// 注册服务
			s.registerService()

			// 续期信号chan
			aliveRsp, err = etcd.Cli().KeepAlive(context.TODO(), s.grant.ID)
			if err != nil{
				zap.S().Warn(err)
			}

			ctx, s.heartCancel = context.WithCancel(context.Background())
		}

		// 监听心跳信号
		select{
		case rsp := <- aliveRsp:
            //异常时无信号
			if rsp ==nil{
				s.IsAlive = false
				zap.S().Info("service missing signal")
				time.Sleep(time.Second*5)
				continue
			}

			s.IsAlive = true
			zap.S().Debugf("service alive %v", rsp.ID)
		case <- ctx.Done():
			zap.S().Info("service stopping")
			return
		}
	}
}

//停止

func (s *Service) Stop(){
	s.heartCancel()
}
 
[佛說大乘無量壽莊嚴清淨平等覺經pdf](http://www.sxjy360.top/page-download/)
[净土大经科注2014-doc](http://www.sxjy360.top/page-download/)
[此生必看的科学实验-水知道答案](http://www.sxjy360.top/page-download/)
[印光大师十念法(胡小林主讲第1集)](http://www.sxjy360.top/page-download/)
 

Tags: etcd
评论(107) 阅读(821)

go和python解码msgpack不一致

2021年11月27日 18:37

 

描述

 
    有一个消息字典类型, 使用go进行编码, 传入消息中间件。同时有一个python程序监听, 监听到消息之后进行解码, 遇到了编码问题
 
 

环境

 
go使用:     github.com/vmihailenco/msgpack/v5 v5.3.4
python使用: msgpack==1.0.2
 
 

python解码

 
# go编码的对象是个字典,value可能包含了数组,并且数组类型复杂
msgpack.unpackb(xxx)
 
 

错误提示

 
UnicodeDecodeError: 'utf-8' codec can't decode byte 0bx0 in position 0: invalid start byte
 

解决办法

 
msgpack.unpackb(xxx, raw=True)

#raw=True  解析为python字节类型
#raw=False 解析为python字符串, 默认使用utf-8编码
 

评论(75) 阅读(610)