编程笔记

lifelong learning & practice makes perfect

什么是微服务,微服务概览

微服务设计

服务治理

服务发现

grpc

多租户&多集群

service mesh

  1. excelize 介绍
1
2


  1. 时间格式读取

excel表格操作库,对日期格式的数据读写还不是很完善,能识别的日期格式返回一个01-02-06(day-month-day)格式的字符串,无法识别时直接返回的是excel表格中的原始数据,一个浮点型数,在excel中支持很多种日期格式显示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
file,err:=excelize.OpenFile(filepath)
if err!=nil{
return
}

strTime,err:=file.GetCellValue("Sheet1","A1")
if err!=nil{
return
}

// 方式一:正常识别,通过time的库函数转换
resTime, err = time.ParseInLocation("01-02-06", strTime, time.Local)

// 方式二:未正常识别,先转换成int型数据再转换
intTime,err:=strconv.Atoi(strTime)
if err!=nil{
return
}

//转换为time.Time
time.Time=excelize.ExcelDateToTime(float64(intTime),false)
  1. 时间格式写入
    通过excelize写入时间格式的数据到文件,需要设置单元格格式,excelize支持写入的格式包含有time.Time,但是写入时需要使用UTC格式。
1
2
3
4
5
6
7
8
file:=excelize.NewFile()
//style 格式编号
style,err:=file.NewStyle(`{"number_format": 14}`)
if err!=nil{
return
}
file.SetCellValue("Sheet1","A1",time.Now().UTC())
file.SetCellStyle("Sheet1","A1","A1",style)

hexo clean 清除用于部署博客文件
删除.deploygit(也是)

先将themes/下要使用的主题作为git submodule,(git submodule add https://****.git)
添加后可使用git submodule查看子模块

将hexo根目录下的文件(含themes source scaffolds 等的目录)添加到git上传到私有项目

设置workflow等

由于使用了子模块

checkout的workflow最好找对应的submodule checkout

参考

系统依赖

  • Jenkins
  • nginx
  • golang后端
  • 前端

问题

  1. 接口调用失败,到服务器上本地请求接口失败
  2. 通过ps搜索后端进程,发现服务进程不存在,判定=>Jenkins构建失败
  3. 然后到Jenkins上查看构建日志,发现报错信息,’sudo stop xxxx [no runing]’,错误判定为有人修改了服务器配置,问了一圈人,没有修改
  4. 排除员工原因,查找代码原因,尝试直接执行在服务器本地的后端可执行程序,报错
  5. 排查代码原因

反思

大部分错误最先从代码层面开始找,比较有效率,服务器配置之类的改动毕竟比较少;错误日志需要仔细查看,往往兜兜转转找了一圈会发现
错误提示一开始就清晰地摆在面前.
下决定前多思考.

command

  1. lsb_release : 查看LSB(Linux Standard Base),Distribution information

description & usage

  1. LSB (Linux Standard Base)
  2. tldr description
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    lsb_release

    Provides certain LSB (Linux Standard Base) and distribution-specific information.

    - Print all available information:
    lsb_release -a

    - Print a description (usually the full name) of the operating system:
    lsb_release -d

    - Print only the operating system name (ID), suppressing the field name:
    lsb_release -i -s

    - Print the release number and codename of the distribution, suppressing the field names:
    lsb_release -rcs

    example

    1
    2
    3
    4
    5
    LSB Version:    :core-4.1-amd64:core-4.1-noarch
    Distributor ID: CentOS
    Description: CentOS Linux release 8.2.2004 (Core)
    Release: 8.2.2004
    Codename: Core

Waht

slow_log table

  1. table

    column type null default description
    start_time timestamp(6) NO CURRENT_TIMESTAMP(6) Time the query began.
    user_host mediumtext NO NULL User and host combination.
    query_time time(6) NO NULL Total time the query took to execute.
    lock_time time(6) NO NULL Total time the query was locked.
    rows_sent int(11) NO NULL Number of rows sent.
    rows_examined int(11) NO NULL Number of rows examined.
    db varchar(512) NO NULL Default database.
    last_insert_id int(11) NO NULL last_insert_id.
    insert_id int(11) NO NULL Insert id.
    server_id int(10) unsigned NO NULL The server’s id.
    sql_text mediumtext NO NULL Full query.
    thread_id bigint(21) unsigned NO NULL Thread id.
    rows_affected int(11) NO NULL Number of rows affected by an UPDATE or DELETE (from MariaDB 10.1.2)
  2. reference

  1. 查看相关参数
    1
    2
    show variables like 'long%';
    show variables like 'slow%';
    • long_query_time,SQL语句执行时间超过此数值,记录日志
    • slow_query_log,是否开启慢查询(ON/OFF)
    • slow_query_log_file,慢查询日志文件
    • slow_launch_time
    • log_output,慢查询日志输出方式,可选FILE(文件,通过slow_query_log_file查询),TABLE(数据表是mysql.slow_log表)
  2. 设置参数
    1
    set long_query_time=0.5;
    开启慢查询日志,需要设置如下参数:
    • long_query_time,慢查询时间
    • slow_query_log,是否开启
    • log_output,日志输出方式,这个是全局变量.
      通过set global设置,如:
      1
      2
      3
      SET GLOBAl log_output='TABLE';

      SET GLOBAl log_output='FILE';
  3. 通过sql查询
    1
    select * from mysql.slow_log;
  4. 通过文件查询
    查询slow_query_log_file参数得到慢查询日志文件所在位置,查看文件.

Solution 性能优化

索引

在无索引的表中查询会进行全表扫描,如果表的数据量很大,则扫描大量的数据,执行效率过
慢,占用数据库连接,连接数堆积很快达到数据库的最大连接数设置,新的应用请求将会被拒绝导致故障发生。
隐式转换也会导致索引无法使用.

创建索引
  1. 在经常查询而不经常增删改操作的字段加索引。
  2. order by与group by后应直接使用字段,而且字段应该是索引字段。
  3. 一个表上的索引不应该超过6个。
  4. 索引字段的长度固定,且长度较短。
  5. 索引字段重复不能过多。
  6. 在过滤性高的字段上加索引。
使用索引注意事项
  1. 使用like关键字时,前置%会导致索引失效。
  2. 使用null值会被自动从索引中排除,索引一般不会建立在有空值的列上。
  3. 使用or关键字时,or左右字段如果存在一个没有索引,有索引字段也会失效。
  4. 使用!=操作符时,将放弃使用索引。因为范围不确定,使用索引效率不高,会被引擎自动改为全表扫描。
  5. 不要在索引字段进行运算。
  6. 在使用复合索引时,最左前缀原则,查询时必须使用索引的第一个字段,否则索引失效;并且应尽量让字段顺序与索引顺序一致。
  7. 避免隐式转换,定义的数据类型与传入的数据类型保持一致。
验证

使用mysql的explain分析sql,查看执行计划.

  1. 执行计划参数含义
  2. 例如一个sql执行计划如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      // type为ALL,是全表扫描,每次执行需要扫描505560行数据
    id: 1
    select_type: SIMPLE
    table: customers
    type: ALL
    possible_keys: NULL
    key: NULL
    key_len: NULL
    ref: NULL
    rows: 505560
    Extra: Using where
    增加索引后:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      // 执行计划看到type为ref,基于索引的等值查询,或者表间等值连接
    id: 1
    select_type: SIMPLE
    table: customers
    type: ref
    possible_keys: idx_cus
    key: idx_cus
    key_len: 31
    ref: const
    rows: 4555
    Extra: Using index condition

    参考

  3. 阿里云: https://help.aliyun.com/document_detail/52274.html?spm=a2c4g.11186623.2.8.1b1945135Wahhf

通过iperf,iperf3测试网络

iperf用法

tldr工具获取的iperf用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
iperf

Measure network bandwidth between computers.
More information: https://iperf.fr.
- Run on server:
iperf -s

- Run on server using UDP mode and set server port to listen on 5001:
iperf -u -s -p 5001

- Run on client:
iperf -c server_address

- Run on client every 2 seconds:
iperf -c server_address -i 2

- Run on client with 5 parallel threads:
iperf -c server_address -P 5

- Run on client using UDP mode:
iperf -u -c server_address -p 5001

分别启动server和client进行测试,如:

1
2
iperf -s -p 9988 -f M
iperf -c 111.111.111.111 -p 9988 -t 300 -d -f M -i 2

参数说明

  1. -f 格式/单位:Kbits, Mbits, KBytes, MBytes
  2. -i
  3. -p
  4. -P
  5. -u
  6. -c
  7. -s

在阿里云服务器上遇到的问题

  1. 问题
    阿里云服务器上仅开放了80和443,及ssh端口,其他端口未开放,不能使用其他端口进行测试,也无权限开放新的端口用
    于测试,服务上提供api接口的服务也都是通过nginx反向代理实现.
  2. 测试代码
1
2
3
4
5
6
7
8
9
address, err := net.ResolveTCPAddr("tcp", "http://server_address:18090")
if err != nil {
fmt.Println(err)
}
conn, err := net.DialTCP("tcp4", nil, address)
if err != nil {
fmt.Println(err)
}
conn.Write([]byte("test connect"))

无法建立tcp连接,timeout

解决

服务器上无可用端口用于测试,仅开放的80,443等端口已被网页服务服务占用,可以通过ssh端口转发到一个未暴露的端口,在该端口启动iperf的服务端进行测试.

1
2
3
4
ssh -L local_port:localhost:server_port_for_iperf -N -T user@server_address -p   server_ssh_port
如:
ssh -L 9999:localhost:8888 -N -T user_test@111.111.111.111 -p 22
将发送到本地端口9999的请求数据转发到111.111.111.111转发到8888端口

在服务器上启动iperf server

1
2
3
4
iperf -s -p port -f M

iperf -s -p 8888
使用TCP方式,在8888端口启动服务端,监听

结果

数据

1
2
3
4
5
6
7
8
9
10
11
12
[ ID] Interval       Transfer     Bandwidth
[ 13] 0.0-44.1 sec 30.5 MBytes 0.69 MBytes/sec
[ 7] 0.0-44.2 sec 30.6 MBytes 0.69 MBytes/sec
[ 9] 0.0-44.2 sec 30.6 MBytes 0.69 MBytes/sec
[ 11] 0.0-44.2 sec 30.6 MBytes 0.69 MBytes/sec
[ 15] 0.0-44.2 sec 30.6 MBytes 0.69 MBytes/sec
[ 21] 0.0-44.9 sec 31.6 MBytes 0.70 MBytes/sec
[ 17] 0.0-45.1 sec 31.9 MBytes 0.71 MBytes/sec
[ 4] 0.0-45.2 sec 32.5 MBytes 0.72 MBytes/sec
[ 18] 0.0-45.2 sec 32.1 MBytes 0.71 MBytes/sec
[ 5] 0.0-45.2 sec 32.5 MBytes 0.72 MBytes/sec
[SUM] 0.0-45.2 sec 314 MBytes 6.94 MBytes/sec

分析

参考

  1. ssh端口转发: 玩转SSH端口转发 https://zhuanlan.zhihu.com/p/26547381
  2. nginx反向代理:

3.

外观配置

resource position

C:\Users(user_name)\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\RoamingState

icon

每个profile可单独设置,增加icon项指定icon位置

1
"icon" : "ms-appdata:///roaming/ubuntu.png"

background

1
"backgroundImage": "ms-appdata:///roaming/arch_linux.jpg",

  • Errror description

MFC dll中的界面在Debug时调用UpdateData()函数,会判断窗口的运行环境是否跨线程,如果创建窗口的线程与调用该函数的线程不是同一个,就会触发CWnd的AssertVaild()函数中断.提示:

it is likely that you have passed a C++ object from one thread to another and have used that object in a way that was not intended.把一个C++对象从一个线程传到另一个线程,使用对象的方式不正确(与代码的原本设计相悖)

阅读全文 »