linux-防火墙命令

Linux关闭防火墙命令
问题:老是关闭防火墙太麻烦,所以选择彻底关闭防火墙,发现每次都记不住命令!

下面是red hat/CentOs7关闭防火墙的命令!

1:查看防火状态

systemctl status firewalld

service iptables status

2:暂时关闭防火墙

systemctl stop firewalld

service iptables stop

3:永久关闭防火墙

systemctl disable firewalld

chkconfig iptables off

4:重启防火墙

systemctl enable firewalld

service iptables restart

5:永久关闭后重启

//暂时还没有试过

chkconfig iptables on

ipcc-4-批次event排查

前言

有时候我们批次会出现不拨打问题

内容

如果按照以下方式信息都查不出来,直接

1
grep "1999" callnotify_callnotify01_157749*

一些基本的批次排查指令如下:

  1. 1.查找任务呼叫情况
1
grep "callout" callnotify_callnotify01_157673* |grep 1523
  1. 2.查看任务停止
1
grep "end t" callnotify_callnotify01_15759* |grep 2093
  1. 3.查看任务启动
1
grep "beginthreadex notifyid" callnotify_callnotify01_15759* |grep 2093
  1. 4.查任务是否暂停,批次是否在呼叫时间
1
grep "getTaskCallPause" callnotify_callnotify01_15759* |grep 2093
  1. 5.查看任务心跳 非暂停任务 5s会有一次心跳
1
grep "hartbit taskid" callnotify_callnotify01_15759* |grep 2093
  1. 6.查看任务占用通道取名单有值的时候 3s执行一次
1
grep "getnotifychn taskid" callnotify_callnotify01_15759* |grep 2093
  1. 7.计算当前呼出名单数,名单缓冲有值的时候执行 有呼叫通道时候或者超过5s没通道的时候输出
1
grep "getTaskCallNew begin taskid" callnotify_callnotify01_15759* |grep 2093
  1. 8.取不到主叫 无法呼出
1
grep "caller is empty" callnotify_callnotify01_15759* |grep 2093
  1. 9.通道数量不够 无法呼出
1
grep "no idel channel" callnotify_callnotify01_15759* |grep 2093
  1. 10.呼叫失败
1
grep "callout fail" callnotify_callnotify01_15759* |grep 2093
  1. 11.查找僵尸线程
1
grep "thread exit notifyid" callnotify_callnotify01_1577* |grep "wait count\[4\]

title: docker-1-docker基础入门
date: 2019-12-15 08:53:59
tags:

docker

前言

我们基础入门,从以下几方面讲解:
1.什么是docker
2.理解docker
3.走进docker
4.Hello World运行docker
5.Nginx服务
6.docker化Java web

内容

docker官网:https://www.docker.com/

1.什么是docker

1.1 Docker历史
  1. 1.2010年几个年轻人在旧金山成立了做paas平台公司dotCloud,后面由于微软,亚马逊竞争
  2. 2.2013年公司发展受限,又不想之前东西付之东流,docker开源
  3. 3.2014.6 Docker1.0
  4. 4.2014.7 C轮$4000万
  5. 5.2015.4 D轮9500万
  6. 6.至今Docker1.13
1.2 什么是docker
  1. 1.docker是一个装应用的容器,就像杯子可以装水,笔筒可以放笔,你可以把Hello world放在docker里,你可以把网站放到docker里,你可以把你任何想到的程序放到docker里面。
  2. 2.Docker is the world’s leading software containerization platform
  3. 3.Docker公司开发,开源,托管在github上
  4. 4.跨平台、支持Windows、Macos、Linux

2.理解docker

2.1 docker思想

docker的logo是一条鲸鱼驮着很多集装箱;
docker思想体现在:

  1. 1.集装箱(没有集装箱之前运输货物是非常零散,没有规矩,运输过程中某一个东西可能就掉落了,有了集装箱之后,我们的东西装到集装箱里面去了,箱子是密封的,并很大,保证货物安全原样送到目的地,这些货物就是类似于我们的各种程序)
  2. 2.标准化->标准化主要体现在以下3个方面:
    a.传输方式:docker运输程序有一个超级码头,任何一个地方需要货物时候,都是由鲸鱼将获取送到超级码头,然后由鲸鱼将货物从超级码头送到目的地。例子:假如你要把你台式机上面的应用部署到你的笔记本上,一般选择u盘或者qq传输过去,但是docker标准化了这个过程,你要做的只需要在台式机上执行一个docker命令把程序输送到超级码头去;然后在你的笔记本上执行一个docker命令->由鲸鱼把程序从超级码头送到笔记本上去。
    b.存储方式:比如你把程序从台式机拷贝到你笔记本,你还得创建目录,并且记住这个目录,有了docker之后存储方式标准化了你不需要关心程序在哪个目录下,你只需要执行或者停止一个命令就可以了。docker标准化让快速扩展、弹性伸缩变得简单。
    c.API接口标准化:docker提供了一系列api接口,包括了docker对我们应用的控制:查看,删除,停止等等。

  3. 3.隔离:轻量级创建销毁docker,你创建虚拟机可能需要几分钟,但是创建docker只需要1秒。最底层的技术其实是linux的内核限制机制,叫做LXC(轻量级的容器虚拟化技术,最大效率地隔离了进程和资源)

2.2 docker解决了什么问题

docker解决了运行环境不一致导致的问题。

  1. 1.我们本地运行没有问题,线上测试有问题
    很多时候我们开发程序员说我们开发没有问题,但是运维说他那边部署没有问题、测试说就有问题,如果一个应用正常运行需要什么?,比如一个java web应用运行需要什么?
    一般需要:1.最底层的操作系统 2.JDK 3.Tomcat 4.依赖于程序代码和配置文件
    以上任何一个条件多个环境下不一致可能就会导致系统问题;下面docker来了,他把操作系统、JDK、Tomcat、程序放在一个个的集装箱里面再打包放到鲸鱼上,鲸鱼将其运输到服务器上。你机器上怎么运行,他在服务器上也是怎样运行的

  2. 2.系统好卡,哪个人又写死循环了?!
    linux本身就是一个多用户的操作系统,登录的每个人都有可能修改配置,那怎么办呢?用docker,docker的隔离性很好的解决了这个问题。如果把大家的应用程序都放到docker里面运行,就算别人的程序是死循环都不会导致别人的程序?原因是docker启动的时候就限定好了每个程序使用的最大的cpu,内存,硬盘

  3. 3.双11来了,服务器撑不住啦!
    大部分系统每天的业务量并不是平均的,特别是一些电商系统每年总会有那么几天业务量比平时多几倍甚至几十倍。如果按照平时量准备服务器,那么双十一来了肯定撑不住,如果按照双十一规模准备服务器,那么平时就是极大浪费。所以只能在节日前临时扩展机器,过完节给其他服务下线,这给运维带来非常大工作量,节日时候需要在各个服务器上部署各种各样服务,装好只有还不一定能运行,还得调试,这是多么烦躁的事情。使用docker使事情变得好多了,我们只需要点击一下,就可以变成几十台、几百台、几千几万台;

3.走进docker

3.1 docker核心技术

docker里面有3个核心词汇,叫做:仓库(超级码头)、镜像(集装箱)、容器(运行程序的地方)

用docker运行一个程序的过程就是:从仓库,把镜像拉到本地、然后用一条命令把镜像运行起来变成容器

上面图有:build、ship、run
a.build(构建)->构建镜像
b.ship(运输)->运输镜像
c.run(运行)->运行镜像就是个容器

3.2 docker镜像

鲸鱼驮着的集装箱就是一个镜像,镜像本质其实就是文件(应用程序文件、运行环境文件)既然是文件docker是将其保存到本地了,既然保存了,那么是以什么样的格式来保存呢?说到镜像存储格式,就需要提到linux的存储技术叫做联合文件系统:unionfs 是一个分层的文件系统,可以将不同的文件挂载到同一个虚拟文件下

以上可以看到test1和test2下面都有各自的文件,unionfs系统就像test可以看到上面所有文件,类似于把test1看成第一层,test2看做第二层。docker镜像就是利用这种分层实现镜像存储。

docker镜像存储格式如下:

a.最底层是操作系统的引导
b.第二层是linux的操作系统
c.第三层,第四层是我们的应用程序,我们可以控制
d.第五层是容器相关东西,先不管

docker镜像的每一层文件系统都是只读的,然后把每一层加载完成之后,文件都会被看成同一个目录,相当于只有一个文件系统,叫做镜像。

3.3 docker容器
  1. 1.容器的本质就是一个进程,便于理解我们可以把容器看成一个虚拟机。
  2. 2.每个虚拟机都有自己的文件系统

    可以把上面看成是容器的文件系统,和虚拟机的区别是这里的文件系统是一层一层的,并且最下面的四层都是只读的,最上面的一层是可写的,为什么需要可写的呢?大家程序运行起来,势必需要一些日志,一些文件,对系统文件修改。所以创建一个可读可写系统。

如何修改镜像里面可读的文件,因为镜像每一层只读,所以会把镜像可读的文件拷贝到可写的文件一层,然后再对他进行修改,修改之后我们的应用要读一个文件时候,就会从最上层开始查找,如果没有才会找下一层。所以容器是可以修改的,镜像是不可以修改的,这样保证同一个镜像生成不同容器独立运行,并且之间无直接干扰。

3.4 docker仓库
  1. 1.镜像已经构建完了,镜像构建目的是要在其他机器、其他环境运行我们的程序,如果在本机上运行就不需要构建镜像了。构建完之后如果运输到其他环境中去,这里就运用到了docker仓库。我们先把我们的镜像传递到仓库里面去,再由目的地把docker仓库拉过去。这样就完成了这样的传输过程。
  2. 2.谁提供了docker仓库呢?需要有一个中央服务器提供一个地址,让我们去访问,docker自己就提供了这个服务,提供服务的地址就叫:hub.docker.com,但是有一个问题是最开始这个网站是被墙掉的,国内根本访问不了,现在虽然可以访问了,但是加载镜像速度还是很慢,为了解决这个问题,国内很多也在做这个仓库,国内比较著名的是国内一个c.163.com的仓库
  1. 3.以上是共有的镜像中心,假如我们自己的镜像比较私密,不想被其他人看到呢?docker也是支持我们自己搭建一个镜像中心

4.docker安装

4.1 window安装docker

Windows

docker下载地址:
win10: www.docker.com/products/docker#/windows
win10之外:http://www.docker.com/products/docker-toolbox
国内下载地址:http://get.daocloud.io

boot2docker.iso下载地址:
http://pan.baidu.com/s/1qYyc0ag

  1. 1.下载后默认安装

安装完之后,在桌面上会有3个快捷方式,其中Docker Quickstart Terminal是我们启动docker的按钮。

  1. 2.缺包之后,我们从百度云盘去下载:boot2docker.iso下载地址:http://pan.baidu.com/s/1qYyc0ag
    第一次运行可能比较慢

    上面说从github上下载文件失败,因为github是外国网站,所以慢,需要我们自己下载:
    我们现在下载好iso文件后,我们把他存放到:C:\Users\yxm.docker\machine\cache里面的docker文件:

4.2 linux安装docker

Linux
1.Redhat&CentOS:
系统要求:64-bit OS and version 3.10
安装连接:http://www.imooc.com/article/16448

linux下安装完之后,如果执行docker version出现:Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
说明docker服务没有起来。我们需要执行如下指令:

1
systemctl start docker.service

2.Ubuntu:
系统要求:64-bit OS and version 3.10

5.docker实践

5.1 第一个docker镜像

5.1.1 二个命令

第一个初体验就是运行hello world,运行这个的时候,我们需要运行两条命令。

  1. 1.docker pull [OPTIONS] NAME[:TAG]
    a.从docker远程仓库拉取一个镜像到我们本地
    b.NAME表示:拉取镜像的名称 :TAG是可选的,如果不加的话默认会是:latest表示我们镜像的最新版本,如果指定一个tag的话;中间的options是拉取时候的一些参数

  2. 2.docker images [OPTIONS][REPOSITORY[:tag]]
    查看我们本机都有哪些镜像?也可以验证我们pull是否成功了?

5.1.2 具体操作
  1. 1.查看本机所有镜像列表

    我们发现本地没有任何镜像,只打印了每列的列头

  2. 2.拉取hello-world镜像

    a.Using default tag: latest—表示默认拉取最新分支
    b.Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064—摘要
    c.Status: Downloaded newer image for docker.io/hello-world:latest—状态

再使用docker images查看时候,出现如下:
a.REPOSITORY:镜像名称
b.TAG:分支
c.IMAGEID:id标识
d.CREATED:最后修改时间
e:SIZE:镜像大小

  1. 3.2点说明:
    a.我们这里的镜像名称为:hello-world是docker镜像官网限制的
    b.我们pull取镜像的时候,没有填写镜像的地址,他是如何找到的呢?他会默认从docker自己仓库下载:hub.docker.com

5.2 第一个docker容器

我们已经把docker镜像下载下来了,下面我们需要运行docker容器

  1. 1.docker运行指令
1
docker run [OPTIONS] IMAGE[:TAG][COMMAND][ARG...]

以上是docker运行后的输出,指明了docker运行时候经历的4步。

为了形象理解,我们使用一张图表示:


a.上图分为3个部分:Client、DOCKER_HOST、Register
b.client:在我们本机;就是我们终端,执行指令的地方
c.DOCKER_HOST也是在我们本机的Docker daemon
d.Register:Docker的远程仓库

以上执行分析:
1.docker pull:把我们的命令发到docker daemon,docker daemon去找Images镜像,daemon去检查我们本地是否存在对应版本,如果存在直接返回到,如果镜像不存在就去远程仓库去拉取到本地
2.docker run:把我们的命令发到docker daemon,daemon检查镜像在本机是否已经存在,如果不存在,就去远端拉取。存放到本地images,然后产生一个docker容器。

6.docker运行nginx

nginx是一个web服务器,nginx镜像的特点:
1):持久运行的容器
2):前台挂起&后台运行(前台运行我们使用Ctrl+c即可关闭,我们用后端运行)
3):进入容器内部

6.1 docker运行nginx

去网易镜像中心查看:https://c.163.com/hub#/home

  1. 1.拉取镜像:hub.c.163.com/library/nginx:latest

  2. 2.运行镜像:
    前台运行镜像:docker run hub.c.163.com/library/nginx

我们发现没有什么反应:我们打开另一个终端,查看下docker运行的进程
docker ps

从上面可以看出我们的docker已经运行了,说明上面是前台运行

通过:docker run –help:查看docker run有哪些参数
后台启动:docker run -d

id:656dea8798aefb5699df96f623835d6df34b2c839de1876efe9842052bfb5757

  1. 3.查看容器内部结构
    容器已经运行起来了,我们如何查看容器内部的结构呢?我们有时候需要看下运行的容器是否正常,内部日志等。

docker exec –help

我们一般用到的是-i和-t参数,一般是可以合并的。

进入自带的镜像目录:

6.2 docker的网络

上面我们已经用docker运行了一个nginx,但是我们还没有在浏览器访问nginx,这一章节我们看下docker的网络,然后从浏览器上访问下nginx

6.2.1 docker网络类型
  1. 1.网络也是隔离性一部分,linux使用namespace来实现隔离的,pid namespace就是用来隔离进程的,mount namespace就是用来隔离文件系统的,network namespace就是用来隔离网络的,每一个network namespace都提供了独立的网络环境(包括:网卡、路由等)

  2. 2.docker容器默认情况下会分配默认的独立的network namespace也就是网络类型中的:Bridge模式 还有一种Host模式(如果启动时候使用Host模式,那么这个容器将不会获得独立的network namespace而是和主机共同使用一个,这个时候容器将不会虚拟出自己网卡,ip等,而是会使用宿主机上的ip和port,也就是在docker里面使用网络和在主机上使用网络没有区别的 还有一种网络类型是没有网络:none;这种情况docker将不会和外界任何东西进行通讯)

  3. 3.Bridge模式时候涉及到,既然是独立的network namespace,这就需要一种技术:这就需要容器内部的端口可以在主机上访问到,这种技术就是端口映射,docker可以实现容器内部端口和容器所在的主机上端口进行映射,也就是访问主机里面这个端口就是访问容器里面的端口;

  4. 4.docker网络模式图:

    a.host模式(最左边):eth0是我们主机网卡,host模式时候,容器会直接连接到主机的网卡上,跟主机使用同一块网卡,所以说容器内看到的网络和主机看到的网络是一样的。
    b.Bridge模式(中间):首先会创建一个docker0的网桥,这个网桥跟主机eth0相连接,使用同一块网卡,所以说启动容器的时候,容器内部会虚拟出一个容器内部的虚拟网卡跟网桥相连通过这种方式docker与主机进行通信,这种情况容器里面会有自己独有的ip、port;端口映射的过程:在主机上有一个端口80,通过访问80端口会到主机的eth0网卡,通过这个网卡,会访问到

SpringCloud-10-服务追踪

服务追踪,我们使用SpringCloudSleuth和Zipkin做服务追踪

前言

有时候,我们订单服务创建订单时候耗时很严重

以上订单花费了2.2秒,耗时很严重。到底问题出现在哪里呢?可能是下单时候调用product服务获取商品信息时候耗时比较严重。也可能是扣库存地方耗时比较严重,那我们如何确认是哪个接口耗时比较严重呢?一般我们是通过计时:在调用之前计时,在调用之后计时,这样就得出结论来了。假设已经定位出问题是调用商品服务返回商品信息耗时严重,此时我们就会通知此接口开发者解决,但是获取商品信息接口又是调用了其他服务,

就像上面的服务:A调用B,B调用C,这是一整套链路,当服务调用越来越多,链路越来越长时候,通过日志计时打点效率非常低而且排查起来不方便,这就牵涉到服务追踪。我们要做的其实就是链路监控。

10.1 服务追踪

针对于链路监控,SpringCloud提供了非常方便的组件:Spring Cloud Sleuth,Sleuth是侦查,链路监控这一章节,要写的东西并不多,主要是要会看。

10.1.1 使用SpringCloudSleuth

  1. 1.引入依赖
1
2
  1. 2.使用postman请求:

    从上图我们知道:
    a.第一列:order->代表order服务
    b.第二列:代表traceId(链路id);一条链路里面最多包含一个id,也就是说traceId是一条链路的唯一标识。
    c.第三列:spanId,是一个基本单元;一条链路里面可以包含多个spanid,spanid可以理解成最基本的工作单元。
    d.第四列:true表示要把这些信息输出到其他服务搜集和展示,false就是不搜集。

我们现在在本地配置文件中将日志级别改为debug模式

1
2
3
logging:
level:
org.springframework.cloud.openfeign: debug

此时展示出更多的日志:

2019-12-15 08:15:41.058 DEBUG [order,dc93086b3bb2856a,eec9e8de8adb4274,false] 16616 --- [strix-product-2] o.s.c.openfeign.support.SpringEncoder    : Writing [[DecreaseStockInput{productId='157875227953464068', productQuantity=2}]] using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@d43328]
Hibernate: select ordermaste0_.order_id as order_id1_1_0_, ordermaste0_.buyer_address as buyer_ad2_1_0_, ordermaste0_.buyer_name as buyer_na3_1_0_, ordermaste0_.buyer_openid as buyer_op4_1_0_, ordermaste0_.buyer_phone as buyer_ph5_1_0_, ordermaste0_.create_time as create_t6_1_0_, ordermaste0_.order_amount as order_am7_1_0_, ordermaste0_.order_status as order_st8_1_0_, ordermaste0_.pay_status as pay_stat9_1_0_, ordermaste0_.update_time as update_10_1_0_ from order_master ordermaste0_ where ordermaste0_.order_id=?

一条链路请求里面只有1个reaceId,order服务是调用product服务的,那么product服务是否也是拥有此traceId,我们在product服务也加上服务追踪的sleuth

我们用postman再次请求1次:

现在指标已经出来了,但是我们不可能一直在控制台上看,我们需要友好的,有计划的展示出来。这里我们用到Zipkin框架展示。

10.1.1 使用Zipkin

访问官网:https://zipkin.io/

SpringCloud-9-服务容错

9.1 服务容错和Hystrix

  1. 1.雪崩效应:在微服务架构中,通常会有多个服务层调用,如果某个服务不可用,导致几连故障,造成整个系统不可用的情况。

    如上所示:服务A调用服务B,服务B调用服务C。当服务C发生故障时候,服务B调用不通服务C,则B发生故障,由于服务A也调用服务B,服务A调用不通服务B时候,会采取多次重连,同步等待会造成资源耗尽,则服务A也故障。最后都不可用。

  2. 2.SpringCloud家族中防雪崩的利器就是:SpringCloud Hystrix,它是基于Netflix的开源框架(Hystrix的中文意思是豪猪:defend you app);Hystrix目的就是给微服务提供一系列服务容错保护机制;还记得Eureka的意思吗?Eureka就是找到了,也就是服务注册中心

  3. 3.Spring Cloud Hystrix具有如下功能:
    a.服务降级 b.依赖隔离 c.服务熔断 d.监控(Hystrix Dashboard)

9.1.1 服务降级

比如双十一时候,刷新网站时候会出现”哎呦喂,被挤爆了”,还有秒杀的时候,某些app提示网络开小差,请稍后再试,诸如此类问题,服务降级知道思想是要区分业务,具体是:

  1. 1.优先核心服务,非核心服务不可用或弱可用。
    (比如在订单,商品微服务中:买家查询是核心服务,卖家查询是弱可用服务,我们需要优先保证买家查询服务)
  2. 2.在应用层面,使用服务降级很简单,通过HystrixCommand注解制定。在fallbackMethod(回退函数)中具体实现降级逻辑。

9.2 触发降级

在order服务中有一个create接口调用商品服务代码块

我们将其拎出来

我们单独在order服务的controller包中创建一个:HystrixController类,然后在里面使用restTemplate

然后通过浏览器请求:

我们此时关掉product服务,然后再次请求:发现连接被拒绝:

9.2.1服务降级应用搭建

我们这个时候使用Hystrix用作服务降级,然后就是老套路了

  1. 1.引入依赖:(order-server的pom.xml文件中)
1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

然后刷新一下:maven

  1. 2.在启动类中加入注解:@EnableCircuitBreaker
    此时我们发现在启动类上:OrderApplication有很多注解,这个时候,我们再看一个注解:@SpringCloudApplication
1
2
3
4
5
6
7
8
9
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

其实SpringCloudApplication可以替换上面 3个注解

  1. 3.在请求的HystrixController类的方法中加入注解:

浏览器测试输入:

当被调用的server端不能正常提供服务时候,我们换一个思路,被请求的服务不是client端调用server端的代码,而是抛出一个异常:


以上情况说明:降级不一定用在这种场景:被调用的server端不能正常提供服务了,触发降级,我们也可以用在我们自己服务内部来触发降级(比如:自己服务内部抛出异常,内部服务并发数太高,或者数据库连接数太多时候,我们抛出一个异常)

9.2 超时设置

以上就调用了一个fallback方法,那么如果我们有很多业务逻辑都需要处理的话,是不是都需要降级呢?这样写会不会很麻烦,其实SpringCloud提供了一个在类型注解默认的fallback方法:

1
@DefaultProperties(defaultFallback = "defaultFallback")

联系之前我们的介绍,比如我们上面getProductInfoList方法是我们核心业务的方法,比如就是买家查询商品时候,我们需要优先保证其正常使用,使用注解,自定义特殊的降级处理逻辑fallback,但是此时fallback中50%的概率是可以正常处理的,其他方法是非核心业务,统一的降级策略就是直接回到了一个静态页面之类。更多的场景其实要注意服务的时间,也就是超时的问题。比如我们在product服务中根据商品id查询商品时候,我们让其睡眠2秒。

我们在浏览器访问order服务获取商品接口:

其实我们可以在HystrixCommand里面设置超时时间。
我们进入源码发现其配置的默认超时时间是1秒
点击注解:@HystrixProperty 再点击:package com.netflix.hystrix.contrib.javanica.annotation;然后我们看到左边的源码:HystrixCommandProperties属性配置

默认1秒,所以控制台请求响应一般为1秒左右,那我们该如何配置呢?在类中搜索一下:default_executionTimeoutInMilliseconds

然后我们设置getProductInfoList个超时时间为4秒

然后我们在浏览器请求:

超时时间配置很重要,具体超时时间设置需要看调用方和具体业务,比如有些场景请求到第三方:开发、充值等需要将超时时间设置为长一些。

9.4 依赖隔离

  1. 1.线程池隔离(依赖隔离)
    SpringCloud Hystrix的依赖隔离类似于docker的”舱壁模式”;docker通过”舱壁模式”实现进程隔离,使得容器之间互不影响,而Hystrix使用该模式实现:“线程池隔离”;会为每一个HystrixCommand创建一个独立线程池,这样就算某个在Hystrix包装下的依赖服务出现延迟过高情况,也只是对该依赖服务的调用产生影响,并不会拖慢其他服务,使用HystrixCommand来将某个函数包装成了Hystrix命令时候,Hystrix框架自动地为这个函数实现了依赖隔离。所以依赖隔离,服务降级在使用时候都是一体化实现的,这样就可以实现服务容错保护。在编程模型上就会非常方便。

  2. 2.服务熔断:除了依赖隔离,服务降级之外,Hystrix还有另一一个重要元素:服务熔断。

9.4.1 服务熔断

  1. 1.服务熔断还是使用@HystrixCommand注解:
    我们如何配置了,我们还是打开HystrixCommandProperties类:

我们将上面注解拷贝出来,使用在Order服务的getProductInfoList上

然后我们在浏览器测试:http://localhost:8082/getProductInfoList
发现其一直返回”默认提示:太拥挤了,请稍后再试~~~”

此时发现一直返回错误,我们该如何进行测试呢?我们加一个请求参数,如果number为偶数直接返回success,否则调用product服务;注意此时调用product服务肯定会进入服务降级回调,原因是因为上面execution.isolation.thread.timeoutInMilliseconds已经注释掉了并且product服务里面线程等待为2秒,并且execution.isolation.thread.timeoutInMilliseconds默认等待时间是1秒。

  1. 2.产生熔断:我们不停地访问:http://localhost:8082/getProductInfoList?number=1让其错误率达到60%

  1. 3.服务熔断:
    circuitBreaker.requestVolumeThreshold
    circuitBreaker.sleepWindowInMilliseconds
    circuitBreaker.errorThresholdPercentage

这是我们上面用到的3个配置,3个配置前面都有一个共同的词:circuitBreaker
a.circuitBreaker:断路器(当某个服务发生故障,类似用电器发生短路,通过断路器的故障监控,就类似于熔断的保险丝,直接切断原来的主逻辑调用)
b.微服务和分布式里面容错必须是要考虑的,通常做法有两种:
1)重试机制:对于预期的短暂的故障问题,可以重试解决的
2)断路器模式:对于更长时间的故障问题,不断重试也是没有意义的,这个时候就可以使用断路器模式。

断路器模式是将受保护的服务封装在一个可监控的断路器对象里面,当故障到达一定的值,断路器将会跳闸,断路器对象返回错误。如下所示:

上图描述了断路器模式的3中状态积:
1)close:熔断器的关闭状态,调用失败次数累计到一定阈值/比例时候,就会启动熔断机制。
2)open:熔断器的打开状态,对服务直接返回错误,但是有一个时钟,到达这个时钟之后,会进入半熔断状态,也就是half open,允许定量的服务请求,如果调用成功到一定比例就认为恢复了,就会关闭熔断器。否则,认为还没有好,又回到熔断器打开状态。
3):half open:

  1. 4.参数含义:
    circuitBreaker.sleepWindowInMilliseconds:这里面的Window很多地方会翻译成时间窗口,断路器确定是否需要断开统计一些请求和错误数据的时候,是有一个时间范围的,这个时间范围就被称为时间窗口;当断路器打开对主逻辑进行熔断之后,Hystrix会启动一个休眠时间窗,在这个时间窗内降级逻辑临时成为主逻辑,当休眠时间窗到期,断路器将进为半开状态,释放一些请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,主逻辑恢复,如果此次请求依然有问题,断路器将继续进入打开状态,休眠时间窗重新计时。我们上面将此参数设置为10000ms。
    circuitBreaker.requestVolumeThreshold :设置在滚动窗中,断路器的最小请求数
    circuitBreaker.errorThresholdPercentage:设置断路器打开的错误百分比条件,上面设置的是60,表示在滚动时间窗口中,如果发生了10次调用,有7次异常超过60%,此时断路器设置为打开状态,否则设置为关闭状态。

9.5 使用配置项

我们先注释掉所有配置:

之前的关于断路器的配置都是在代码里面配置的,如下图所示,不利于后期的维护
我们能把上面的配置写到配置文件中去吗?我们先写到本地文件中的yml格式
现在要改成用配置文件的方式进行,我们针对超时时间来做一个配置,
Hystrix全局超时时间配置如下图所示,表示3秒

有时候我们发现我们配置不起作用,服务器不触发降级,原因是我们没有在方法上添加@HystrixCommand注解

加上之后就可以了。上面是配置的全局的default配置,如果我们想给某一个类单独配置:在方法上注解:@HystrixComman然后配置属性里面的comandKey,然后再配置文件中加上。

9.6 feign-hystrix的使用

feign如何搭配hystrix,我们先看一下feign依赖了哪些组件?

再按:Ctrl+F

说明feign已经依赖了hystrix,所以使用按照如下方式:

  1. 1.order服务添加依赖

  1. 2.product服务在client端改造:@FeignClient注解属性里面添加fallback
    a.在fallback填写ProductClientFallback.class类。
    b.书写内部静态类并且实现ProductClient接口。
    c.内部静态类需要添加@Component注解。
    d.将此包打出去:在Terminal中输入:mvn install
    此时我们进入order服务里面OrderServiceImpl里面的productClient,然后点击进去:发现就有了。

启动order服务,我们发现报错了:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘orderServiceImpl’: Unsatisfied dependency expressed through field ‘productClient’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘com.yxm.product.client.ProductClient’: FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: No fallback instance of type class com.yxm.product.client.ProductClient$ProductClientFallback found for feign client product

以上说明orderServiceImpl里面引入的com.yxm.product.client.ProductClient$ProductClientFallbac没有实例化。

原因:以上order服务引入productClient时候,已经把其当做order服务代码的一部分引入,productClient已经是order服务里面的一块代码了,所以运行的时候是在order服务中运行的,为什么不起作用了,原因是我们的启动类中没有扫描到。

明显和com.yxm.product.client.ProductClient不一样了,所以我们需要把扫描扩大:

然后启动正常。

使用post下单(此时我们的product服务没有启动)

以上说明我们已经达到了我们的要求。

9.7 hystrix-dashboard使用

hystrix-dashboard是进行可视化的一个组件,使用老套路

  1. 1.引入依赖
1
2
3
4
5
6
7
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
</dependency>
```
有时候一些网站博客里面可能需要让我们再引入:

org.springframework.boot

spring-boot-starter-actuator

```

但是其实我们这里不需要再次引入了:

有时候我们会遇到@EnableHystrixDashboard注解始终加不上问题,我们统一下SpringBoot和SpringCloud版本。
SpringBoot:2.1.8.RELEASE
SpringCloud:Greenwich.SR3

  1. 2.启动类加注解

  1. 3.浏览器访问:
    http://localhost:8082/hystrix
    a.最上面输入框:填写应用地址
    b.填写应用的3种方式,我们这里是Single Hystrix App所以使用:https://hystrix-app:port/actuator/hystrix.stream
    Cluster via Turbine (default cluster): https://turbine-hostname:port/turbine.stream
    Cluster via Turbine (custom cluster): https://turbine-hostname:port/turbine.stream?cluster=[clusterName]
    Single Hystrix App: https://hystrix-app:port/actuator/hystrix.stream

我们点击Monitor Stream进去后进入:

Unable to connect to Command Metric Stream.
查看控制台发现:java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens
参考:
https://blog.csdn.net/HonsonNgai/article/details/89300789

如果一直loading,我无意中的测试,发现这个Loading…是一直在等待负载均衡的提供方要去消费服务,即访问负载均衡服务器,去调用客户端,如果有数据响应则监控界面就会有图形数据展示:

如果想让图中的数据发生变化,则需要循环多次的去访问负载均衡的提供方,让其消费服务,以至于达到监控的目的。
http://localhost:8082/getProductInfoList?number=1

a.上面颜色小圈对应的就是:Success | Short-Circuited | Bad Request | Timeout | Rejected | Failure | Error
b.Circuit Closed表明已经是熔断了
c.中间有一个圆;圆越大说明流量就越大;圆颜色偏向于红色,表示服务越不健康。线条表示流量的相对变化。
d.最上面百分比是错误率;下面两个百分比是请求的频率。

在HystrixController中打开之前设置的参数,然后请求:

有时候,我们如果把熔断百分比设置比较大的话,我们一次次请求是很耗费时间的,其实postman提供了一个多次发送的功能:

ipcc-3-日常运维

前言

1.中间跳过的名单拨打处理
2.统计批次进度问题
3.重呼数据未拨打问题(重启后拨打)
4.查看某个租户是否配置了重呼轮呼策略
5.批次数据号码处理(加前缀去掉前缀)

内容

1.中间跳过的名单拨打处理

先查看未拨打批次:

1
2
3
SELECT DISTINCT(ocm_buslist.event_id) FROM ocm_buslist ocm_buslist
LEFT JOIN cti_cdr cdr ON ocm_buslist.list_id = cdr.memberid LEFT JOIN ocm_event e ON e.event_id = ocm_buslist.event_id
WHERE e.event_state IN(0,1,2) AND ocm_buslist.create_time<'2019-12-22 23:59:59' AND cdr.id IS NULL ORDER BY ocm_buslist.list_id DESC

1.1 数据量小时候处理

1.查询出未拨打的数据保存成.sql文件:

1
2
3
SELECT ocm_buslist.* FROM ocm_buslist ocm_buslist
LEFT JOIN cti_cdr cdr ON ocm_buslist.list_id = cdr.memberid
WHERE ocm_buslist.event_id = xxx AND cdr.id IS NULL ORDER BY ocm_buslist.list_id DESC

2.查询批次(比较max_member_id和查询的list_id大小)

1
SELECT event_name,max_member_id FROM ocm_event WHERE event_id = xxx;

2.然后执行插入

3.最后删除之前list_id

1
DELETE FROM ocm_buslist WHERE event_id = xxx AND list_id IN(xxx1,xxx2);

4.查询导入之后数据大小

1
select count(*) from ocm_buslist where list_id > max_memberid

1.2 数据量大时候处理

批次是按照大于ocm_event表中的max_member_id对比进行拨打,在名单表中小于max_member_id将不会拨打。如果出现跳过拨打的数据,我们需要按照如下步骤处理:注意:首先先要查看对应的名单是否已经拨打但是没有插入扫cti_cdr表,防止重复导入拨打。[
操作:

1
grep 5314900 callnotify_callnotifysql01_1574*;

]

  1. 1.未拨打数据采集:[查询未拨打客户名单->将其导入到名单模板中重新导入]
1
2
3
SELECT ob.customer_name,ob.customer_phone,ob.car_no,ob.cust_id FROM ocm_buslist ob
LEFT JOIN cti_cdr cdr ON ob.list_id = cdr.memberid
WHERE ob.event_id = xxx AND cdr.id IS NULL ORDER BY ob.list_id DESC
  1. 2.ocm_base_shbo处理:[删除未拨打的数据,删除之前先查询]
    a.查询未拨打的数据:
1
2
3
4
5
6
SELECT sb.* FROM ocm_base_shbo sb WHERE sb.event_id = xxx AND sb.cust_id IN (SELECT DISTINCT ob.cust_id FROM ocm_buslist ob
LEFT JOIN cti_cdr cdr ON ob.list_id = cdr.memberid
WHERE ob.event_id = xxx AND cdr.id IS NULL);
```
b.删除未拨打数据:

DELETE FROM ocm_base_shbo WHERE event_id = xxx AND cust_id IN (SELECT ob.cust_id FROM ocm_buslist ob
LEFT JOIN cti_cdr cdr ON ob.list_id = cdr.memberid
WHERE ob.event_id = xxx AND cdr.id IS NULL);

1
2
3
3. 3.ocm_buslist处理:[删除未拨打的数据,删除之前先查询]
a.查询未拨打数据

select * FROM ocm_buslist WHERE event_id = xxx AND list_id NOT IN (SELECT DISTINCT memberid FROM cti_cdr WHERE notifyid = xxx);

1
2
b.删除未拨打数据

DELETE FROM ocm_buslist WHERE event_id = xxx AND list_id NOT IN (SELECT DISTINCT memberid FROM cti_cdr WHERE notifyid = xxx);

1
2
4. 4.最后导入数据,修改批次统计:

select * from ocm_event_statistics where event_id = xxx

1
2
3
4
5
6
7
### 2.统计批次进度问题
批次进度统计主要是表:ocm_event_statistics,其中进度主要由3部分指标组成:
called_number(已拨打数量:从ocm_buslist中distinct cust_id)、filter_number(过滤掉的数量:从ocm_base_shbo表中count下:valid_flag=0的数据)、list_number(名单总数量:ocm_base_shbo中count(*));如果ocm_buslist_timing表中含有数据的话即使ocm_buslist中数据拨打完了,也会是99%
1. 查询批次整体进度情况

SELECT * FROM ocm_event_statistics WHERE event_id = xxx; //xxx批次id

1
2
1. 查看是否还有重呼数据

SELECT * FROM ocm_buslist_timing WHERE event_id = xxx; //xxx批次id

1
2
1. 查询导入到ocm_buslist中名单数量

SELECT COUNT(DISTINCT cust_id) FROM ocm_buslist WHERE event_id = xxx; //xxx批次id

SELECT COUNT(*) FROM ocm_base_shbo WHERE event_id = xxx AND valid_flag >= 1; //xxx批次id

1
2
3
4
1. 查询批次下总共数量:list_number

SELECT COUNT(*) FROM ocm_base_shbo WHERE event_id = xxx; //xxx批次id

1
2
1. 查看过滤掉的数据filter_number

SELECT COUNT(*) FROM ocm_base_shbo WHERE event_id = xxx AND valid_flag = 0; //xxx批次id

1
2
3
4
5
### 3.重呼数据未拨打问题(重启后拨打)
有时候,我们的重呼数据一直可能存在于:ocm_buslist_timing表中而不会拨打,所以我们需要处理这些批次,重新启用停用(对于在执行时间段内的批次)。
1. 1.查看在当前时间前未重呼的批次

SELECT event_id,event_state,event_name,send_time,over_time FROM ocm_event WHERE event_id IN (SELECT DISTINCT event_id FROM ocm_buslist_timing WHERE call_next_time

1
2
### 4.查看某个租户是否配置了重呼轮呼策略

SELECT enti.id,enti.entname,enti.state,oc.id,oc.parameter FROM cti_entinfo enti LEFT JOIN ocm_after_call_action oc ON enti.id = oc.entid

1
2
3
4
5
6
7
8
9
### 5.批次数据号码处理(加前缀去掉前缀)
1. 1.参考
参考:https://blog.csdn.net/xiaosongbk/article/details/77199007
update forumdata_userttt set userLink=right(userLink,length(userLink)-2) where id >= 137;
2. 2.去除批次号码的前缀(前两位)

UPDATE ocm_buslist SET customer_phone=RIGHT(customer_phone,LENGTH(customer_phone)-2) WHERE event_id = 1658 AND list_id>6253939;

1
2
3. 3.去除重呼表中93开头的号码前两位

UPDATE ocm_buslist_timing SET customer_phone RIGHT(customer_phone,LENGTH(customer_phone)-2) WHERE customer_phone LIKE ‘93%’;
```

acdgate-1-websocket404

将AcdGate发布到阿里云服务器之后,登录坐席一直报websocket连接不上的404,如下:

查看原因是:tomcat下webapps打包后的AcdGate里面WEB-INF里面的lib下面含有:websocket-api.jar包,并且在部署的Tomcat下的lib里面也有:websocket-api.jar包,导致冲突,解决办法删除其中一个里面的websocket-api.jar即可

work-11-nginx安装配置https

参考1:https://www.cnblogs.com/wanghuaijun/p/5480554.html
参考2:https://www.runoob.com/linux/nginx-install-setup.html

安装nginx

软件需求:

下载地址:
链接:https://pan.baidu.com/s/1OTFCGaTXOEQ54cnMtv8JJw
提取码:z3h5

1.创建nginx用户

  1. 1.groupadd -r nginx
  2. 2.useradd -r -g nginx -M nginx

2.解压缩nginx的源码并安装

  1. 1.nginx-1.10.2.tar.gz、pcre-8.33.tar.gz、zlib-1.2.8.tar.gz上传文件到tools目录
  2. 2.解压:
  3. 3.cd nginx-1.10.2 执行:configure

    1
    2
    ./configure --user=nginx --group=nginx --prefix=/founder/tools/nginx --with-http_stub_status_module --with-http_ssl_module
    --with-http_realip_module --with-http_addition_module --with-pcre=/founder/tools/pcre-8.33 --with-zlib=/founder/tools/zlib-1.2.8
  4. 4.编译 make && make install
    如果出现以下错误按照要求修改即可:

  5. 5.查看nginx版本
    进入前面configure中配置的prefix下,执行如下命令:

    1
    ./nginx/sbin/nginx -v
  6. 6.启动nginx

    1
    ./nginx/sbin/nginx

2.配置https

2.1 配置前需要准备

  1. 1.配置前需要准备:域名、私钥文件、key文件、密码文件。如下图:
2.2 开始配置
  1. 1.安装证书
    将证书置于服务器中,一般放于/nginx/sslcrt下。
  2. 2.修改配置文件
    早期的配置文件是/opt/nginx/conf/nginx.conf,较新的项目是/opt/nginx/conf.d/*.conf
    找到需要添加https的服务所在的位置。进行如下配置:

  3. 3.重载nginx配置文件
    /nginx/sbin/nginx -s reload

3.nginx常见错误

  1. 1.解决nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed错误

4.nginx其他命令

以下包含了 Nginx 常用的几个命令:

  1. 1./usr/local/webserver/nginx/sbin/nginx -s reload # 重新载入配置文件
  2. 2./usr/local/webserver/nginx/sbin/nginx -s reopen # 重启 Nginx
  3. 3./usr/local/webserver/nginx/sbin/nginx -s stop # 停止 Nginx

5.编译nginx平滑添加stream模块

有时候我们如果直接不能连接服务器c,但是B服务器能够连接服务器c,所有我们通过在B服务器做代理直接连接c。
http://www.mamicode.com/info-detail-2272209.html。

1
2
3
4
./configure --user=nginx --group=nginx --prefix=/founder/tools/nginx --with-http_stub_status_module --with-http_ssl_module
--with-http_realip_module --with-http_addition_module --with-pcre=/founder/tools/pcre-8.33 --with-zlib=/founder/tools/zlib-1.2.8 --with-stream
--with-stream_ssl_module

nginx实现端口监听:

https://www.jianshu.com/p/c5097147ace3

6.安装stream模块

./configure –with-stream –prefix=/usr/local/nginx && make && make install

ipcc-2-常见问题记录

1.ipcc对接第三方话务平台

1.1抓包找不到对应ip数据包
  1. 1.分析:ipcc对接第三方话务平台的时候、我们抓包时候压根抓不到对应的ip网络交互、说明ipcc没能和第三方话务平台建立链接、说明freeswitch的sip对接地址注册有问题
  2. 2.解决:a.查看对应的网关对接信息是否有问题,在freeswitch的/usr/local/freeswitch/conf/sip_profiles/external/gw5.xml配置
  3. 3.解决:b.查看freeswitch启动时候日志信息:

    从上面看是gw5.xml网关对应的配置信息有误
  4. 4.解决:c.打开fs的客户端fs_cli通过sofia status 查看网关注册状态

    从上面可以知道网关注册失败

综上:找相关人员再次获取相关信息。

1.2.fs通过mrcp对接asr时候对接不上

在测试环境下fs通过mrcp对接asr时候对接时候、启动fs和ipcc平台时候、发现和机器人交互时候总是感觉机器人获取不到用户说话的声音并且抓包时候也没有抓到包
解决:

  1. 1.查看asr的配置信息并确认没问题
  2. 2.查看fs的启动日志:然后查看端口信息、发现端口被占用

    综上:杀掉端口对应进程、然后重启即可。

2.ipcc通话录音不存在

2.1 现象

gs在拨打电话测试时候,测试时候交互都很正常,但是在拨打完听录音时候出现:

HTTP Status 404-
/record/ivrrecord2/20190820/10/42/90043811800411.wav

2.2 排查
  1. 1.查询服务器磁盘录音是否存在
    -进入/cc/data/ivrrecord2/20190820/10目录下确实没有此文件

  2. 2.查看fsg日志
    fsg是freeswitch和ag进行交互的枢纽,所以fsg日志里面会记录相关的日志信息,fsg的日志文件在/cc/bin/log下:log0819060907.log

    从上面我们知道fsg和freeswitch已经断开过连接,然后重新建立了连接。

我们在查看freeswitch.log知道:丢失了很多交互信息

  1. 3.查看fsg.cfg的配置
    从配置中我们知道连接的freeswitch是127.0.0.1,对应的录音文件是:/cc/data

    说明在连接本地freeswitch的时候,也出现了网络抖动问题。

2.查看批次数据不拨打

  1. 1.首先我们需要查看批次暂停/启用是否生效
    启停 之前给过你grep方法 搜一下
    停用:grep “end taskid”
    启用:init notifyid

  2. 2.查看具体原因:

1
2
3
4
5
6
grep "批次id" callnotify_callnotify01_1575880253.log;
```
![](https://raw.githubusercontent.com/startshineye/img/master/2019/12/4.png)
3. 3.查看是否有对应主叫

grep “ocm_enti_exinfo_sub” dbg_dbgnotify01_xxx.log
```

再去到数据库执行,查找批次下的comcode是否有下对应是否有次主叫:

有时候我们查询出后发现:主叫表里面有对应comcode的主叫,但是还是报:caller is empty这个时候我们就需要再去:dbgnotify查看日志。

毕业于<br>相信技术可以改变人与人之间的生活<br>码农一枚