Service的常见用法分析

本文详细介绍了Android中的Service组件,包括其用途、生命周期、启动方式及与Activity间的通信机制。Service用于后台执行长时间运行的任务,如与服务器保持心跳连接等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

Service四大组件之一,主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。例如:上传图片,大量计算,保活;Service后台执行任务,但是运行在主线程中,如果需要执行耗时任务,需要开启子线程;

Android的后台指:它的运行不依赖UI,即使Activity被销毁,或者程序关闭,只要进程还在,Service依然可以正常运行;例如,需要与服务器保持心跳连接,就可以用Service来实现,在Service中开启子线程;

Service的优势:所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例

声明周期

基本用法

开启方式:

方式一: startService() --stopService() :

on Create(只执行一次)-- onStartCommand()(每次都执行)--onDestory();

方式二:bindService() --unBindService(): 

onCreate() -- onBind()--onUnBind()--onDestory();

两种启动Service方式的区别:

1):启动Service,onCreat或onStartCommand() 里面执行具体逻辑,Service和Activity的关系并不大,只是通知Service可以干活了;

2):可以通过ServiceConnection里面的onServiceConnected 调用Service里的方法;一旦绑定成功,ServiceConnection接口中的onServiceConnected()就立刻执行;

进程内Service和Activity通信

分为两种情况:

1:Activity向Service传递消息的方法:

    1)利用BroadcastReceiver发送广播,Activity发送广播,Service中定义广播接收者进行接收。

    2)利用绑定服务的方式开启服务,暴露服务中的方法,Activity进行调用。

    3)利用Intent打开服务的方式,通过Intent传递数据,分别在onStartCommand(Intent intent)和onBind()可以通过intent获取到信息;onCreate()内无法获取到Intent实例。

Activity向服务传递消息,暴露服务中的方法:

Activity

private ServiceConnection connection = new ServiceConnection() {
   @Override
   public void onServiceDisconnected(ComponentName name) {// 解除关联

   }

   @Override
   public void onServiceConnected(ComponentName name, IBinder service) {//建立关联
     myBinder = (MyService.MyBinder) service;
     myBinder.startDownload();
   }
};

Service

private MyBinder mBinder = new MyBinder();
  @Override
  public IBinder onBind(Intent intent) {
    return mBinder;
  }

class MyBinder extends Binder {
  public void startDownload() {
    Log.d("TAG", "startDownload() executed");
    // 执行具体的下载任务
  }
}

通过上面的方式,可以在Activity中根据具体的场景来调用MyBinder中的任何public方法,即实现了Activity指挥Service干什么Service就去干什么的功能。

2:Service向Activity传递消息的方法:

    1)利用BroadcastReceiver,在Service中发送广播,Activity中接收。

    2)回调的方式 

2.2:回调的方式,Service更新UI。

Service 

public ServiceCallBack serviceCallBack;

public interface ServiceCallBack {
  void serviceCallBack(String string);
}

public void setServiceListener(ServiceCallBack serviceCallBack) {
  this.serviceCallBack = serviceCallBack;
}


//通信的桥梁
class MyBinder extends Binder {
  /**
  *获取当前Service的实例
  *@return
  */
  public InnerService getService() {
    return InnerService.this;
  }

  public void tell() {
    Log.d(TAG, "我执行了");
      //TODO 
      //方式一:广播
      //Intent intent = new Intent("InnerService");
      //sendBroadcast(intent);

      //方式二: 回调
      if (serviceCallBack != null) {
        serviceCallBack.serviceCallBack("通过回调,我执行了");
     }
  }
}

Activity

//和服务组件间通信
private ServiceConnection serviceConnection = new ServiceConnection() {
  private InnerService.MyBinder myBinder;

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
    myBinder = (InnerService.MyBinder) service;
    InnerService service1 = myBinder.getService();
    service1.setServiceListener(new InnerService.ServiceCallBack() {

      @Override
      public void serviceCallBack(String string) {
       Log.d(TAG, "serviceCallBack::" + string);
       //改变UI
      }
    });

    //监听之后 在调用
    myBinder.tell();
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   Log.d(TAG, "onServiceDisconnected");
   myBinder = null;
  }
};

Service销毁

思考:1:如果bindService(),点击stopService,服务会销毁吗?

不会,两种开启方式,只能用对应的停止方式,关闭Service;

2: startService,bindService 都执行了,Service怎么才能销毁?

如果我们既点击了Start Service按钮,又点击了Bind Service按钮会怎么样呢?这个时候你会发现,不管你是单独点击Stop Service按钮还是Unbind Service按钮,Service都不会被销毁,必要将两个按钮都点击一下,Service才会被销毁。也就是说,点击Stop Service按钮只会让Service停止,点击Unbind Service按钮只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。即:先点击一下Start Service按钮,再点击一下Bind Service按钮,这样就将Service启动起来,并和Activity建立了关联。然后点击Stop Service按钮后Service并不会销毁,再点击一下Unbind Service按钮,Service就会销毁了;

Service和Thread的关系

Service和Thread没有任何关系,什么时候用Service呢?

Service运行在主线程,如果在Service中做耗时操作,肯定会报ANR;

既然在Service里也要创建一个子线程,那为什么不直接在Activity里创建呢?这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

如有问题,请多指教,谢谢!

参考文档

http://blog.youkuaiyun.com/guolin_blog/article/details/11952435/

源码

<think>嗯,用户之前问了后端系统的安全性,现在转向了Kubernetes的常见用法,看来他对系统架构和运维方面比较感兴趣。需要整理k8s的常见用法,可能用户刚开始接触k8s,或者想系统化自己的知识。用户可能是在准备面试,或者在实际工作中需要部署和管理容器化应用,所以需要一份清晰的指南。 首先,我得确定用户对k8s的了解程度。之前的回答结构很详细,用户可能期待类似的层次结构。需要覆盖基本概念、核心功能、常用操作、网络存储、运维监控、安全、扩展和生态系统等方面。 要确保回答结构清晰,分点列出,每个部分有子项。例如,核心功能包括部署、扩缩容、配置管理、服务发现、存储管理、自动修复、滚动更新、任务调度。常用操作涉及kubectl命令,可能需要具体例子,但用户可能不需要太详细的命令,而是分类说明。 还要注意用户可能关心的实际应用场景,比如如何做CI/CD集成,监控方案选型,或者安全策略。之前的回答中有提到安全维度,所以在k8s这里也需要涉及RBAC、网络策略、密钥管理等内容。 用户可能还需要了解k8s的生态系统,比如Helm、Operators、Service Mesh等工具,这些能帮助他们扩展功能。另外,常见问题如Pod故障排查、资源优化、网络问题等也是实际使用中会遇到的问题,需要给出解决思路。 需要避免太技术化的术语,但保持专业性。比如解释Deployment和StatefulSet的区别时,要简明扼要。同时,结合之前的回答风格,可能用户喜欢表格和公式,比如在核心功能部分用表格区分控制器类型,或者在资源配额部分用数学表达式。 还要注意用户可能没提到的深层需求,比如如何选择存储类型,或者如何监控集群健康状态,这些在整理常见用法时也应涵盖。最后,确保回答有总结,强调k8s的优势和适用场景,帮助用户形成整体认识。</think>以下是对Kubernetes常见用法的系统化整理,采用分层结构说明核心功能和应用场景: --- ### 一、核心功能模块 | 功能分类 | 实现方式 | 典型应用场景 | 数学表达示例 | |----------------|---------------------------|----------------------------------|-----------------------------------| | **部署管理** | Deployment | 无状态应用滚动更新 | 副本数 $replicas = \lceil \frac{QPS}{1000} \rceil$ | | **有状态服务** | StatefulSet | 数据库集群部署 | 有序编号 $pod\_name = {sts-name}-{0..N-1}$ | | **配置注入** | ConfigMap/Secret | 环境变量动态配置 | 数据映射 $\forall k \in ConfigMap, v \to Pod$ | | **服务发现** | Service/Ingress | 内外网流量路由 | 负载均衡 $endpoints = \sum_{healthy\;pod} ip:port$ | | **存储管理** | PersistentVolume(PV) | 数据库持久化存储 | 容量规划 $PV_{size} \geq \sum_{pod} request_{storage}$ | | **自动扩缩容** | HPA(HorizontalPodAutoscaler) | 应对流量波动 | 扩缩规则 $desiredReplicas = \lceil currentReplicas \times \frac{currentMetricValue}{desiredMetricValue} \rceil$ | --- ### 二、常用操作指令 ```bash # 声明式资源管理 $ kubectl apply -f deployment.yaml # 应用YAML配置(幂等操作) # 实时监控与调试 $ kubectl get pods -l app=nginx --watch # 标签筛选+实时状态监控 $ kubectl logs -f pod/nginx-7cdbd8cdc9-zwxrb # 流式日志跟踪 $ kubectl exec -it pod/nginx -- /bin/sh # 进入容器调试 # 集群状态诊断 $ kubectl describe node worker-01 # 节点资源详情分析 $ kubectl top pod --containers # 容器级资源消耗排名 ``` --- ### 三、网络模型实践 1. **Service类型选择矩阵** | 类型 | 流量特征 | 典型场景 | 网络开销 | |--------------|------------------------|---------------------------|----------| | ClusterIP | 集群内部通信 | 微服务间调用 | 低 | | NodePort | 单节点外部暴露 | 开发环境测试 | 中 | | LoadBalancer | 云厂商负载均衡集成 | 生产环境公网访问 | 高 | | Ingress | 七层路由规则管理 | 多域名HTTPS卸载 | 可变 | 2. **网络策略示例** ```yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy spec: podSelector: matchLabels: app=db ingress: - from: - podSelector: matchLabels: app=api ports: - protocol: TCP port: 5432 # 只允许api服务访问数据库的5432端口 ``` --- ### 四、存储方案选型 1. **存储类(StorageClass)配置维度** - 性能等级:$IOPS \propto \frac{1}{latency}$ - 数据持久性:$RPO \leq 15\text{min}, RTO \leq 5\text{min}$ - 挂载方式:ReadWriteOnce/ReadOnlyMany/ReadWriteMany 2. **典型存储方案对比** | 存储类型 | 适用场景 | 数据一致性 | 扩容复杂度 | |----------------|-------------------|--------------|------------| | 本地SSD | 高性能数据库 | 强一致性 | 不可扩容 | | Ceph RBD | 通用块存储 | 最终一致性 | 动态扩容 | | NFS | 文件共享 | 弱一致性 | 手动扩容 | | 云盘(如AWS EBS)| 云环境持久化存储 | 强一致性 | 在线扩容 | --- ### 五、运维监控体系 1. **监控指标采集公式** - 节点健康度:$$ \text{NodeScore} = 0.4 \times \text{CPU\_free} + 0.3 \times \text{Mem\_free} + 0.3 \times \text{Disk\_IOPS} $$ - Pod驱逐预测:$$ \text{EvictRisk} = \begin{cases} 1 & \text{if } \frac{current\_memory}{limit} > 0.9 \\ 0.5 & \text{if } \frac{current\_cpu}{limit} > 0.8 \\ 0 & \text{otherwise} \end{cases} $$ 2. **常用工具链组合** ```mermaid graph LR A(Prometheus) -->|采集| B(Node Exporter) A -->|告警| C(AlertManager) D(Grafana) -->|可视化| A E(Fluentd) -->|日志| F(Elasticsearch) ``` --- ### 六、安全加固措施 1. **RBAC权限矩阵** | 角色 | 权限范围 | API资源限制 | |-------------------|------------------------------|----------------------------| | dev-user | 特定namespace的Pod读写 | verbs: get, list, watch | | cluster-admin | 全集群管理权限 | resources: * | | storage-manager | PersistentVolumeClaims管理 | resourceNames: "ssd-*" | 2. **安全基线配置** ```yaml securityContext: runAsNonRoot: true capabilities: drop: ["NET_RAW"] seccompProfile: type: RuntimeDefault ``` --- ### 七、进阶使用模式 1. **Operator设计范式** ```go func Reconcile() error { current := GetCurrentState() desired := CalculateDesiredState() if !reflect.DeepEqual(current, desired) { return UpdateCluster(desired) # 实现声明式状态收敛 } return nil } ``` 2. **混合云调度策略** ```python def schedule_pod(pod): if pod.requires_gpu: return filter_nodes(has_gpu=True) elif pod.low_latency: return min_distance(user_region) else: return cheapest_zone() ``` --- **总结建议**: 生产环境建议采用$GitOps$模式(如Argo CD),配合$Service\;Mesh$(如Istio)实现细粒度流量治理。对于有状态服务,优先使用Operator模式封装领域知识。监控体系应满足$SLO = \frac{成功请求数}{总请求数} \geq 99.9\%$的服务级别目标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值