• 关于

    java 计时 执行

    的搜索结果

问题

java 任务执行(非定时任务)绑定处理对象问题 - java报错

montos 2020-06-04 22:04:32 2 浏览量 回答数 1

回答

1、为所有的Activity定义一个基类BaseActivity,程序中的所有Activity都继承自这个基类。 2、重写BaseActivity的dispatchTouchEvent()方法,只要监听到此方法,表明用户操作,纪录这个时间。 3、写一个定时器Timer,每1秒检查一次当前系统时间上次操作的时间,如果时间差大于5s,则自动退出(1s、5s自己设定)。 4、示例代码如下: 4.1 MainActivity.java public class MainActivity extends BaseActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 登录成功,开始计时 startTimer(); } } 4.2 BaseActivity.java public class BaseActivity extends Activity { // 都是static声明的变量,避免被实例化多次;因为整个app只需要一个计时任务就可以了。 private static Timer mTimer; // 计时器,每1秒执行一次任务 private static MyTimerTask mTimerTask; // 计时任务,判断是否未操作时间到达5s private static long mLastActionTime; // 上一次操作时间 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } // 每当用户接触了屏幕,都会执行此方法 @Override public boolean dispatchTouchEvent(MotionEvent ev) { mLastActionTime = System.currentTimeMillis(); Log.e("wanghang", "user action"); return super.dispatchTouchEvent(ev); } private static class MyTimerTask extends TimerTask { @Override public void run() { Log.e("wanghang", "check time"); // 5s未操作 if (System.currentTimeMillis() - mLastActionTime > 5000) { // 退出登录 exit(); // 停止计时任务 stopTimer(); } } } // 退出登录 protected static void exit() { } // 登录成功,开始计时 protected static void startTimer() { mTimer = new Timer(); mTimerTask = new MyTimerTask(); // 初始化上次操作时间为登录成功的时间 mLastActionTime = System.currentTimeMillis(); // 每过1s检查一次 mTimer.schedule(mTimerTask, 0, 1000); Log.e("wanghang", "start timer"); } // 停止计时任务 protected static void stopTimer() { mTimer.cancel(); Log.e("wanghang", "cancel timer"); } }

爵霸 2019-12-02 02:24:07 0 浏览量 回答数 0

问题

关于java的消息传递的问题

爵霸 2019-12-01 19:35:31 861 浏览量 回答数 1

阿里云高校特惠,助力学生创业梦!0元体验,快速入门云计算!

学生动手场景应用,快速了解并掌握云服务器的各种新奇玩法!

问题

android在Activity实例化abstract类出错? 400 报错

爱吃鱼的程序员 2020-06-04 15:18:32 1 浏览量 回答数 1

问题

EMR 常见问题?

nicenelly 2019-12-01 21:19:58 2355 浏览量 回答数 0

回答

根据 java 文档,倒计时是同步辅助,允许一个或多个线程等待,直到在其他线程中执行的操作集完成。换句话说,CountDownLatch 等待其他线程完成一组操作。 CountDownLatch使用计数进行初始化。任何线程通常主线程调用 latch.awaits() 方法,因此它将等待计数变为零或被另一个线程中断,所有其他线程在完成某些操作后都需要调用 latch.countDown()。 因此,每当调用 latch.countDown() 方法时,计数将减少 1,因此,如果计数为 n,则意味着计数可以用作 n 个线程才能完成某些操作或必须完成一些操作 n 次

YDYK 2020-04-24 20:00:59 0 浏览量 回答数 0

问题

我写了两段代码,几乎完全一样,但是其中一个的运行速度比另一个(Java)快得多

七天一失眠 2020-04-11 15:50:33 0 浏览量 回答数 1

回答

方法一: 利用java的类Timer,TimerTask还有android的Handler 界面welcome_activity.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" http://schemas.android.com/apk/res/android" xmlns:tools=" http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/count_down" android:layout_width="60dp" android:layout_height="60dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="16dp" android:layout_marginTop="16dp" android:gravity="center" android:textSize="32sp" android:textColor="#50000000" android:background="@drawable/count_down_background" tools:text="2" /> </RelativeLayout> package com.example.counttimer; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.widget.TextView; public class WelcomeActivity extends Activity { private final static int COUNT = 1; private TextView countDown; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_welcome); initView(); } //sehedule的第而个参数是第一次启动延时的时间,第三个是每隔多长时间执行一次。单位都是ms。  //因此这里是每一秒发送一次消息给handler更新UI。  //然后三秒后时间到了,在timer的第二个sehedule中进行跳转到另外一个界面 private void initView() { countDown = (TextView) findViewById(R.id.count_down); final Timer timer = new Timer(); final long end = System.currentTimeMillis() + 1000*3; timer.schedule(new TimerTask() { @Override public void run() { handler.sendEmptyMessage(COUNT); } }, 0, 1000); //这里的schedule的第二个参数意义是到了这个时间尽快运行run里面的方法 timer.schedule(new TimerTask() { @Override public void run() { Intent i = new Intent(WelcomeActivity.this, SecondActivity.class); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(i); finish(); timer.cancel(); } }, new Date(end)); } private Handler handler = new Handler(){ int num = 2; public void handleMessage(android.os.Message msg) { switch (msg.what) { case COUNT: countDown.setText(String.valueOf(num)); num--; break; default: break; } }; }; } count_down_background.xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android=" http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="8dp"/> <solid android:color="#1e000000"/> </shape> 方法二 : 利用android封装的类CountDownTimer。其实内部也是用Handler实现的。其他都一样。 package com.example.counttimer; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.CountDownTimer; import android.view.Window; import android.widget.TextView; public class WelcomeActivity extends Activity { private final static int COUNT = 1; private TextView countDown; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_welcome); initView(); } private void initView() { countDown = (TextView) findViewById(R.id.count_down);    //CountDownTimer构造器的两个参数分别是第一个参数表示总时间,第二个参数表示间隔时间。    //意思就是每隔xxx会回调一次方法onTick,然后xxx之后会回调onFinish方法。 CountDownTimer timer = new CountDownTimer(3200,1000) { int num = 2; @Override public void onTick(long millisUntilFinished) { countDown.setText(String.valueOf(num)); num--; } @Override public void onFinish() {          //计时完成调用 Intent i = new Intent(WelcomeActivity.this, SecondActivity.class); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(i); finish(); } }; timer.start(); } } 答案来源于网络

养狐狸的猫 2019-12-02 03:02:55 0 浏览量 回答数 0

问题

【精品问答】E-MapReduce

montos 2020-04-08 15:00:05 2 浏览量 回答数 1

回答

推荐工具 1、Linx: Linx 是一款低代码的 IDE 和服务器。IT 专业人员使用 Linx 可以快速创建自定义的自动化业务流程、集成应用程序、公开 Web 服务,并有效地处理高工作负载。 易用使用的拖放式界面。 超过 100 种预建功能和服务,可实现快速开发。 直接从 IDE 一键部署到任何本地或远程 Linx 服务器。 输入和输出包括几乎所有的 SQL 和 NoSQL 数据库、大量文件格式(文本和二进制)或 REST 和 SOAP Web 服务。 使用分步逻辑进行现场调试。 通过计时器、目录事件或消息队列将后端流程自动化,或者公开 Web 服务,并通过 HTTP 请求调用 API。 下载链接:https://linx.software/lowcode-application-designer/?utm=99 2、Buddy Buddy 是一款面向 Web 开发人员的智能 CI/CD 工具,旨在降低 DevOps 的入门门槛。它使用交付管道来构建、测试和部署软件。这些管道由 100 多个随时可用的动作创建的,这些动作可以以任何方式进行安排,就像你用砖头建造房子一样。 15 分钟的配置,清晰易懂的用户界面 / 用户体验。 基于变更集的快速部署。 构建在具有缓存依赖项的独立容器中运行。 支持所有流行语言、框架和任务管理器。 Docker/Kubernetes 动作专用名册。 与 AWS、Google、DigitalOcean、Azure、Shopify、WordPress 等集成。 支持并行和 YAML 配置。 下载链接:https://buddy.works/ IDE (集成开发环境) 3、NetBeans NetBeans 是一款流行的免费开源 IDE。它可以用来开发桌面、移动和 Web 应用程序。 支持快速和智能代码编辑。 简单高效的项目管理流程。 快速用户界面开发。 帮助编写无 Bug 代码。 NetBeans IDE 为 C/C++ 和 PHP 开发人员提供了卓越的支持。 它可以安装在任何支持 Java 的操作系统上,从 Windows 到 Linux,再到 Mac OSX 系统。 下载链接:https://netbeans.org/downloads/index.html 4、Cloud9 IDE Cloud9 IDE 是一款在线集成软件开发环境。它支持许多编程语言,如 C、C++、PHP、Ruby、Perl、Python、JavaScript 和 Node.js。 允许克隆整个开发环境。 命令行想到的内置终端。 代码完成建议的功能可以帮助软件开发人员更快地编写代码并避免输入错误。 调试器可帮助开发人员设置断点,并检查任何 JS/Node.js 应用的变量。 只需拖动任何文件或终端即可创建多个拆分视图。 开发人员可以选择广泛的默认运行程序来执行应用程序,如 Ruby、Pythn、PHP/Apache。 下载链接:https://c9.io/pricing

有只黑白猫 2020-01-20 17:21:34 0 浏览量 回答数 0

回答

推荐工具 1、Linx: Linx 是一款低代码的 IDE 和服务器。IT 专业人员使用 Linx 可以快速创建自定义的自动化业务流程、集成应用程序、公开 Web 服务,并有效地处理高工作负载。 易用使用的拖放式界面。 超过 100 种预建功能和服务,可实现快速开发。 直接从 IDE 一键部署到任何本地或远程 Linx 服务器。 输入和输出包括几乎所有的 SQL 和 NoSQL 数据库、大量文件格式(文本和二进制)或 REST 和 SOAP Web 服务。 使用分步逻辑进行现场调试。 通过计时器、目录事件或消息队列将后端流程自动化,或者公开 Web 服务,并通过 HTTP 请求调用 API。 下载链接:https://linx.software/lowcode-application-designer/?utm=99 2、Buddy Buddy 是一款面向 Web 开发人员的智能 CI/CD 工具,旨在降低 DevOps 的入门门槛。它使用交付管道来构建、测试和部署软件。这些管道由 100 多个随时可用的动作创建的,这些动作可以以任何方式进行安排,就像你用砖头建造房子一样。 15 分钟的配置,清晰易懂的用户界面 / 用户体验。 基于变更集的快速部署。 构建在具有缓存依赖项的独立容器中运行。 支持所有流行语言、框架和任务管理器。 Docker/Kubernetes 动作专用名册。 与 AWS、Google、DigitalOcean、Azure、Shopify、WordPress 等集成。 支持并行和 YAML 配置。 下载链接:https://buddy.works/ IDE (集成开发环境) 3、NetBeans NetBeans 是一款流行的免费开源 IDE。它可以用来开发桌面、移动和 Web 应用程序。 支持快速和智能代码编辑。 简单高效的项目管理流程。 快速用户界面开发。 帮助编写无 Bug 代码。 NetBeans IDE 为 C/C++ 和 PHP 开发人员提供了卓越的支持。 它可以安装在任何支持 Java 的操作系统上,从 Windows 到 Linux,再到 Mac OSX 系统。 下载链接:https://netbeans.org/downloads/index.html 4、Cloud9 IDE Cloud9 IDE 是一款在线集成软件开发环境。它支持许多编程语言,如 C、C++、PHP、Ruby、Perl、Python、JavaScript 和 Node.js。 允许克隆整个开发环境。 命令行想到的内置终端。 代码完成建议的功能可以帮助软件开发人员更快地编写代码并避免输入错误。 调试器可帮助开发人员设置断点,并检查任何 JS/Node.js 应用的变量。 只需拖动任何文件或终端即可创建多个拆分视图。 开发人员可以选择广泛的默认运行程序来执行应用程序,如 Ruby、Pythn、PHP/Apache。 下载链接:https://c9.io/pricing

有只黑白猫 2020-01-08 17:49:54 0 浏览量 回答数 0

问题

某政务网站性能优化

猫饭先生 2019-12-01 21:25:38 1412 浏览量 回答数 0

问题

【javascript学习全家桶】934道javascript热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:22 6202 浏览量 回答数 1

回答

阿里云ECS在已有的系统事件的基础上,通过云监控新发布了状态变化类事件和抢占型实例的中断通知事件。每当ECS实例的状态发生变化的时候,都会触发一条ECS实例状态变化事件。这种变化包括您在控制台/OpenAPI/SDK操作导致的变化,也包括弹性伸缩或欠费等原因而自动触发的变化,还包括因为系统异常而触发的变化。 云监控以前发布的系统事件,主要针对告警后人工介入的场景,而这次新发布的事件属于正常类的信息通知,适合自动化的审计运维等场景。为了自动化处理ECS状态变化事件,云监控提供了两种主要途径:一种是通过函数计算,另一种是通过MNS消息队列。本文将为您介绍利用MNS消息队列自动化处理ECS事件的三种最佳实践。 自动化处理ECS状态变化事件的准备工作 创建消息队列 登录MNS控制台。 在队列列表页面,选择地域,单击右上角的创建队列,进入新建队列页面。 输入队列的名称(例如“ecs-cms-event”)等信息,单击确认即可完成创建消息队列。 创建事件报警规则 登录云监控控制台。 单击左侧导航栏中的事件监控,进入事件查询页面 单击报警规则页签,然后单击右上角的创建事件报警,弹出创建/修改事件报警对话框。 在基本信息区域,填写报警规则名称,例如如“ecs-test-rule”。 设置事件报警规则:选择事件类型为系统事件。 产品类型、事件等级、事件名称:产品类型选择云服务器ECS,事件类型选择StatusNotification,其余按照实际情况填写。 资源范围:选择全部资源时,任何资源发生相关事件,都会按照配置发送通知;选择应用分组时,只有指定分组内的资源发生相关事件时,才会发送通知。 在报警方式中,选择消息队列,然后选择地域和队列(例如ecs-cms-event)。 完成以上设置后,单击确定按钮即可完成创建事件报警规则。 安装Python依赖 本文所有的代码均使用Python 3.6测试通过,您也可以使用Java等其他编程语言。 请使用Pypi安装以下Python依赖: aliyun-python-sdk-core-v3>=2.12.1 aliyun-python-sdk-ecs>=4.16.0 aliyun-mns>=1.1.5 自动化处理ECS状态变化事件的实施步骤 云监控会把云服务器ECS所有的状态变化事件都投递到MNS里面,接下来我们需要通过编写代码从MNS获取消息并进行消息处理。 实践一:对所有ECS的创建和释放事件进行记录 目前ECS控制台无法查询已经释放的实例。如果您有查询需求,可以通过ECS状态变化事件把所有ECS的生命周期记录在自己的数据库或者日志里。每当创建ECS时,会首先发送一个Pending事件,每当释放ECS时,会最后发送一个Deleted事件。我们需要对这两种事件进行记录。 编辑一个Conf文件。需包含mns的endpoint(可以登录MNS的控制台,在队列列表页,单击获取Endpoint得到)、阿里云的access key和secrect、region id(例如cn-beijing)以及mns queue的名字。 class Conf: endpoint = 'http://<id>.mns.<region>.aliyuncs.com/' access_key = '<access_key>' access_key_secret = '<access_key_secrect>' region_id = 'cn-beijing' queue_name = 'test' vsever_group_id = '<your_vserver_group_id>' 使用MNS的SDK编写一个MNS Client用来获取MNS消息。 # -*- coding: utf-8 -*- import json from mns.mns_exception import MNSExceptionBase import logging from mns.account import Account from . import Conf class MNSClient(object): def __init__(self): self.account = Account(Conf.endpoint, Conf.access_key, Conf.access_key_secret) self.queue_name = Conf.queue_name self.listeners = dict() def regist_listener(self, listener, eventname='Instance:StateChange'): if eventname in self.listeners.keys(): self.listeners.get(eventname).append(listener) else: self.listeners[eventname] = [listener] def run(self): queue = self.account.get_queue(self.queue_name) while True: try: message = queue.receive_message(wait_seconds=5) event = json.loads(message.message_body) if event['name'] in self.listeners: for listener in self.listeners.get(event['name']): listener.process(event) queue.delete_message(receipt_handle=message.receipt_handle) except MNSExceptionBase as e: if e.type == 'QueueNotExist': logging.error('Queue %s not exist, please create queue before receive message.', self.queue_name) else: logging.error('No Message, continue waiting') class BasicListener(object): def process(self, event): pass 上述代码只是对MNS消息进行拉取,调用Listener消费消息之后删除消息,后面的实践也会用到。 注册一个Listener进消费指定事件。这个简单的Listener判断收到Pending和Deleted事件时,打印一行日志。 # -*- coding: utf-8 -*- import logging from .mns_client import BasicListener class ListenerLog(BasicListener): def process(self, event): state = event['content']['state'] resource_id = event['content']['resourceId'] if state == 'Panding': logging.info(f'The instance {resource_id} state is {state}') elif state == 'Deleted': logging.info(f'The instance {resource_id} state is {state}') Main函数可以这么写: mns_client = MNSClient() mns_client.regist_listener(ListenerLog()) mns_client.run() 实际生产环境下,可能需要把事件存储在数据库里,或者利用SLS日志服务,方便后期的搜索和审计。 实践二:ECS的关机自动重启 在某些场景下,ECS会非预期的关机,您可能需要自动重启已经关机的ECS。 为了实现这一目的,我们复用实践一里面的MNS Client,添加一个新的Listener。当收到Stopped事件的时候,对该ECS执行一个Start命令。 -- coding: utf-8 -- import logging from aliyunsdkecs.request.v20140526 import StartInstanceRequest from aliyunsdkcore.client import AcsClient from .mns_client import BasicListener from .config import Conf class ECSClient(object): def init(self, acs_client): self.client = acs_client # 启动ECS实例 def start_instance(self, instance_id): logging.info(f'Start instance {instance_id} ...') request = StartInstanceRequest.StartInstanceRequest() request.set_accept_format('json') request.set_InstanceId(instance_id) self.client.do_action_with_exception(request) class ListenerStart(BasicListener): def init(self): acs_client = AcsClient(Conf.access_key, Conf.access_key_secret, Conf.region_id) self.ecs_client = ECSClient(acs_client) def process(self, event): detail = event['content'] instance_id = detail['resourceId'] if detail['state'] == 'Stopped': self.ecs_client.start_instance(instance_id) 在实际生产环境下,执行完Start命令后,可能还需要继续接收后续的Starting/Running/Stopped等事件,再配合计时器和计数器,进行Start成功或失败之后的处理。 实践三:抢占型实例释放前,自动从SLB移除 抢占型实例在释放之前五分钟左右,会发出释放告警事件,您可以利用这短暂的时间运行一些业务不中断的逻辑。例如,主动从SLB的后端服务器中去掉这台即将被释放的抢占型实例,而不是被动等待实例释放后SLB的自动处理。 我们还是复用实践一的MNS Client,添加一个新的Listener,当收到抢占型实例的释放告警时,调用SLB的SDK。 -- coding: utf-8 -- from aliyunsdkcore.client import AcsClient from aliyunsdkcore.request import CommonRequest from .mns_client import BasicListener from .config import Conf class SLBClient(object): def init(self): self.client = AcsClient(Conf.access_key, Conf.access_key_secret, Conf.region_id) self.request = CommonRequest() self.request.set_method('POST') self.request.set_accept_format('json') self.request.set_version('2014-05-15') self.request.set_domain('slb.aliyuncs.com') self.request.add_query_param('RegionId', Conf.region_id) def remove_vserver_group_backend_servers(self, vserver_group_id, instance_id): self.request.set_action_name('RemoveVServerGroupBackendServers') self.request.add_query_param('VServerGroupId', vserver_group_id) self.request.add_query_param('BackendServers', "[{'ServerId':'" + instance_id + "','Port':'80','Weight':'100'}]") response = self.client.do_action_with_exception(self.request) return str(response, encoding='utf-8') class ListenerSLB(BasicListener): def init(self, vsever_group_id): self.slb_caller = SLBClient() self.vsever_group_id = Conf.vsever_group_id def process(self, event): detail = event['content'] instance_id = detail['instanceId'] if detail['action'] == 'delete': self.slb_caller.remove_vserver_group_backend_servers(self.vsever_group_id, instance_id)

景凌凯 2020-03-25 22:23:53 0 浏览量 回答数 0

回答

本文通过实践案例为您介绍云监控如何利用MNS消息队列实现自动化处理ECS状态变化事件。 背景信息 阿里云ECS在已有的系统事件的基础上,通过云监控新发布了状态变化类事件和抢占型实例的中断通知事件。每当ECS实例的状态发生变化的时候,都会触发一条ECS实例状态变化事件。这种变化包括您在控制台/OpenAPI/SDK操作导致的变化,也包括弹性伸缩或欠费等原因而自动触发的变化,还包括因为系统异常而触发的变化。 云监控以前发布的系统事件,主要针对告警后人工介入的场景,而这次新发布的事件属于正常类的信息通知,适合自动化的审计运维等场景。为了自动化处理ECS状态变化事件,云监控提供了两种主要途径:一种是通过函数计算,另一种是通过MNS消息队列。本文将为您介绍利用MNS消息队列自动化处理ECS事件的三种最佳实践。 自动化处理ECS状态变化事件的准备工作 创建消息队列 登录MNS控制台。 在队列列表页面,选择地域,单击右上角的创建队列,进入新建队列页面。 输入队列的名称(例如“ecs-cms-event”)等信息,单击确认即可完成创建消息队列。 创建事件报警规则 登录云监控控制台。 单击左侧导航栏中的事件监控,进入事件查询页面 单击报警规则页签,然后单击右上角的创建事件报警,弹出创建/修改事件报警对话框。 在基本信息区域,填写报警规则名称,例如如“ecs-test-rule”。 设置事件报警规则:选择事件类型为系统事件。 产品类型、事件等级、事件名称:产品类型选择云服务器ECS,事件类型选择StatusNotification,其余按照实际情况填写。 资源范围:选择全部资源时,任何资源发生相关事件,都会按照配置发送通知;选择应用分组时,只有指定分组内的资源发生相关事件时,才会发送通知。 在报警方式中,选择消息队列,然后选择地域和队列(例如ecs-cms-event)。 完成以上设置后,单击确定按钮即可完成创建事件报警规则。 安装Python依赖 本文所有的代码均使用Python 3.6测试通过,您也可以使用Java等其他编程语言。 请使用Pypi安装以下Python依赖: aliyun-python-sdk-core-v3>=2.12.1 aliyun-python-sdk-ecs>=4.16.0 aliyun-mns>=1.1.5 自动化处理ECS状态变化事件的实施步骤 云监控会把云服务器ECS所有的状态变化事件都投递到MNS里面,接下来我们需要通过编写代码从MNS获取消息并进行消息处理。 实践一:对所有ECS的创建和释放事件进行记录 目前ECS控制台无法查询已经释放的实例。如果您有查询需求,可以通过ECS状态变化事件把所有ECS的生命周期记录在自己的数据库或者日志里。每当创建ECS时,会首先发送一个Pending事件,每当释放ECS时,会最后发送一个Deleted事件。我们需要对这两种事件进行记录。 编辑一个Conf文件。需包含mns的endpoint(可以登录MNS的控制台,在队列列表页,单击获取Endpoint得到)、阿里云的access key和secrect、region id(例如cn-beijing)以及mns queue的名字。 class Conf: endpoint = 'http:// .mns. .aliyuncs.com/' access_key = '<access_key>' access_key_secret = '<access_key_secrect>' region_id = 'cn-beijing' queue_name = 'test' vsever_group_id = '<your_vserver_group_id>' 使用MNS的SDK编写一个MNS Client用来获取MNS消息。 -- coding: utf-8 -- import json from mns.mns_exception import MNSExceptionBase import logging from mns.account import Account from . import Conf class MNSClient(object): def init(self): self.account = Account(Conf.endpoint, Conf.access_key, Conf.access_key_secret) self.queue_name = Conf.queue_name self.listeners = dict() def regist_listener(self, listener, eventname='Instance:StateChange'): if eventname in self.listeners.keys(): self.listeners.get(eventname).append(listener) else: self.listeners[eventname] = [listener] def run(self): queue = self.account.get_queue(self.queue_name) while True: try: message = queue.receive_message(wait_seconds=5) event = json.loads(message.message_body) if event['name'] in self.listeners: for listener in self.listeners.get(event['name']): listener.process(event) queue.delete_message(receipt_handle=message.receipt_handle) except MNSExceptionBase as e: if e.type == 'QueueNotExist': logging.error('Queue %s not exist, please create queue before receive message.', self.queue_name) else: logging.error('No Message, continue waiting') class BasicListener(object): def process(self, event): pass 上述代码只是对MNS消息进行拉取,调用Listener消费消息之后删除消息,后面的实践也会用到。 注册一个Listener进消费指定事件。这个简单的Listener判断收到Pending和Deleted事件时,打印一行日志。 # -- coding: utf-8 -- import logging from .mns_client import BasicListener class ListenerLog(BasicListener): def process(self, event): state = event['content']['state'] resource_id = event['content']['resourceId'] if state == 'Panding': logging.info(f'The instance {resource_id} state is {state}') elif state == 'Deleted': logging.info(f'The instance {resource_id} state is {state}') Main函数可以这么写: mns_client = MNSClient() mns_client.regist_listener(ListenerLog()) mns_client.run() 实际生产环境下,可能需要把事件存储在数据库里,或者利用SLS日志服务,方便后期的搜索和审计。 实践二:ECS的关机自动重启 在某些场景下,ECS会非预期的关机,您可能需要自动重启已经关机的ECS。 为了实现这一目的,我们复用实践一里面的MNS Client,添加一个新的Listener。当收到Stopped事件的时候,对该ECS执行一个Start命令。 -- coding: utf-8 -- import logging from aliyunsdkecs.request.v20140526 import StartInstanceRequest from aliyunsdkcore.client import AcsClient from .mns_client import BasicListener from .config import Conf class ECSClient(object): def init(self, acs_client): self.client = acs_client # 启动ECS实例 def start_instance(self, instance_id): logging.info(f'Start instance {instance_id} ...') request = StartInstanceRequest.StartInstanceRequest() request.set_accept_format('json') request.set_InstanceId(instance_id) self.client.do_action_with_exception(request) class ListenerStart(BasicListener): def init(self): acs_client = AcsClient(Conf.access_key, Conf.access_key_secret, Conf.region_id) self.ecs_client = ECSClient(acs_client) def process(self, event): detail = event['content'] instance_id = detail['resourceId'] if detail['state'] == 'Stopped': self.ecs_client.start_instance(instance_id) 在实际生产环境下,执行完Start命令后,可能还需要继续接收后续的Starting/Running/Stopped等事件,再配合计时器和计数器,进行Start成功或失败之后的处理。 实践三:抢占型实例释放前,自动从SLB移除 抢占型实例在释放之前五分钟左右,会发出释放告警事件,您可以利用这短暂的时间运行一些业务不中断的逻辑。例如,主动从SLB的后端服务器中去掉这台即将被释放的抢占型实例,而不是被动等待实例释放后SLB的自动处理。 我们还是复用实践一的MNS Client,添加一个新的Listener,当收到抢占型实例的释放告警时,调用SLB的SDK。 -- coding: utf-8 -- from aliyunsdkcore.client import AcsClient from aliyunsdkcore.request import CommonRequest from .mns_client import BasicListener from .config import Conf class SLBClient(object): def init(self): self.client = AcsClient(Conf.access_key, Conf.access_key_secret, Conf.region_id) self.request = CommonRequest() self.request.set_method('POST') self.request.set_accept_format('json') self.request.set_version('2014-05-15') self.request.set_domain('slb.aliyuncs.com') self.request.add_query_param('RegionId', Conf.region_id) def remove_vserver_group_backend_servers(self, vserver_group_id, instance_id): self.request.set_action_name('RemoveVServerGroupBackendServers') self.request.add_query_param('VServerGroupId', vserver_group_id) self.request.add_query_param('BackendServers', "[{'ServerId':'" + instance_id + "','Port':'80','Weight':'100'}]") response = self.client.do_action_with_exception(self.request) return str(response, encoding='utf-8') class ListenerSLB(BasicListener): def init(self, vsever_group_id): self.slb_caller = SLBClient() self.vsever_group_id = Conf.vsever_group_id def process(self, event): detail = event['content'] instance_id = detail['instanceId'] if detail['action'] == 'delete': self.slb_caller.remove_vserver_group_backend_servers(self.vsever_group_id, instance_id) 注意 抢占型实例释放告警的event name与前面不同,应该是“Instance:PreemptibleInstanceInterruption”, mns_client.regist_listener(ListenerSLB(Conf.vsever_group_id), 'Instance:PreemptibleInstanceInterruption') 在实际生产环境下,您可能需要再申请一台新的抢占型实例,挂载到SLB上,来保证服务能力。

1934890530796658 2020-03-25 19:15:43 0 浏览量 回答数 0

回答

给各位一个反馈信息,目前问题已解决,原先的检验线程是一小时连接一次数据库,改成十五分钟一次之后程序跑到现在差不多一周时间,还没出现异常。具体原因有大神能解释一下吗? 看这异常好像是定时器中事务提交失败,检查方法事务配置以及Mysql表引擎。表引擎是InnoDB,应该没有问题同意是数据库连接问题 数据库的连接池是用的什么的。 我们公司我是位了保证系统稳定性,凌晨会重启tomcat的。因为是基于spring封装的私有框架,连接池的配置都是已经做好的。具体哪里做的配置我还没找到,不过看maven中引用的jar包连接池用的是c3p0mysql主动断开的 Mysql的8小时超时问题?加个检验语句,每小时检验一下,连接池就不会被数据库单方面断开了。回复<aclass='referer'target='_blank'>@xdjames:连接池配置的最小连接数(闲置的)大于1,你的检验线程,就有可能总是只请求到其中的一个来校验。其他的连接,可能无法被检验语句执行到。连接池配置方式的检验语句,是连接池自己来管理的,对每个闲置超过一个小时的连接,都去检验一次,保证每个超过1小时闲置时间的连接,重新开始计时。刚开始的报错确实是8小时超时问题,后来启了个线程每小时读数据库一次,然后就报这个错了 <spanstyle="font-size:10pt;line-height:1.5;">Connection conn = <spanstyle="font-size:10pt;line-height:1.5;color:#006699;font-weight:bold;">null<spanstyle="font-size:10pt;line-height:1.5;">; <spanstyle="color:black;">    Statement stmt = <spanstyle="color:#006699;font-weight:bold;">null;  <spanstyle="color:black;">    ResultSet rs = <spanstyle="color:#006699;font-weight:bold;">null;  <spanstyle="color:black;">    <spanstyle="color:#006699;font-weight:bold;">int retryCount = <spanstyle="color:#C00000;">5;  <spanstyle="color:black;">    <spanstyle="color:#006699;font-weight:bold;">boolean transactionCompleted = <spanstyle="color:#006699;font-weight:bold;">false;  <spanstyle="color:black;">    <spanstyle="color:#006699;font-weight:bold;">do {  <spanstyle="color:black;">        <spanstyle="color:#006699;font-weight:bold;">try {  <spanstyle="color:black;">            conn = getConnection(); <spanstyle="color:#008200;">// assume getting this from a  <spanstyle="color:black;">                                    <spanstyle="color:#008200;">// javax.sql.DataSource, or the  <spanstyle="color:black;">                                    <spanstyle="color:#008200;">// java.sql.DriverManager  <spanstyle="color:black;">            conn.setAutoCommit(<spanstyle="color:#006699;font-weight:bold;">false);  <spanstyle="color:black;">            retryCount = <spanstyle="color:#C00000;">0;  <spanstyle="color:black;">            stmt = conn.createStatement();  <spanstyle="color:black;">            String query = <spanstyle="color:blue;">"SELECT foo FROM bar ORDER BY baz";  <spanstyle="color:black;">            rs = stmt.executeQuery(query);  <spanstyle="color:black;">            <spanstyle="color:#006699;font-weight:bold;">while (rs.next()) {  <spanstyle="color:black;">            }  <spanstyle="color:black;">            all.close()  <spanstyle="color:black;">            transactionCompleted = <spanstyle="color:#006699;font-weight:bold;">true;  <spanstyle="color:black;">        } <spanstyle="color:#006699;font-weight:bold;">catch (SQLException sqlEx) {  <spanstyle="color:black;">            String sqlState = sqlEx.getSQLState();  <spanstyle="color:black;">           <spanstyle="color:#008200;">// 这个08S01就是这个异常的sql状态。单独处理手动重新链接就可以了。  <spanstyle="color:black;">            <spanstyle="color:#006699;font-weight:bold;">if (<spanstyle="color:blue;">"08S01".equals(sqlState) || <spanstyle="color:blue;">"40001".equals(sqlState))   <spanstyle="color:black;">                {                  <spanstyle="color:black;">                    retryCount--;              <spanstyle="color:black;">                 } <spanstyle="color:#006699;font-weight:bold;">else {                  <spanstyle="color:black;">                     retryCount = <spanstyle="color:#C00000;">0;              <spanstyle="color:black;">                     }          <spanstyle="color:black;">         } <spanstyle="color:#006699;font-weight:bold;">finally {              <spanstyle="color:black;">                 all close:          <spanstyle="color:black;">             }      <spanstyle="color:black;">      } <spanstyle="color:#006699;font-weight:bold;">while (!transactionCompleted && (retryCount > <spanstyle="color:#C00000;">0));}  看看innod是不是关闭了你的连接关闭了吧?默认tomcat是8小时后无使用就自动断开连接了.<spanstyle="font-family:Verdana,sans-serif,宋体;font-size:14px;line-height:normal;background-color:#FFFFFF;">看看innod是不是关闭了,确认下,看这个貌似是不支持事务的表现呢?不然就是超时了感谢楼上各位的热心支持,明天到公司后再排查一下

爱吃鱼的程序员 2020-06-15 19:24:08 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站