博客

  • CentOS 8 安装 Python 3.8.0

    CentOS 8 安装 Python 3.8.0

    [root@aikaiyuan ~]# cat /etc/redhat-release
    CentOS Linux release 8.0.1905 (Core)
    [root@aikaiyuan ~]# dnf install libffi-devel -y
    

    安装 OpenSSL 1.1.1d

    [root@aikaiyuan ~]# wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz
    [root@aikaiyuan ~]# tar zxvf openssl-1.1.1d.tar.gz
    [root@aikaiyuan ~]# cd openssl-1.1.1d/
    [root@aikaiyuan ~/openssl-1.1.1d]# ./config --prefix=/usr/local/openssl-1.1.1d --openssldir=/usr/local/openssl-1.1.1d
    [root@aikaiyuan ~/openssl-1.1.1d]# make -j
    [root@aikaiyuan ~/openssl-1.1.1d]# make install
    
    [root@aikaiyuan ~/openssl-1.1.1d]# echo "/usr/local/openssl-1.1.1d/lib/" > /etc/ld.so.conf.d/openssl-1.1.1d.conf
    [root@aikaiyuan ~/openssl-1.1.1d]# ldconfig
    [root@aikaiyuan ~/openssl-1.1.1d]# /usr/local/openssl-1.1.1d/bin/openssl version
    OpenSSL 1.1.1d  10 Sep 2019
    

    安装 Python 3.8.0

    [root@aikaiyuan ~]# wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz
    [root@aikaiyuan ~]# tar zxvf Python-3.8.0.tgz
    [root@aikaiyuan ~]# cd Python-3.8.0/
    [root@aikaiyuan ~/Python-3.8.0]# vi Modules/Setup
    

    修改 Setup 文件如下:

    SSL=/usr/local/openssl-1.1.1d
    _ssl _ssl.c \
            -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
            -L$(SSL)/lib -lssl -lcrypto
    
    [root@aikaiyuan ~/Python-3.8.0]# ./configure --prefix=/usr/local/python-3.8.0 --with-openssl=/usr/local/openssl-1.1.1d --enable-optimizations
    [root@aikaiyuan ~/Python-3.8.0]# make -j
    [root@aikaiyuan ~/Python-3.8.0]# make install
    
    [root@aikaiyuan ~/Python-3.8.0]# /usr/local/python-3.8.0/bin/python3
    Python 3.8.0 (default, Nov 13 2019, 16:49:35)
    [GCC 8.2.1 20180905 (Red Hat 8.2.1-3)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> sys.version
    '3.8.0 (default, Nov 13 2019, 16:49:35) \n[GCC 8.2.1 20180905 (Red Hat 8.2.1-3)]'
    >>>
    

    转载请注明:爱开源 » CentOS 8 安装 Python 3.8.0

  • apt-get 使用HTTP代理

    测试代理

     # curl -x 127.0.0.1:8118 https://ip.cn
    {"ip": "xxx.xxx.xxx.xxx", "country": "美国", "city": "Multacom"}
    

    添加 80proxy.conf 配置文件

     # cat /etc/apt/apt.conf.d/80proxy.conf
    Acquire::http::Proxy "http://127.0.0.1:8118";
    

    使用代理方式(不推荐)

    export http_proxy=127.0.0.1:8118
    

    转载请注明:爱开源 » apt-get 使用HTTP代理

  • CentOS 7 CentOS 8 下 NetworkManager 配置网卡

    CentOS 7 CentOS 8 下 NetworkManager 配置网卡

    • 所有 nmcli 命令调用完成后, 会自动更新 ifcfg-eth0 route-eth0 等等相关配置文件
    • 部分参数修改完之后,调用 nmcli connection up eth0 使配置生效

    查看设备

    [root@aikaiyuan ~]# yum install bash-completion -y
    [root@aikaiyuan ~]# nmcli device show | grep DEV
    GENERAL.DEVICE:                         eth0
    GENERAL.DEVICE:                         eth1
    GENERAL.DEVICE:                         lo
    

    安装 bash-completion , 可以多使用 tab 补全功能
    eth0 和 eth1 , 关于设备名可以 查看下面文章

    CentOS 7 CentOS 8 网卡命名规则

    接口和设备映射

    [root@aikaiyuan ~]# nmcli connection add type ethernet con-name eth0 ifname eth0
    [root@aikaiyuan ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
    TYPE=Ethernet
    PROXY_METHOD=none
    BROWSER_ONLY=no
    BOOTPROTO=dhcp
    DEFROUTE=yes
    IPV4_FAILURE_FATAL=no
    IPV6INIT=yes
    IPV6_AUTOCONF=yes
    IPV6_DEFROUTE=yes
    IPV6_FAILURE_FATAL=no
    IPV6_ADDR_GEN_MODE=stable-privacy
    NAME=eth0
    UUID=8a7935e9-4b6e-41e5-856f-51bea112f672
    DEVICE=eth0
    ONBOOT=yes
    

    新创建一个 eth0 接口, 绑定到 eth0 设备上
    完成之后会 会自动创建 /etc/sysconfig/network-scripts/ifcfg-eth0 文件

    开机自启动

    [root@aikaiyuan ~]# nmcli connection modify eth0 connection.autoconnect yes
    

    配置IP/MASK/GATEWAY/DHCP

    1. 关闭DHCP, 默认是开启DHCP的 BOOTPROTO=dhcp
    [root@aikaiyuan ~]# nmcli connection modify eth0 ipv4.method manual
    [root@aikaiyuan ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep BOOTPRO
    BOOTPROTO=none
    
    或禁用
    [root@aikaiyuan ~]# nmcli connection modify eth0 ipv4.method disabled
    
    1. 配置IPv4 地址
    [root@aikaiyuan ~]# nmcli connection modify eth0 ipv4.add 192.168.1.144/24
    [root@aikaiyuan ~]# nmcli connection show eth0 | grep ipv4.addresses
    ipv4.addresses:                         192.168.1.144/24
    [root@aikaiyuan ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep -E 'IPADDR|PREFIX'
    IPADDR=192.168.1.144
    PREFIX=24
    
    1. 添加DNS
    [root@aikaiyuan ~]# nmcli connection modify eth0 ipv4.dns "192.168.1.10 192.168.1.20"
    [root@aikaiyuan ~]# nmcli connection modify eth0 +ipv4.dns 192.168.1.30
    [root@aikaiyuan ~]# nmcli connection modify eth0 -ipv4.dns 192.168.1.10
    [root@aikaiyuan ~]# nmcli connection modify eth0 ipv4.dns-search "aikaiyuan.com"
    [root@aikaiyuan ~]# nmcli connection modify eth0 ipv4.dns-options "timeout:1"
    [root@aikaiyuan ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep DNS
    DNS1=192.168.1.20
    DNS2=192.168.1.30
    [root@aikaiyuan ~]# nmcli connection up eth0
    Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/13)
    [root@aikaiyuan ~]# cat /etc/resolv.conf
    # Generated by NetworkManager
    search aikaiyuan.com
    nameserver 192.168.1.20
    nameserver 192.168.1.30
    options timeout:1
    

    注意: 参数前面符号,

    没有符号: 全量覆盖
    “+” 加号: 添加配置
    “-” 减号: 删除配置

    最后 up eth0 配置生效,并写入配置文件

    1. 添加默认网关
    [root@aikaiyuan ~]# nmcli connection modify eth0 ipv4.gateway 192.168.1.1
    [root@aikaiyuan ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep -E "GATEWAY|^DEFROUTE"
    DEFROUTE=yes
    GATEWAY=192.168.1.1
    
    删除网关
    [root@aikaiyuan ~]# nmcli c modify eth0 -ipv4.gateway ""
    

    这里要注意 DEFROUTE=yes 配置
    这里 eth0 连接公网,需要走默认路由, 也就是 ip route 看到的 default via 192.168.1.1 dev eth0默认网关
    如果有多个设备, 另外设备要 关闭
    DEFROUTE=no`, 否则会出现多个 默认 网关

    [root@aikaiyuan ~]# nmcli connection modify eth1 ipv4.never-default yes
    [root@aikaiyuan ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | grep "^DEFROUTE"
    DEFROUTE=no
    [root@aikaiyuan ~]# nmcli connection modify eth1 +ipv4.routes "10.0.0.0/8 172.16.1.1"
    [root@aikaiyuan ~]# nmcli connection modify eth1 +ipv4.routes "172.16.0.0/12 172.16.1.1"
    [root@aikaiyuan ~]# cat /etc/sysconfig/network-scripts/route-eth1
    10.0.0.0/8 via 172.16.1.1
    172.16.0.0/12 via 172.16.1.1
    

    这里是对 第二个设备 eth1 配置
    添加 内网路由

    修改MTU

    [root@aikaiyuan ~]# nmcli connection show eth0 | grep mtu
    802-3-ethernet.mtu:                     auto
    [root@aikaiyuan ~]# nmcli connection modify eth0 802-3-ethernet.mtu 1480
    [root@aikaiyuan ~]# nmcli connection show eth0 | grep mtu
    802-3-ethernet.mtu:                     1480
    [root@aikaiyuan ~]# nmcli connection up eth0
    Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/12)
    

    MTU 一般默认 auto 即可, 如果有特许需求在修改

    转载请注明:爱开源 » CentOS 7 CentOS 8 下 NetworkManager 配置网卡

  • curl 连接超时,执行超时

    连接超时

    [root@aikaiyuan ~]# curl --connect-timeout 1 http://2.2.2.2
    curl: (28) Connection timed out after 1001 milliseconds
    

    连接超时

           --connect-timeout <seconds>
                  Maximum time in seconds that you allow curl's connection to take.  This only limits the connection phase, so if curl connects within the
                  given period it will continue - if not it will exit.  Since version 7.32.0, this option accepts decimal values.
    
                  If this option is used several times, the last one will be used.
    
                  See also -m, --max-time.
    

    最大执行时间

    [root@aikaiyuan ~]# curl --max-time 2 http://2.2.2.2
    curl: (28) Operation timed out after 2005 milliseconds with 0 bytes received
    

    curl 最大执行时间, 有时候连接成功了, 但服务端长时间未返回,可以使用 max-time

           -m, --max-time <seconds>
                  Maximum time in seconds that you allow the whole operation to take.  This is useful for preventing your  batch  jobs  from  hanging  for
                  hours  due to slow networks or links going down.  Since 7.32.0, this option accepts decimal values, but the actual timeout will decrease
                  in accuracy as the specified timeout increases in decimal precision.
    
                  If this option is used several times, the last one will be used.
    
                  See also --connect-timeout.
    

    转载请注明:爱开源 » curl 连接超时,执行超时

  • CentOS 7 CentOS 8 网卡命名规则

    CentOS 7 CentOS 8 网卡命名规则

    修改方法

    安装依赖 yum install initscripts biosdevname

    1. 修改/etc/default/grub
    2. 在 GRUB_CMDLINE_LINUX 后面添加如下 参数,

      GRUB_CMDLINE_LINUX=”crashkernel=auto rhgb quiet net.ifnames=1 biosdevname=1″

    • 需要 em[id] 添加 net.ifnames=1 biosdevname=1
    • 需要 eth[id] 添加 net.ifnames=0 biosdevname=0
    • 需要 enp0s2 添加 net.ifnames=1 biosdevname=0
      3. 重新生成image # grub2-mkconfig -o /boot/grub2/grub.cfg
      4. 重启

    以下是命名规则

       从centos7开始,系统默认的网卡命名有已经不是我们熟悉的ethX方式了,细心的同学会留意到一些比如ens enp等开头的网卡名称,简单了解,可以解释为centos7开始,网卡命名会根据网卡的硬件信息,插槽位置等有关;
    
       而网上也有为那些依然想使用ethX方式命名的提供了策略。比如在内核启动参数里增加biosdevname=0 net.ifnames=0;
    
       但是这里忽略了 一个问题,那就是为什么centos7不再使用以前的ethX方式?根本是因为之前ethX方式是不确定的,每次启动可能都不同(如果没有用户自定义网卡名称的前提下);
    

    所以大家提供的这种办法其实是不好的;

       解释完上面内容之后,咱们来看下到底网卡名称是如何命名的。
    
       核心流程:明确一点是,linux内核启动过程中,会默认给网卡以ethX方式随机命名,然后再通过systemd去rename成其他名称。关键字,rename!
    

    biosdevname和net.ifnames两种命名规范

    net.ifnames的命名规范为:

    设备类型:

    • en 表示Ethernet
    • wl 表示WLAN
    • ww 表示无线广域网WWAN

    设备位置:

    Format Description
    o on-board device index number
    s[f][d] hotplug slot index number
    x MAC address
    ps[f][d] PCI geographical location
    ps[f][u][..][c][i] USB port number chain

    实际的例子:

    • eno1 板载网卡
    • enp0s2 pci网卡
    • ens33 pci网卡
    • wlp3s0 PCI无线网卡
    • wwp0s29f7u2i2 4G modem
    • wlp0s2f1u4u1 连接在USB Hub上的无线网卡
    • enx78e7d1ea46da pci网卡

    biosdevname的命名规范为

    实际的例子:

    • em1 板载网卡
    • p3p4 pci网卡
    • p3p4_1 虚拟网卡

    一、如何rename?

    默认rename流程:

    1. step1 依据/usr/lib/udev/rules.d/60-net.rules, 查看是否有ifcfg-xx配置文件(路径在/etc/sysconfig/network-scripts/),是否有定义了指定MAC地址的配置文件(ifcfg-xx ,xx必须和配置文件的内容DEVICE一致),如果有,则命名改网卡;

    2. 如果 /etc/udev/rules.d/70-persistent-net.rules 地址与 ifcfg-xx 匹配使用自定义网卡名

    3. # cat /etc/udev/rules.d/70-persistent-net.rules
      SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:0c:29:9f:c8:dd", NAME="aaa"
      # cat /etc/sysconfig/network-scripts/ifcfg-aaa | grep -E 'aaa|MACADDR'
      NAME="aaa"
      DEVICE="aaa"
      MACADDR="00:0c:29:9f:c8:dd"
    4. step2 依据/usr/lib/udev/rules.d/71-biosdevname.rules, 如果系统中安装了biosdevname,且内核参数未指定biosdevname=0,且上一步没有重命名网卡,则按照biosdevname的命名规范,从BIOS中取相关信息来命名网卡。主要是取SMBIOS中的type 9 (System Slot) 和 type 41 (Onboard Devices Extended Information)不过要求SMBIOS的版本要高于2.6,且系统中要安装biosdevname程序。

    5. # cat /usr/lib/udev/rules.d/71-biosdevname.rules
      # whitelist all Dell systems
      ATTR{[dmi/id]sys_vendor}=="Dell*", ENV{UDEV_BIOSDEVNAME}="1" # 是 Dell 型号设置 biosdevname=1
      # kernel command line "biosdevname={0|1}" can turn off/on biosdevname
      IMPORT{cmdline}="biosdevname" # 从GRUB启动项重置 biosdevname 配置
      ENV{UDEV_BIOSDEVNAME}=="0", GOTO="netdevicename_end" # 如果 biosdevname = 0 跳出 end
      ENV{UDEV_BIOSDEVNAME}=="1", GOTO="netdevicename_start" # 如果 biosdevname = 1 执行 netdevicename_start
      # off by default
      GOTO="netdevicename_end"
      LABEL="netdevicename_start"
      # using NAME= instead of setting INTERFACE_NAME, so that persistent
      # names aren't generated for these devices, they are "named" on each boot.
      SUBSYSTEMS=="pci", PROGRAM="/sbin/biosdevname --smbios 2.6 --nopirq --policy physical -i %k", NAME="%c" OPTIONS+="string_escape=replace" # 执行 /sbin/biosdevname 命令
      LABEL="netdevicename_end"

    6. step3, 依据/lib/udev/rules.d/75-net-description.rules,将udev工具会根据device属性将填写网卡的属性命名,可能一个网卡会有多个维度的名称哦;

    udevadm info /sys/class/net/aaa | grep NAME

    E: ID_NET_NAME_MAC=enx000c299fc8dd
    E: ID_NET_NAME_PATH=enp4s0
    E: ID_NET_NAME_SLOT=ens161
    4. step4, /usr/lib/udev/rules.d/80-net-name-slot.rules 如果在60-net.rules ,71-biosdevname.rules这两条规则中没有重命名网卡,且内核未指定net.ifnames=0参数 则udev依次尝试使用以下属性值来命名网卡,如果这些属性值都没有,则网卡不会被重命名。

    1. # cat /usr/lib/udev/rules.d/80-net-name-slot.rules
      # do not edit this file, it will be overwritten on update
      ACTION!="add", GOTO="net_name_slot_end"
      SUBSYSTEM!="net", GOTO="net_name_slot_end"
      NAME!="", GOTO="net_name_slot_end"
      IMPORT{cmdline}="net.ifnames" # 从 GRUB 读取 net.ifnames 配置, net.ifnames = 0 跳出 net.ifnames = 1 按照下面顺序配置
      ENV{net.ifnames}=="0", GOTO="net_name_slot_end"
      NAME=="", ENV{ID_NET_NAME_ONBOARD}!="", NAME="$env{ID_NET_NAME_ONBOARD}" # 没有名字,ID_NET_NAME_ONBOARD这个ENV存在,用ID_NET_NAME_ONBOARD作为名字
      NAME=="", ENV{ID_NET_NAME_SLOT}!="", NAME="$env{ID_NET_NAME_SLOT}" # 没有名字,ID_NET_NAME_SLOT这个ENV存在,用ID_NET_NAME_SLOT作为名字
      NAME=="", ENV{ID_NET_NAME_PATH}!="", NAME="$env{ID_NET_NAME_PATH}" # 没有名字,ID_NET_NAME_PATH这个ENV存在,用ID_NET_NAME_PATH作为名字
      LABEL="net_name_slot_end"
    2. step5,udev 根据step3中的赋值,按照指定的scheme规则,去给在step1 step2中没有命名的网卡命名;

    强调:这个step顺序是在我们没有自定义自己的rules的前提下,如果用户自定义了自己的rules,则用户自定义为优先级最高;

    二、scheme次序

    上面step4中提到,按照指定的scheme规则,这个规则是什么呢?

    首先说step3中,提到按照网卡的不同属性命名,系统识别网卡有好几种维度:

    • 比如:BIOS provided index numbers for on-board devices (example: eno1),
    • 比如:BIOS provided PCI Express hotplug slot index numbers (example: ens1)
    • 比如:physical location of the connector of the hardware (example: enp2s0),
    • 比如:mac地址

    同一个网卡通常同时具有多个维度的名称,systemd在选取的时候,按照有先后次序,使用先命中的;

    顺序可以简单理解为(eno1-ens1-enp1)

    # qemu xml 配置
        <interface type='bridge'>
          <mac address='52:54:00:b5:4d:84'/>
          <source bridge='br0'/>
          <model type='virtio'/>
          <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
        </interface>
    
    [root@aikaiyuan ~]# lspci | grep Eth
    00:02.0 Ethernet controller: Red Hat, Inc. Virtio network device
    00:03.0 Ethernet controller: Red Hat, Inc. Virtio network device
    
    [root@aikaiyuan ~]# udevadm info /sys/class/net/eth0 | grep NAME
    E: ID_NET_NAME_MAC=enx525400b54d84
    E: ID_NET_NAME_PATH=enp0s2
    E: ID_NET_NAME_SLOT=ens2
    E: UDEV_BIOSDEVNAME=0
    [root@aikaiyuan ~]#
    

    eth0这个网卡,scheme名称有3个,如果systemd自选,会使用哪个?ens2.(那这个为什么是/sys/class/net/eth0 而不是/sys/class/net/ens2 ,那是因为自定义
    在我们未修改 /etc/default/grub 之前系统默认就是 ens2

    三、用户自定义网卡名称

    1. 在用户没有自定义rules文件前提下,step1中的网卡命名方式也可认为是 一种用户自定义的网卡命名,即在/etc/sysconfig/network-scripts/ifcfg-xx 文件,xx就是这个网卡名称,文件内容中体现MAC_ADDRESS、NAME,这种情况下,则会按照配置文件中指定的名称来命名网卡;
    2. 如果用户自定义了rules文件,放在/etc/udev/rules.d/目录下,则这个优先级是最高的;比1中ifcfg-xx方式优先级更高,但是如果两者不一致,则在重启network服务时,会依据ifcfg-xx,所以用户不应该同时采用里两种方式给同一个网卡命不同的名称;

    四、内核启动参数biosdevnane、net.ifnames

    默认就是内核启动参数没有biosdevname 也没有net.ifnames 参数(其实默认是net.ifnames=1,biosdevname=0)这种情况下就按照一 中进行网卡命名;eno-ens-enp的方式逐个匹配。但是如果使能了biosdevname.则会使用biosdevname的命名 step1没有命名的网卡;

    bios命名规则:

    要么是em开头,要么是p开头;

    怎么样使能biosdevname呢?2个条件,安装biosdevname包,且在内核启动参数中明确 biosdevname=1. 否则使能不了;

    但是不管怎么样,如果用户自定义了udev rules,则用户自定义的rules优先!

    这是总述,但凡用户自定义rules,优先级最高;

    内核启动参数net.ifname,

    如果在启动参数中增加net.ifname=0,这个文件会在/lib/udev/rule.d/80-net-name-slot.rules体现使用价值,则告诉系统不用scheme的方式来命名,这个时候,会恢复ethx这种不确定性的命名方式;

    五、 不要用ethX去命名

    内核在boot 过程是默认使用ethX方式来命名的,每次启动的时候都不确定,启动会后再通过udev等方式去rename,

    参考

    转载请注明:爱开源 » CentOS 7 CentOS 8 网卡命名规则

  • CentOS 8.x 和 RHEL 8.x 更改默认启动项

    CentOS 8.x 和 RHEL 8.x 更改默认启动项

    CentOS 7内核升级后内核启动顺序的更改
    CentOS 8.x 和 RHEL 8.x 更改默认启动项

    当前默认启动 “CentOS Linux (4.18.0-80.7.1.el8_0.x86_64) 8 (Core)”
    如何修改使用 “CentOS Linux (4.18.0-80.11.2.el8_0.x86_64) 8 (Core)” 启动

    安装 grubby

    [root@aikaiyuan ~]# dnf install grubby
    

    一般默认都以安装

    查看默认启动项

    [root@aikaiyuan ~]# grubby --default-kernel
    /boot/vmlinuz-4.18.0-80.7.1.el8_0.x86_64
    

    查看所有内核

    [root@aikaiyuan ~]# grubby --info=ALL
    index=0
    kernel="/boot/vmlinuz-4.18.0-80.11.2.el8_0.x86_64"
    args="ro crashkernel=auto resume=UUID=b9b14ba1-0b5c-49ac-842f-f11fa2081cfd console=ttyS0 $tuned_params"
    root="UUID=3db5c437-b4f7-46cf-a20e-0345459003f3"
    initrd="/boot/initramfs-4.18.0-80.11.2.el8_0.x86_64.img $tuned_initrd"
    title="CentOS Linux (4.18.0-80.11.2.el8_0.x86_64) 8 (Core)"
    id="f56bd0e5ce8b45e594c3fb6d1753d61d-4.18.0-80.11.2.el8_0.x86_64"
    index=1
    kernel="/boot/vmlinuz-4.18.0-80.7.1.el8_0.x86_64"
    args="ro crashkernel=auto resume=UUID=b9b14ba1-0b5c-49ac-842f-f11fa2081cfd console=ttyS0 $tuned_params"
    root="UUID=3db5c437-b4f7-46cf-a20e-0345459003f3"
    initrd="/boot/initramfs-4.18.0-80.7.1.el8_0.x86_64.img $tuned_initrd"
    title="CentOS Linux (4.18.0-80.7.1.el8_0.x86_64) 8 (Core)"
    id="f56bd0e5ce8b45e594c3fb6d1753d61d-4.18.0-80.7.1.el8_0.x86_64"
    index=2
    kernel="/boot/vmlinuz-4.18.0-80.el8.x86_64"
    args="ro crashkernel=auto resume=UUID=b9b14ba1-0b5c-49ac-842f-f11fa2081cfd console=ttyS0 $tuned_params"
    root="UUID=3db5c437-b4f7-46cf-a20e-0345459003f3"
    initrd="/boot/initramfs-4.18.0-80.el8.x86_64.img $tuned_initrd"
    title="CentOS Linux (4.18.0-80.el8.x86_64) 8 (Core)"
    id="f56bd0e5ce8b45e594c3fb6d1753d61d-4.18.0-80.el8.x86_64"
    index=3
    kernel="/boot/vmlinuz-0-rescue-f56bd0e5ce8b45e594c3fb6d1753d61d"
    args="ro crashkernel=auto resume=UUID=b9b14ba1-0b5c-49ac-842f-f11fa2081cfd console=ttyS0"
    root="UUID=3db5c437-b4f7-46cf-a20e-0345459003f3"
    initrd="/boot/initramfs-0-rescue-f56bd0e5ce8b45e594c3fb6d1753d61d.img"
    title="CentOS Linux (0-rescue-f56bd0e5ce8b45e594c3fb6d1753d61d) 8 (Core)"
    id="f56bd0e5ce8b45e594c3fb6d1753d61d-0-rescue"
    

    查看指定内核启动项

    [root@aikaiyuan ~]# grubby --info=/boot/vmlinuz-4.18.0-80.7.1.el8_0.x86_64
    index=1
    kernel="/boot/vmlinuz-4.18.0-80.7.1.el8_0.x86_64"
    args="ro crashkernel=auto resume=UUID=b9b14ba1-0b5c-49ac-842f-f11fa2081cfd console=ttyS0 $tuned_params"
    root="UUID=3db5c437-b4f7-46cf-a20e-0345459003f3"
    initrd="/boot/initramfs-4.18.0-80.7.1.el8_0.x86_64.img $tuned_initrd"
    title="CentOS Linux (4.18.0-80.7.1.el8_0.x86_64) 8 (Core)"
    id="f56bd0e5ce8b45e594c3fb6d1753d61d-4.18.0-80.7.1.el8_0.x86_64"
    

    修改默认启动

    [root@aikaiyuan ~]# grubby --set-default /boot/vmlinuz-4.18.0-80.11.2.el8_0.x86_64
    The default is /boot/loader/entries/f56bd0e5ce8b45e594c3fb6d1753d61d-4.18.0-80.11.2.el8_0.x86_64.conf with index 0 and kernel /boot/vmlinuz-4.18.0-80.11.2.el8_0.x86_64
    [root@aikaiyuan ~]# grubby --default-kernel
    /boot/vmlinuz-4.18.0-80.11.2.el8_0.x86_64
    

    修改内核启动项参数

    [root@aikaiyuan ~]# grubby --update-kernel=/boot/vmlinuz-4.18.0-80.7.1.el8_0.x86_64 --args=console=ttyS0,115200
    
    [root@aikaiyuan ~]# grubby --info=/boot/vmlinuz-4.18.0-80.7.1.el8_0.x86_64
    index=1
    kernel="/boot/vmlinuz-4.18.0-80.7.1.el8_0.x86_64"
    args="ro crashkernel=auto resume=UUID=b9b14ba1-0b5c-49ac-842f-f11fa2081cfd $tuned_params console=ttyS0,115200"
    root="UUID=3db5c437-b4f7-46cf-a20e-0345459003f3"
    initrd="/boot/initramfs-4.18.0-80.7.1.el8_0.x86_64.img $tuned_initrd"
    title="CentOS Linux (4.18.0-80.7.1.el8_0.x86_64) 8 (Core)"
    id="f56bd0e5ce8b45e594c3fb6d1753d61d-4.18.0-80.7.1.el8_0.x86_64"
    

    –update-kernel=/boot/vmlinuz-4.18.0-80.7.1.el8_0.x86_64
    –update-kernel=ALL 也可以更新 所有内核
    console=ttyS0,115200

    转载请注明:爱开源 » CentOS 8.x 和 RHEL 8.x 更改默认启动项

  • ICMP报文如何通过NAT来地址转换

    ICMP报文如何通过NAT来地址转换

    • 设备A: 192.168.1.100
    • 设备B: 192.168.1.200
    • NAT设备: 192.168.1.1 123.123.123.123

    如果A和B都想ping 114.114.114.114,
    大家都知道ping是基于ICMP的,是没有端口的,那么这样是怎么来实现的呢???

    没有端口,那就创造端口,首先ICMP的报文格式如下

    在A发送ICMP报文的时候,会根据(Type+Code)的值生成源端口号,根据Identifier的值生成目的端口号,即发送到路由器的报文如下:

    源报文:

    源IP 源端口 目的IP 目的端口
    192.168.1.100 (Type+Code) 114.114.114.114 Identifier

    在路由器上进行SNAT,源IP更改后ICMP报文中的Identifier会改变,记作IDENTIFIER。这时候的报文如下:

    源IP 源端口 目的IP 目的端口
    123.123.123.123 IDENTIFIER 114.114.114.114 Identifier

    Nat表

    源IP 源端口 协议 目的IP 目的端口
    192.168.1.100 (Type+Code) ICMP 123.123.123.123 IDENTIFIER

    在web服务器C收到ICMP请求后,生成ICMP响应报文,响应报文中的(Type+Code)会作为源端口,IDENTIFIER作为目的端口

    源报文

    源IP 源端口 目的IP 目的端口
    114.114.114.114 (Type+Code) 123.123.123.123 IDENTIFIER

    报文到达路由器后,根据NAT表中,查询目的IP和目的端口为123.123.123.123和IDENTIFIER的信息。将目的IP和目的端口换为

    192.168.1.100 和(Type+Code),这样报文就可以成功的到达A了。

    所以ICMP报文的NAT大致是根据ICMP报文的字段,形成伪端口,然后根据TCP报文的流程来处理。

    以上是个人查阅资料后总结,有不正确的,还请指出。

    转载请注明:爱开源 » ICMP报文如何通过NAT来地址转换

  • 磁盘性能测试 ioping 命令

    https://github.com/koct9i/ioping

    ioping

    一个实时显示磁盘io延时的工具,以类似ping 的输出一样展示输出结果
    常用参数:

    -c count
        stop after count requests.
    -i interval
        Set time between requests to interval(Default 1s).
    -l 速度
        default size(-s size)/speed = interval(-i)
        如果size=4k 如果要实现80iops则-l 320k
    -L 顺序,同时每次操作块大小会变成256k.(即-s 256k)
    -D Derect IO
    -s size
        指定请求数据块的大小(默认:4k)
        4k时那么平均每次读写的扇区就是8个
    -S wsize
        指定工作路径的大小,如果不指定,默认是1m的,也就是io会只在这个1m的块上执行,指定该参数执行ioping会先创建一个指定大小的块文件,再开始读写。
    -W 写io。会从0磁道开始写,要与-WWW一起使用。
    -G 混合读写
    -k 在使用目录做测试时,保留ioping.tmp(-S 创建的文件,默认会完成测试后自动删除)。
    -Y sync IO
    

    把要测试的盘挂载到一个目录比如/test,cd /test开始测试

    测试4k随机写(写测试必须使用目录或者文件)

    ioping -W -WWW -S 1G -D -c 100 .
    

    测试顺序读(读可以测试设备)

    ioping -L -D -S 1G -c 100 .
    

    以下是man page方法:

    简单用法:

    使用默认值和当前目录显示磁盘I / O延迟,直到被中断

    [root@node-1 ops]# ioping -D /dev/sda
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=1 time=56.1 ms (warmup)
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=2 time=8.89 ms
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=3 time=9.45 ms
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=4 time=5.37 ms
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=5 time=5.34 ms
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=6 time=7.24 ms
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=7 time=2.62 ms (fast)
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=8 time=8.16 ms
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=9 time=10.2 ms (slow)
    4 KiB <<< /dev/sda (block device 557.9 GiB): request=10 time=7.02 ms
    ^C
    --- /dev/sda (block device 557.9 GiB) ioping statistics ---
    9 requests completed in 64.3 ms, 36 KiB read, 140 iops, 560.3 KiB/s
    generated 10 requests in 9.11 s, 40 KiB, 1 iops, 4.39 KiB/s
    min/avg/max/mdev = 2.62 ms / 7.14 ms / 10.2 ms / 2.24 ms
    

    测量磁盘搜索率(iops,avg)

    $ ioping -R /dev/sda
    
    --- /dev/sda (device 465.8 GiB) ioping statistics ---
    186 requests completed in 3004.6 ms, 62 iops, 0.2 MiB/s
    min/avg/max/mdev = 6.4/16.0/26.8/4.7 ms
    

    测量磁盘顺序速度(MiB / s)

    $ ioping -RL /dev/sda
    
    --- /dev/sda (device 465.8 GiB) ioping statistics ---
    837 requests completed in 3004.1 ms, 292 iops, 72.9 MiB/s
    min/avg/max/mdev = 2.0/3.4/28.9/2.0 ms
    

    获取磁盘每秒顺序速度(bytes)

    [root@node-1 ops]# ioping -RLB . | awk '{printf "%s MB\n",$4/1024/1024}'
    1129.74 MB
    

    raw 统计

    ioping -p 100 -c 200 -i 0 -q .
           100 26694 3746 15344272 188 267 1923 228 100 26694
           100 24165 4138 16950134 190 242 2348 214 100 24165
           (1) (2)   (3)  (4)      (5) (6) (7)  (8) (9) (10)
    
           (1) 请求次数统计
           (2) 运行时间         (usec)
           (3) 每秒的请求次数  (iops)
           (4) 传输速度       (bytes/sec)
           (5) 最低的请求时长 (usec)
           (6) 平均请求时长 (usec)
           (7) 最大的请求时长 (usec)
           (8) request time standard deviation (usec)
           (9) 总的请求数       (including too slow and too fast)
           (10) 总的运行时长  (usec)
    

    名词解释

    tps: 每秒接收的I/O请求数,等于r/s + w/s
    avgrq-sz: 平均每次io请求扇区数
    avgqu-sz: 平均每次io等待队列数
    maxsect: max sectors per request
    通过blockdev –getmaxsect /dev/sdx获取,sas默认值512,sata默认值128
    sector: 扇区,每个扇区512Bytes,1k=2sect
    iops: 每秒的io次数
    此次测试使用的硬盘为sas 10k, iops为140, 平均io time/per为14ms

    写测试实例

    同步IO写

    测试一:

    ioping -DWWW -S 1G -s 4k -l 560k .
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4          0.00     0.00    0.00  140.00     0.00     0.55     8.00     0.02    0.15    0.00    0.15   0.15   2.10
    

    扇区达到8之后,tps、avgrq、avgqu和await符合预期

    测试二:

    ioping -DWWW -S 1g -s 256k -l 35m .
    04/20/2019 03:07:59 PM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  140.00     0.00    35.00   512.00     0.03    0.20    0.00    0.20   0.20   2.80
    Note:
    

    扇区达到512后,符合预期
    size为256k时,刚好avgrq为512个sector;
    此时tps = 35m / 256k = 140 , 与测试结果w/s相符,也于10k sas盘的iops参数相符;
    观察此时avgqu为0.04,几乎没有队列等待, iops = 140 / (1 + 0.04) = 134;
    w_wait: 0.29;
    且util值为4%,接近0;
    可以认为此时是硬盘的最佳io处理状态,可以作为基准状态;

    测试三:

    ioping -DWWW -S 1g -s 256k -l 70m .
    正常的盘:
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  280.00     0.00    70.00   512.00     0.05    0.18    0.00    0.18   0.17   4.80
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdc1           0.00     0.00    0.00  153.00     0.00    38.25   512.00     0.95    6.21    0.00    6.21   6.19  94.70
    Note:
    

    稳定后,wMB/s和avgrq达到参数值后,也符合预期,此时如果wMB达不到参数值的话就会增加util,并tps也会达不到预期。
    正常的盘和异常的盘在这个压力下,已经显现了差距
    size不变,增加数据量及加快给数据的速度,speed为70m,此时util开始接近100%;
    此时计算tps = 70m / 256 k = 280 ,与实际测出结果有一定差距,
    但是此时avgqu-sz已经达到0.95,接近1,
    根据avgqu,计算iops ≈ 280 / (1 + 0.95) = 143 接近153;
    w_wait: 6.21有所增加,但是依然符合io time;
    再增加speed,后实际结果也没有大的变化,只增加这个值此时已经没有测试效果;

    测试四:

    增加size

    ioping -DWWW -S 1g -s 512k -l 35m .
    iostat输出:
    正常的盘:
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  140.00     0.00    35.00   512.00     0.02    0.16    0.00    0.16   0.09   1.20
    异常的盘
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdc1           0.00     0.00    0.00  140.00     0.00    35.00   512.00     0.06    0.42    0.00    0.42   0.24   3.40
    Note:
    

    wMB/s和avgrq达到参数值后,符合预期
    低压力的情况下,正常的盘和异常的盘区别不大
    size为512k=1024sector,为测试一的两倍,也就是每次request都要分成两次完成,因为每次是512个sector;
    计算tps = 35m / 512k = 70 , 但是结果是140, 结合size,那么新的tps计算方法就应该是: tps = speed / size × (size_k 2 /maxsect)
    tps = 35
    1024 / 512 (512 2 / 512) = 140
    avgqu-sz: 0.06
    w_wait: 0.42;
    数据总量不变的情况下,增加request的size,会增加tps,并保持io处理能力不下降。

    测试五:

    ioping -DWWW -S 1g -s 512k -l 70m .
    正常的盘:
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  280.00     0.00    70.00   512.00     0.05    0.17    0.00    0.17   0.11   3.00
    异常的盘:
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdc1           0.00     0.00    0.00  220.00     0.00    55.00   512.00     1.44    6.52    0.00    6.52   4.15  91.20
    Note:
    

    正常的盘在wMB/s avgrq达到参数值后符合预期,如果达不到参数值则会出现iops降低,util增加和avgqu增加,以及await增加
    异常的盘已经基本上达不到参数值了
    size: 512k
    计算tps: 70 1024 / 512 2 = 280, 与实际测试的值略有差距;
    avgqu: 1.44 , 根据avgqu 没有avgqu时的tps = 280 / (1 + 1.44) = 114;
    此时w_wait: 6.52,处于合理状态的范围;

    测试六:

    ioping -DWWW  -S 1g -s 5m -l 150m .
    正常的盘:
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  600.00     0.00   150.00   512.00     1.07    1.79    0.00    1.79   0.14   8.30
    异常的盘:
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdc1           0.00     0.00    0.00  460.00     0.00   115.00   512.00     9.31   20.33    0.00   20.33   1.99  91.60
    Note:
    

    此时正常的盘,达到参数值后,依然符合预期,而异常的盘已经远远达不到了。
    size: 5m
    计算tps: 150 / 50 (5 1024 * 2 / 512) = 600
    由于有avgqu值偏大,此时已经不具有生产使用意义

    测试名称 size speed 测试tps 计算tps avgqu-sz wait util MB/s
    256k 35m 140 140 0.04 0.29 4% 35
    256k 70m 153 280 0.95 6.21 94.7% 38.25
    512k 35m 140 140 0.06 0.42 3.4% 35
    512k 70m 220 280 1.44 6.52 91.2% 55
    5m 150m 460 600 9.31 20.33 91.6% 115

    当size为256k时 avgrq-sz就已经等于maxsect,此时增加-l speed的值并不能提升iops了,只能增加-s的size,
    而增加size必然会带来增加avgqu-sz即等待队列,也就会导致wait上升.

    10k的sas的iops为140,此时140256k = 140/4m = 35m 此时-l 35m,基本上就是硬盘最高繁忙度了util接近100%,此时要降低util,就必须增加-s的size(增加了等待的队列,也可以理解是增加了io通道或者iodepth), 比如size=512k,此时util降低一半,tps=35m/0.5m2 =140

    io供给速度快时,util增加的情况下,tps就达不到计算的结果。

    读测试实例

    ioping -D -S 100g -s 4m -l 160m /dev/sdc1
    iostat输出
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdc1           0.00     0.00  486.00    0.00   121.50     0.00   512.00     9.66   19.78   19.78    0.00   2.04  99.30
    

    此时看wait开始增加到较高的值了,且avgqu-sz已经很高了。
    磁盘测试可以根据计算的方式获取预期的瓶颈范围
    avgqu-sz开始接近1的时候就是盘的性能最佳状态。
    即最佳状态为-s 256k -l 35m此时tps 140 util接近100%
    磁盘在等待队列avgqu-sz <= 4的情况下处于较好的状态,最终获取最大承受范围约 -s 1.5m -l 150m,此时承载能里达到最大承载临界值。(队列avgqu-sz每增加1几乎tps就增加一倍)

    04/19/2019 12:03:34 AM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdc1           0.00     0.00  388.00    0.00    97.00     0.00   512.00     4.32   11.20   11.20    0.00   2.56  99.50
    
    04/19/2019 12:03:35 AM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdc1           0.00     0.00  370.00    0.00    92.50     0.00   512.00     4.37   11.83   11.83    0.00   2.68  99.10
    

    异步IO 写

    测试一:

    ioping -ADWWW -S 1g -s 4k -l 560k .
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  140.00     0.00     0.55     8.00     0.00    0.01    0.00    0.01   0.01   0.20
    

    wMB/s和 avgrq达到预期后,其他的输出都符合预期

    ioping -AD -W -WWW -S 1G -s 256k -l 35m .
    04/20/2019 02:42:57 PM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  140.00     0.00    35.00   512.00     0.02    0.16    0.00    0.16   0.16   2.20
    

    符合预期

    ioping -AD -W -WWW -S 1G -s 256k -l 70m .
    04/20/2019 02:46:11 PM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  280.00     0.00    70.00   512.00     0.05    0.17    0.00    0.17   0.17   4.90
    

    开始阶段avgrq只能到达256,此时iops为500左右
    异步io的util不高

    ioping -AD -W -WWW -S 1G -s 512k -l 35m .
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  140.00     0.00    35.00   512.00     0.03    0.21    0.00    0.21   0.11   1.60
    

    表现与sync io一样,此时iops一致

    ioping -AD -W -WWW -S 1G -s 512k -l 70m .
    04/20/2019 02:50:49 PM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  280.00     0.00    70.00   512.00     0.07    0.26    0.00    0.26   0.14   3.90
    

    符合预期

    ioping -AD -W -WWW -S 1G -s 512k -l 140m .
    
    04/20/2019 02:52:43 PM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  542.00     0.00   135.50   512.00     0.21    0.39    0.00    0.39   0.24  12.80
    
    04/20/2019 02:52:44 PM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  440.00     0.00   110.00   512.00     0.85    1.93    0.00    1.93   1.43  62.80
    

    数据量增大后,tps就很难稳定了

    ioping -AD -W -WWW -S 1G -s 2m -l 140m .
    04/20/2019 02:54:11 PM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     3.00    0.00  623.00     0.00   140.20   460.88     0.44    0.70    0.00    0.70   0.12   7.50
    ioping -AD -W -WWW -S 1G -s 5m -l 140m .
    04/20/2019 02:55:19 PM
    Device:      rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sdb4           0.00     0.00    0.00  540.00     0.00   135.00   512.00     2.54    4.71    0.00    4.71   0.29  15.40
    

    异步IO读

    转载请注明:爱开源 » 磁盘性能测试 ioping 命令

  • Go语言Socket编程

    大部分底层网络的编程都离不开socket编程。HTTP编程、Web开发、IM通信、视频流传输的底层都是socket编程。关于socket编程的基础知识参考TCP/IP协议栈的相关知识。

    socket源于Unix,C语言世界中的socket编程。Python采用C语言实现,其自带的socket接口可以看作是Unix socket的OOP风格的socket编程接口。大致的过程如下:

    服务器端:

    1. 创建套接字
    2. 绑定地址
    3. 设置监听队列
    4. 监听请求
    5. 处理请求
    6. 关闭套接字

    客户端:

    1. 创建套接字
    2. 连接服务器
    3. 发送数据
    4. 接收数据
    5. 关闭套接字

    但Go语言采用一套新的接口,该接口比Unix中的socket简介多。由于Golang的静态编译,使用Golang编写的socket网络工具使用起来很方便。

    本文先从TCP socket编程开始,然后到UDP socket,最后以一个简单的socket工具作为结尾。

    TCP Socket

    Golang net包中TCPConn用来建立TCP客户端、TCP服务器端间的通信通道。类似于Python中的socket对象(通过socket.socket创建)通过DialTCP函数创建该对象。TCPListener服务器端socket,监听网络请求,通过ListenTCP函数创建该对象。形象地理解,可以把TCPConn看作是TCP的连接器;TCPListener看作是TCP监听器。监听器等待客户端连接,一旦有连接进来,创建TCP连接器,然后通过TCP连接器进行服务器端和客户端的通信。

    下面通过TCP心跳(返回服务器端时间)来举例,编程中还有一些细节问题,这里不详细说,看代码注释。

    TCP Server

    TCP服务器端通过ListenTCP创建TCPListener对象。调用Accept方法进入LISTEN状态(参考TCP状态机)

    编写tcp_tick_time.go代码。

    package main
    import (
        "fmt"
        "log"
        "net"
        "os"
        "time"
    )
    func echo(conn *net.TCPConn) {
        tick := time.Tick(5 * time.Second) // 五秒的心跳间隔
        for now := range tick {
            n, err := conn.Write([]byte(now.String()))
            if err != nil {
                log.Println(err)
                conn.Close()
                return
            }
            fmt.Printf("send %d bytes to %s\n", n, conn.RemoteAddr())
        }
    }
    func main() {
        address := net.TCPAddr{
            IP:   net.ParseIP("127.0.0.1"), // 把字符串IP地址转换为net.IP类型
            Port: 8000,
        }
        listener, err := net.ListenTCP("tcp4", &address) // 创建TCP4服务器端监听器
        if err != nil {
            log.Fatal(err) // Println + os.Exit(1)
        }
        for {
            conn, err := listener.AcceptTCP()
            if err != nil {
                log.Fatal(err) // 错误直接退出
            }
            fmt.Println("remote address:", conn.RemoteAddr())
            go echo(conn)
        }
    }
    

    通过终端直接启动。

    go run tcp_tick_time.go
    

    通过简单的客户端连接,我们可以看到该程序终端的显示信息:

    remote address: 127.0.0.1:1915
    send 37 bytes to 127.0.0.1:1915
    send 37 bytes to 127.0.0.1:1915
    send 37 bytes to 127.0.0.1:1915
    send 35 bytes to 127.0.0.1:1915
    send 37 bytes to 127.0.0.1:1915
    send 37 bytes to 127.0.0.1:1915
    send 37 bytes to 127.0.0.1:1915
    2017/08/29 9:23:49 write tcp4 127.0.0.1:8000->127.0.0.1:1915: wsasend: An established connection was aborted by the software in your host machine.
    send 0 bytes to 127.0.0.1:1915
    

    TCP Client

    通过func DialTCP(net string, laddr, raddr TCPAddr) (TCPConn, error)创建TCP客户端。net需要指定具体的TCP
    网络类型:”tcp”, “tcp4”, “tcp6”。laddr表示本地地址,一般为nil。raddr为要连接的服务器地址。

    我们写一个简单的HTTP客户端。

    package main
    import (
        "net"
        "log"
        "fmt"
        "io/ioutil"
        "os"
    )
    func main() {
        if len(os.Args) != 2 {
        log.Fatalf("Usage: %s host:port", os.Args[0])
        }
        service := os.Args[1]
        tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
        if err != nil {
            log.Fatal(err)
        }
        conn, err := net.DialTCP("tcp4", nil, tcpAddr)
        if err != nil {
            log.Fatal(err)
        }
        n, err := conn.Write([]byte("HEAD / HTTP/1.1\r\n\r\n"))
        if err != nil {
            log.Fatal(err)
        }
    

    完。

    转载请注明:爱开源 » Go语言Socket编程

  • 一次完整的网络请求

    • 一次完整的网络请求这个问题虽然很平凡,但仔细想想它涉及了计算机网络协议栈、操作系统、数据库系统原理、服务器端架构、网络安全…如果还考虑前端渲优化,可能连用户体验、心理学(如何让用户感觉面页加载更快)都用上了….好好想想这个问题,梳理下各个环节。
    1. APP客户端、浏览器端处理、用户代理:协商加密、RSA、AES、HTTP协议、URL处理、请求头构造、表单构造、前端缓存、Ajax、域名缓存TTL
    2. DNS、DNS-poll、hosts文件
    3. 操作系统层面,系统级I/O操作:epoll、poll、select、线程并发或进程并发、IO复用、数据从内核空间到用户空间
    4. TCP、三次握手、四次挥手、流量控制、拥塞控制、滑动窗口、超时重传、Nagle算法、长连接、管线化
    5. IP、前置代理、VPN、路由选择算法、BGP、ARP
    6. 链路层、网络接口层、通信原理、差错检测、纠错原理
    7. 服务器端、入侵检测系统、DDoS、SYN Flood、CC Flood、DNS反射、NTP反射、MC反射
    8. 负载均衡、LVS、反向代理、CDN服务器、高可用性、容灾性
    9. HTTP、HTTPS、RESTful、RPC
    10. 应用服务器、子域名、业务应用、业务拆分、robot协议、IP地址访问权限、IP地址访问频次控制、防网络爬虫
    11. 缓存、网络安全、注入攻击、Session、Cookie、用户认证
    12. 数据库操作、搜索引擎、访问日志记录、消息队列、分布式系统、微服务、BASE特性、分布式下的数据一致性处理
    13. MVC架构模式视图、JSON、XML、前后端分离的工程化
    14. 逆着TCP/IP栈、从解包、封装的角度
    15. 前端、HTML、CSS、JavaScript、渲染、用户体验、状态码、重定向、交互设计、多媒体流
    16. 补充:HTTP2.0、websocket、RTC、UDP在各种业务下的使用、解析完毕后的片段定位

    转载请注明:爱开源 » 一次完整的网络请求