首页 文章 精选 留言 我的

精选列表

搜索[手动],共10002篇文章
优秀的个人博客,低调大师

Arthas 手动触发生产定时任务的危险操作

背景 最近来了个实习僧小弟,安排他实现对目标网站 连通性检测的小功能,简单讲就是将下边的shell 脚本换成Java 代码来实现 #!/bin/bash URL="https://www.baidu" HTTP_CODE=`curl -o /dev/null -s -w "%{http_code}" "${URL}"` #echo $HTTP_CODE if [ $HTTP_CODE != '200' ];then curl 'https://oapi.dingtalk.com/robot/send?access_token=xx' \ -H 'Content-Type: application/json' \ -d '{"msgtype": "text", "text": { "content": "百度平台状态不正常,请注意!" }, "isAtAll": true }' fi 功能实现 使用spring task @Scheduled(cron = "0 0 0/1 * * ? ") public void startSchedule() { log.info("开始执行定时任务 ,检测百度网站连通性"); try { HttpResponse response = HttpRequest.get("").execute(); if (HttpStatus.HTTP_OK != response.getStatus()) { this.send2DingTalk(response.getStatus()); } log.info("请求百度成功,返回报文:{}",response.body()); } catch (HttpException e) { log.error("请求异常百度:{}", e); this.send2DingTalk(e.getMessage()); } log.info("执行检测百度网站连通任务完毕"); } 问题描述 部署在服务器上,我的老jio本 都已经呼叫任务状态不正常了,可是小弟的Java 代码还是没有执行通知 去翻生产日志,只输入了开始并没有输出定时任务结束,感觉是哪里卡死,想当然以为如果超时总会到catch 逻辑,排查无果 由于任务是一小时一次,如何快速触发一下这个异常,还原事故现场 由于使用简单的Spring Task 没有图形化界面和API接口 Arthas 还原事故现场,重新触发任务 核心拿到 spring context 然后执行它的 startSchedule 方法 确定监控点 SpringMVC 的请求会通过 RequestMappingHandlerAdapter 执行invokeHandlerMethod 到达目标接口上进行处理 而在 RequestMappingHandlerAdapter类中有 getApplicationContext() @Nullable public final ApplicationContext getApplicationContext() throws IllegalStateException { if (this.applicationContext == null && this.isContextRequired()) { throw new IllegalStateException("ApplicationObjectSupport instance [" + this + "] does not run in an ApplicationContext"); } else { return this.applicationContext; } } 任意执行一次请求获取到 RequestMappingHandlerAdapter target 目标,然后执行 getApplicationContext tt命令 获取到ApplicationContext arthas 执行 tt tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod 任意执行一次web 请求,tt 即可捕获 根据目标的索引,执行自定义 OGNL 表达式即可 tt -i 1019 -w 'target.getApplicationContext()' 使用ApplicationContext获取 定时任务bean 执行 startSchedule tt -i 1000 -w 'target.getApplicationContext().getBean("baiduSchedule").startSchedule()' ok 任务重新触发了 事故原因调查清楚,由于使用hutool 的工具类 没有设置timeout 导致无限等待,所以没有执行catch 逻辑 总结 以上吓哭实习僧的操作禁止生产操作,只是提供个思路 ,当然可以衍生其他业务场景的操作 核心是通过Arthas 来抓取Spring ApplicationContext 对象,然后获取bean 进行执行方法 关于Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱 欢迎关注我们获得更多的好玩JavaEE 实践

优秀的个人博客,低调大师

手动撸个Android雷达图(蜘蛛网图)RadarView

image 公司产品需要一个雷达图来展示各维度的比重,网上找了一波,学到不少,直接自己上手来撸一记 无图言虚空 image 简单分析一波,确定雷达图正几边形的--正五边形 int count=5,分为几个层数--4 层 int layerCount=4 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawPolygon(canvas);//画边 drawLines(canvas);//画线 drawText(canvas);//描绘文字 drawRegion(canvas);//覆盖区域 } 主要这几步,开撸! 自定义RadarView继承View 确定需要使用的变量,初始化paint,计算圆心角 private int count = 5; //几边形 private int layerCount = 4; //层数 privatefloatangle; //每条边对应的圆心角 private int centerX; //圆心x private int centerY; //圆心y privatefloatradius; //半径 private Paint polygonPaint; //边框paint private Paint linePaint; //连线paint private Paint txtPaint; //文字paint private Paint circlePaint; //圆点paint private Paint regionColorPaint; //覆盖区域paint private Double[] percents = {0.91, 0.35, 0.12, 0.8, 0.5}; //覆盖区域百分比 private String[] titles = {"dota","斗地主","大吉大利,晚上吃鸡","炉石传说","跳一跳"};//文字 public RadarView(Context context) { this(context, null, 0); } public RadarView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public RadarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //计算圆心角 angle = (float) (Math.PI * 2 / count); polygonPaint = new Paint(); polygonPaint.setColor(ContextCompat.getColor(context, R.color.radarPolygonColor)); polygonPaint.setAntiAlias(true); polygonPaint.setStyle(Paint.Style.STROKE); polygonPaint.setStrokeWidth(4f); linePaint = new Paint(); linePaint.setColor(ContextCompat.getColor(context, R.color.radarLineColor)); linePaint.setAntiAlias(true); linePaint.setStyle(Paint.Style.STROKE); linePaint.setStrokeWidth(2f); txtPaint = new Paint(); txtPaint.setColor(ContextCompat.getColor(context, R.color.radarTxtColor)); txtPaint.setAntiAlias(true); txtPaint.setStyle(Paint.Style.STROKE); txtPaint.setTextSize(DensityUtil.dpToPx(context, 12)); circlePaint = new Paint(); circlePaint.setColor(ContextCompat.getColor(context, R.color.radarCircleColor)); circlePaint.setAntiAlias(true); regionColorPaint = new Paint(); regionColorPaint.setColor(ContextCompat.getColor(context, R.color.radarRegionColor)); regionColorPaint.setStyle(Paint.Style.FILL); regionColorPaint.setAntiAlias(true); } 确定中心点 需要正五边形得有一个圆,圆内接正五边形,在onSizeChanged方法里获取圆心,确定半径 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); radius = Math.min(h, w) / 2 * 0.7f; centerX = w / 2; centerY = h / 2; } 绘制正五边形 绘制正五边形同时描绘最外围的点,确定分为4层,半径 / 层数 =每层之间的间距,从最里层开始画正五边形,每层第一个点位于中心点正上方 private void drawPolygon(Canvas canvas) { Path path = new Path(); float r = radius / layerCount; for (int i = 1; i <= layerCount; i++) { float curR = r * i; //当前所在层的半径 for (int j = 0; j < count; j++) { if (j == 0) { //每一层第一个点坐标 path.moveTo(centerX, centerY - curR); } else { //顺时针记录其余顶角的点坐标 float x = (float) (centerX + Math.sin(angle * j) * curR); float y = (float) (centerY - Math.cos(angle * j) * curR); path.lineTo(x, y); } } //最外层的顶角外面的五个小圆点(图中红色部分) if (i == layerCount) { for (int j = 0; j < count; j++) { float x = (float) (centerX + Math.sin(angle * j) * (curR + 12)); float y = (float) (centerY - Math.cos(angle * j) * (curR + 12)); canvas.drawCircle(x, y, 4, circlePaint); } } path.close(); canvas.drawPath(path, polygonPaint); } } image.png 绘制连线 绘制最内层顶角到最外层顶角的连线 private void drawLines(Canvas canvas) { float r = radius / layerCount; for (int i = 0; i < count; i++) { //起始坐标 从中心开始的话 startx=centerX , startY=centerY float startX = (float) (centerX + Math.sin(angle * i) * r); float startY = (float) (centerY - Math.cos(angle * i) * r); //末端坐标 float endX = (float) (centerX + Math.sin(angle * i) * radius); float endY = (float) (centerY - Math.cos(angle * i) * radius); canvas.drawLine(startX, startY, endX, endY, linePaint); } } image.png 至此简易雷达图成型,可以修改正几边形,多少层数(后续继续添加文字) //设置几边形,**注意:设置几边形需要重新计算圆心角** public void setCount(int count){ this.count = count; angle = (float) (Math.PI * 2 / count); invalidate(); } //设置层数 public void setLayerCount(int layerCount){ this.layerCount = layerCount; invalidate(); } 设置正六边形、六层 radarView.setCount(6); radarView.setLayerCount(6); image.png 对于以下图形的,可以设置第一个点坐标位于中心点正右侧(centerX+curR,centerY),顺时针计算其余顶点坐标x = (float) (centerX+curR*Math.cos(angle*j)), y = (float) (centerY+curR*Math.sin(angle*j)),同理连线等其余坐标相应改变... image.png 描绘文字 由于各产品维度内容不同,所需雷达图样式不一,这里只是描绘下不同位置的文字处理情况,具体需求还得按产品来,因产品而异 private void drawText(Canvas canvas) { for (int i = 0; i < count; i++) { //获取到雷达图最外边的坐标 float x = (float) (centerX + Math.sin(angle * i) * (radius + 12)); float y = (float) (centerY - Math.cos(angle * i) * (radius + 12)); if (angle * i == 0) { //第一个文字位于顶角正上方 txtPaint.setTextAlign(Paint.Align.CENTER); canvas.drawText(titles[i], x, y - 18, txtPaint); txtPaint.setTextAlign(Paint.Align.LEFT); } else if (angle * i > 0 && angle * i < Math.PI / 2) { //微调 canvas.drawText(titles[i], x + 18, y + 10, txtPaint); } else if (angle * i >= Math.PI / 2 && angle * i < Math.PI) { //最右下的文字获取到文字的长、宽,按文字长度百分比向左移 String txt = titles[i]; Rect bounds = new Rect(); txtPaint.getTextBounds(txt, 0, txt.length(), bounds); float height = bounds.bottom - bounds.top; float width = txtPaint.measureText(txt); canvas.drawText(txt, x - width * 0.4f, y + height + 18, txtPaint); } else if (angle * i >= Math.PI && angle * i < 3 * Math.PI / 2) { //同理最左下的文字获取到文字的长、宽,按文字长度百分比向左移 String txt = titles[i]; Rect bounds = new Rect(); txtPaint.getTextBounds(txt, 0, txt.length(), bounds); float width = txtPaint.measureText(txt); float height = bounds.bottom - bounds.top; canvas.drawText(txt, x - width * 0.6f, y + height + 18, txtPaint); } else if (angle * i >= 3 * Math.PI / 2 && angle * i < 2 * Math.PI) { //文字向左移动 String txt = titles[i]; float width = txtPaint.measureText(txt); canvas.drawText(txt, x - width - 18, y + 10, txtPaint); } } } image.png 绘制覆盖区域 绘制覆盖区域,百分比取连线长度的百分比(如果从中心点开始的连线,则是半径的百分比),此处用半径radius减去间隔r即连线长度 private void drawRegion(Canvas canvas) { Path path = new Path(); float r = radius / layerCount;//每层的间距 for (int i = 0; i < count; i++) { if (i == 0) { path.moveTo(centerX, (float) (centerY - r - (radius - r) * percents[i])); } else { float x = (float) (centerX + Math.sin(angle * i) * (percents[i] * (radius - r) + r)); float y = (float) (centerY - Math.cos(angle * i) * (percents[i] * (radius - r) + r)); path.lineTo(x, y); } } path.close(); canvas.drawPath(path, regionColorPaint); } image.png 至此,一个简单的雷达图完毕。同时欢迎关注微信公众号 image.png End

优秀的个人博客,低调大师

CentOS7手动安装OpenStack Pike版--(neutron)

OpenStack安装指南_Mitakahttp://down.51cto.com/data/2331199 Openstack管理手册-Newton版-CentOS7.2http://down.51cto.com/data/2331201 #Configure neutron mysql -uroot -ppasswd123 -e "CREATE DATABASE neutron" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON neutron.TO 'neutron'@'localhost' IDENTIFIED BY 'passwd123'" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON neutron.TO 'neutron'@'%' IDENTIFIED BY 'passwd123'" openstack user create --domain default --password passwd123 neutron openstack role add --project service --user neutron admin openstack service create --name neutron --description "OpenStack Networking" network openstack endpoint create --region RegionOne network publichttp://controller:9696 openstack endpoint create --region RegionOne network internalhttp://controller:9696 openstack endpoint create --region RegionOne network adminhttp://controller:9696 Networking Option 2: Self-service networks Edit the /etc/neutron/neutron.conf openstack-config --set /etc/neutron/neutron.conf database connection mysql+pymysql://neutron:passwd123@controller/neutron openstack-config --set /etc/neutron/neutron.conf DEFAULT core_plugin ml2 openstack-config --set /etc/neutron/neutron.conf DEFAULT service_plugins router openstack-config --set /etc/neutron/neutron.conf DEFAULT allow_overlapping_ips true openstack-config --set /etc/neutron/neutron.conf DEFAULT transport_url rabbit://openstack:passwd123@controller openstack-config --set /etc/neutron/neutron.conf DEFAULT auth_strategy keystone openstack-config --set /etc/neutron/neutron.conf keystone_authtoken auth_urihttp://controller:5000 openstack-config --set /etc/neutron/neutron.conf keystone_authtoken auth_urlhttp://controller:35357 openstack-config --set /etc/neutron/neutron.conf keystone_authtoken memcached_servers controller:11211 openstack-config --set /etc/neutron/neutron.conf keystone_authtoken auth_type password openstack-config --set /etc/neutron/neutron.conf keystone_authtoken project_domain_name default openstack-config --set /etc/neutron/neutron.conf keystone_authtoken user_domain_name default openstack-config --set /etc/neutron/neutron.conf keystone_authtoken project_name service openstack-config --set /etc/neutron/neutron.conf keystone_authtoken username neutron openstack-config --set /etc/neutron/neutron.conf keystone_authtoken password passwd123 openstack-config --set /etc/neutron/neutron.conf DEFAULT notify_nova_on_port_status_changes true openstack-config --set /etc/neutron/neutron.conf DEFAULT notify_nova_on_port_data_changes true openstack-config --set /etc/neutron/neutron.conf nova auth_urlhttp://controller:35357 openstack-config --set /etc/neutron/neutron.conf nova auth_type password openstack-config --set /etc/neutron/neutron.conf nova project_domain_name default openstack-config --set /etc/neutron/neutron.conf nova user_domain_name default openstack-config --set /etc/neutron/neutron.conf nova region_name RegionOne openstack-config --set /etc/neutron/neutron.conf nova project_name service openstack-config --set /etc/neutron/neutron.conf nova username nova openstack-config --set /etc/neutron/neutron.conf nova password passwd123 openstack-config --set /etc/neutron/neutron.conf oslo_concurrency lock_path /var/lib/neutron/tmp Edit the /etc/neutron/plugins/ml2/ml2_conf.ini openstack-config --set /etc/neutron/plugins/ml2/ml2_conf.ini ml2 type_drivers flat,vlan,vxlan openstack-config --set /etc/neutron/plugins/ml2/ml2_conf.ini ml2 tenant_network_types vxlan openstack-config --set /etc/neutron/plugins/ml2/ml2_conf.ini ml2 mechanism_drivers linuxbridge,l2population openstack-config --set /etc/neutron/plugins/ml2/ml2_conf.ini ml2 extension_drivers port_security openstack-config --set /etc/neutron/plugins/ml2/ml2_conf.ini ml2_type_flat flat_networks provider openstack-config --set /etc/neutron/plugins/ml2/ml2_conf.ini ml2_type_vxlan vni_ranges 1:1000 openstack-config --set /etc/neutron/plugins/ml2/ml2_conf.ini securitygroup enable_ipset true Edit the /etc/neutron/plugins/ml2/linuxbridge_agent.ini openstack-config --set /etc/neutron/plugins/ml2/linuxbridge_agent.ini linux_bridge physical_interface_mappings provider:ens34 openstack-config --set /etc/neutron/plugins/ml2/linuxbridge_agent.ini vxlan enable_vxlan true openstack-config --set /etc/neutron/plugins/ml2/linuxbridge_agent.ini vxlan local_ip 192.168.137.145 openstack-config --set /etc/neutron/plugins/ml2/linuxbridge_agent.ini vxlan l2_population true openstack-config --set /etc/neutron/plugins/ml2/linuxbridge_agent.ini securitygroup enable_security_group true openstack-config --set /etc/neutron/plugins/ml2/linuxbridge_agent.ini securitygroup firewall_driver neutron.agent.linux.iptables_firewall.IptablesFirewallDriver Edit the /etc/neutron/l3_agent.ini openstack-config --set /etc/neutron/l3_agent.ini DEFAULT interface_driver linuxbridge Edit the /etc/neutron/dhcp_agent.ini openstack-config --set /etc/neutron/dhcp_agent.ini DEFAULT interface_driver linuxbridge openstack-config --set /etc/neutron/dhcp_agent.ini DEFAULT dhcp_driver neutron.agent.linux.dhcp.Dnsmasq openstack-config --set /etc/neutron/dhcp_agent.ini DEFAULT enable_isolated_metadata true Edit the /etc/neutron/metadata_agent.ini openstack-config --set /etc/neutron/metadata_agent.ini DEFAULT nova_metadata_host controller openstack-config --set /etc/neutron/metadata_agent.ini DEFAULT metadata_proxy_shared_secret openstack Edit the /etc/nova/nova.conf openstack-config --set /etc/nova/nova.conf neutron urlhttp://controller:9696 openstack-config --set /etc/nova/nova.conf neutron auth_urlhttp://controller:35357 openstack-config --set /etc/nova/nova.conf neutron auth_type password openstack-config --set /etc/nova/nova.conf neutron project_domain_name default openstack-config --set /etc/nova/nova.conf neutron user_domain_name default openstack-config --set /etc/nova/nova.conf neutron region_name RegionOne openstack-config --set /etc/nova/nova.conf neutron project_name service openstack-config --set /etc/nova/nova.conf neutron username neutron openstack-config --set /etc/nova/nova.conf neutron password passwd123 openstack-config --set /etc/nova/nova.conf neutron service_metadata_proxy true openstack-config --set /etc/nova/nova.conf neutron metadata_proxy_shared_secret = openstack ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \ --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron systemctl restart openstack-nova-api.service systemctl enable neutron-server.service \ neutron-linuxbridge-agent.service neutron-dhcp-agent.service \ neutron-metadata-agent.service systemctl start neutron-server.service \ neutron-linuxbridge-agent.service neutron-dhcp-agent.service \ neutron-metadata-agent.service systemctl status neutron-server.service \ neutron-linuxbridge-agent.service neutron-dhcp-agent.service \ neutron-metadata-agent.service systemctl enable neutron-l3-agent.service systemctl start neutron-l3-agent.service systemctl status neutron-l3-agent.service 本文转自 OpenStack2015 博客,原文链接: http://blog.51cto.com/andyliu/2069166 如需转载请自行联系原作者

优秀的个人博客,低调大师

CentOS7手动安装OpenStack Pike版--(horizon)

OpenStack安装指南_Mitakahttp://down.51cto.com/data/2331199 Openstack管理手册-Newton版-CentOS7.2http://down.51cto.com/data/2331201 #Configure horizon Edit the /etc/openstack-dashboard/local_settings OPENSTACK_HOST = "controller" ALLOWED_HOSTS = ['*', ] SESSION_ENGINE = 'django.contrib.sessions.backends.cache' CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': 'controller:11211', }, } OPENSTACK_KEYSTONE_URL = "http://%s:5000/v2.0" % OPENSTACK_HOST OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True OPENSTACK_API_VERSIONS = { "data-processing": 1.1, "identity": 3, "image": 2, "volume": 2, "compute": 2, } OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default' OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user" TIME_ZONE = "Asia/Shanghai" systemctl restart httpd.service memcached.service controller节点安装完成,访问Dashboardhttp://192.168.137.145/dashboard/ 本文转自 OpenStack2015 博客,原文链接: http://blog.51cto.com/andyliu/2069169 如需转载请自行联系原作者

优秀的个人博客,低调大师

每日一博 | 请求分级与限流——手动打造服务网关

转载本文需注明出处:微信公众号EAWorld,违者必究。 项目背景 雪崩一词指的是山地积雪由于底部溶解等原因而突然大块塌落的现象,具有很强的破坏力。在系统架构中提到的雪崩,就是由于一台服务器或者一台服务器中的某个模块发生故障进而引起连锁反应,最后导致大量的服务器或者软件模块无法正常工作,这种现象也较做“急剧变化”现象。 在某通信集团统一流程平台项目上线初期就发生过几次服务雪崩的事故,由于业务系统接入持续增多,业务系统的查询请求数量大大高于了前期的设计。当集群中的一台节点宕机下线后,请求压力迅速传导给了整个集群,从而引发了集群整体宕机。 解决方案 为了保障平台整体能稳定运行,在重新对服务器负载进行估算、增加集群冗余后,项目组增加了在部署架构、压力负载分流方面考虑,以持续提升平台性能。 我们对现有平台集群的逻辑架构进行了调整,将业务访问请求按系统ID分流到各子集群,由各集群分开处理,通过对业务请求的细分,达到子集群隔离,提升系统的稳定性与可扩展性。 具体到实施层面,项目组预备在负载均衡上增加服务网关的功能,使得nginx集群不再单纯的做反向代理,而是扩展为服务网关。 服务网关 服务网关基于openresty开发,OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。 我们在其基础上实现了以下功能: 流量限制:设立限流名单制度,对于非VIP且请求量大的用户进行限流。对名单中用户的请求进行计数,限制用户每分钟的请求次数,避免重复调用或短期内大量无效请求。 请求分域:根据请求来源的租户实现请求分域,将不同的租户请求分发到该租户的专用集群。 健康检查:提供一个简单的查询页面,可以查询当前集群节点的健康状况。 部署架构调整 在改造网关之前,我们首先要对集群的物理架构进行调整。通过对统一平台的业务量以及调用量的统计,以及对业务请求的监控我们发现,无论从业务数量以及调用量来看,业务压力主要来自于其中的两个业务系统。 于是我们对现有架构进行了调整,将负载均衡随机分发请求到集群,调整为按系统分发,将一个大集群切割成若干个小集群,按请求所在的系统将请求分发到各自响应的集群中。 请求分域 首先我们已经通过调整集群的部署,将集群进行了物理分割,接下来我们只需要将相关系统的请求转发到对应的集群中即可。 首先通过获取每个请求的请求头,来获得该请求的所属系统、所属用户等关键信息。 map $host $fmt_localtime { default '';}map $host $bpm_method { default '';}map $host $bpm_tenantid { default '';}map $host $bpm_province { default '';}map $host $bpm_userid { default '';}map $host $bpm_provinceFlag { default '';}map$host$RequestId{default'';} (左右滑动查看全部代码) 然后我们在脚本中定义好每个系统的节点地址 #报账upstream bpm_cluster_rbs {server 10.24.20.45:8080;server 10.24.20.46:8080;……server 10.24.20.52:8080; }#合同upstream bpm_cluster_cms {server 10.24.20.53:8080;……server 10.24.20.60:8080;}#其他upstream bpm_cluster_other {server 10.24.20.10:8080;……server 10.24.20.16:8080;} (左右滑动查看全部代码) 最后当收到请求时,将对应请求转发到对应的upstream就可以了 functionforwardUpstream(tenantid)iftenantid=="CMS"--对于合同系统而且是查询待办相关操作thenngx.var.upstream="bpm_cluster_cms"elseiftenantid=="RBS"--对于报账系统而且是查询待办相关操作thenngx.var.upstream="bpm_cluster_rbs"elsengx.var.upstream="bpm_cluster_other"enden (左右滑动查看全部代码) 限流 lua-resty-limit-traffic是一个openresty中用于限制和控制流量的Lua库,使用这个库可以方便的对用户、IP进行限流 https://github.com/openresty/lua-resty-limit-traffic (左右滑动查看全部代码) lua-resty-limit-traffic模块限流分为两种: 第一种限制某用户每分钟只能调用120次(允许在时间段开始的时候一次性放过120个请求) local limit_count = require "resty.limit.count"local lim, err = limit_count.new("my_limit_count_store", 120, 60) (左右滑动查看全部代码) 第二种限制每分钟处理120个请求(平滑处理,每秒钟只放过两个请求) local limit_req = require "resty.limit.req"local lim, err = limit_req.new("my_limit_req_store", 2, 0) (左右滑动查看全部代码) 实战中,我们的策略是将流量大的用户加入到限流名单中,名单内的用户会在redis中维护一份配置表,包括 在请求进来后,我们先从请求头中获取当前请求的用户 map $host $bpm_userid { default '';} (左右滑动查看全部代码) 然后判断该用户是否在限流名单内,如果确定为限流用户则读取该用户的配置信息 local cache_ngx = ngx.shared.my_ngx_redis_cachelocal user_conf = cache_ngx:get(userid)local redis_josn = cjson.decode(user_conf)local maxReq = redis_josn['maxReq']local nextReqTime = redis_josn['nextReqTime'] (左右滑动查看全部代码) 根据配置调用限流方法,设置某用户每分钟只能调用XX次请求(允许一次性放过) local limit_count = require "resty.limit.count"local maxReq = redis_josn['maxReq']local nextReqTime = redis_josn['nextReqTime']local lim, err = limit_count.new("my_limit_count_store", maxReq, nextReqTime)if not lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.count object: ", err) return ngx.exit(500)endlocal delay, err = lim:incoming(key, true)-- 如果发生错误则返回500,如果请求数超过了 count 限制则返回403if not delay then if err == "rejected" then return ngx.exit(403) end ngx.log(ngx.ERR, "failed to limit count:", err) return ngx.exit(500)end (左右滑动查看全部代码) 健康检查 upstream.healthcheck本质上是个定时器,它会定期发送指定的http请求并解析响应码,去探测upstream中每个peer的存活状态,再结合历史请求记录来判断并标记其状态。 模块的源码见下面的页面: https://github.com/openresty/lua-resty-upstream-healthcheck (左右滑动查看全部代码) 实战中我们的代码如下: local ok, err = hc.spawn_checker{ shm = "healthcheck", -- defined by "lua_shared_dict" upstream = "bpm_cluster_rbs", -- defined by "upstream" type = "http", http_req = "GET /default/engineState.jsp HTTP/1.0\r\nHost: bpm_cluster_rbs\r\n\r\n", -- raw HTTP request for checking interval = 2000, -- 每两秒检查一次 timeout = 1000, -- 1 sec is the timeout for network operations fall = 3, -- # 连续3次失败才认定为down rise = 2, -- # 对down状态的节点,连续2次成功认定为UP valid_statuses = {200, 302}, -- 状态正常的code concurrency = 10, -- 检查线程数} (左右滑动查看全部代码) 关于作者:李云涛,普元高级开发工程师,擅长性能调优、微服务、容器、消息队列等技术。先后参与邮储银行Java开发平台、中移总ERP流程平台、中煤信息技术中台等平台的的架构设计与平台研发工作。 关于EAWorld:使能数字转型,共创数智未来,长按二维码关注! 本文分享自微信公众号 - EAWorld(eaworld)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Oracle

Oracle

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

Apache Tomcat

Apache Tomcat

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。