SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介、创建消息生产者、创建消息消费者、自定义消息通道、分组与持久化、设置 RoutingKey)

1、概念:SpringCloudStream

2、具体内容

2.1、SpringCloudStream 简介

SpringCloudStream 就是使用了基于消息系统的微服务处理架构。对于消息系统而言一共分为两类基于应用标准的 JMS、基于协议标准的 AMQP,在整个 SpringCloud 之中支持有 RabbitMQ、Kafka 组件的消息系统。利用 SpringCloudStream 可以实现更加方便的消息系统的整合处理,但是推荐还是基于 RabbitMQ 实现会更好一些。

为什么 SpringCloud 中要提供有一个类似于消息驱动的 SpringCloudStream 呢?

如果通过 Java 历史上的分布式的开发架构大家不难发现,对于消息系统,实际上最初的 SUN 公司是非常看中的,所以在 EJB 的时代里面专门提供有消息驱动 Bean(Message Driven Bean、MDB)利用消息驱动 Bean 可以进行消息的处理操作。利用消息驱动 bean 的模式可以简化用户的操作复杂度,直接传递一些各类的数据即可实现业务的处理操作

于是在 SpringBoot 的之中为了方便开发者去整合消息组件,也提供有一系列的处理支持,但是如果按照这些方式来在 SpringCloud 之中进行消息处理,有些人会认为比较麻烦,所以在 SpringCloud 里面将消息整合的处理操作进行了进一步的抽象操作, 实现了更加简化的消息处理。

总结:SpringCloudStream 就是实现了 MDB 功能,同时可以更加简化方便的整合消息组件

SpringCloudStream的工作原理:

说明:最底层是消息服务,中间层是绑定层,绑定层和底层的消息服务进行绑定,顶层是消息生产者和消息消费者,顶层可以向绑定层生产消息和和获取消息消费

2.2、创建消息生产者

本次基于 RabbitMQ 实现消息的生产者的微服务操作,在整个的生产者项目之中,首先创建了一个新的 Maven 模块: microcloud-stream-provider-8401。

1、 【microcloud-stream-provider-8401】修改 pom.xml 配置文件,在这个配置文件之中要追加如下的依赖程序包:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

2、 【microcloud-stream-provider-8401】修改 application.yml 配置文件,追加如下的绑定处理配置:

server:
  port: 8401
eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://edmin:[email protected]:7001/eureka,http://edmin:[email protected]:7002/eureka,http://edmin:[email protected]:7003/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: send-8401.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址
spring:
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
              addresses: rabbitmq-server
              username: studyjava
              password: hello
              virtual-host: /
      bindings: # 服务的整合处理
        output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
  application:
    name: microcloud-stream-provider

3、 修改 hosts 配置文件,追加主机映射:

127.0.0.1 send-8401.com

4、 【microcloud-stream-provider-8401】定义一个消息的发送接口:

package cn.study.microcloud.service;

import cn.study.vo.Company;

public interface IMessageProvider {

    /**
    * 实现消息的发送,本次发送的消息是一个对象(自动变为json)
    * @param company VO对象,该对象不为null*/
      public void send(Company company) ;
}

5、 【microcloud-stream-provider-8401】定义消息发送的实现子类:

package cn.study.microcloud.service.impl;

import javax.annotation.Resource;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import cn.study.microcloud.service.IMessageProvider;
import cn.study.vo.Company;

@EnableBinding(Source.class) // 可以理解为是一个消息的发送管道的定义
public class MessageProviderImpl implements IMessageProvider {
    @Resource
    private MessageChannel output; // 消息的发送管道

    @Override
    public void send(Company company) {
        this.output.send(MessageBuilder.withPayload(company).build()); // 创建并发送消息
    }
}

6、 【microcloud-stream-provider-8401】分析一下 Source 类的源代码:

public interface Source {

    String OUTPUT = "output"; // 之前所设置的消息发送的管道

    @Output(Source.OUTPUT)
    MessageChannel output();

}

7、 【microcloud-stream-provider-8401】定义程序主类:

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
@EnableDiscoveryClient
public class StreamProvider_8401_StartSpringCloudApplication {
    public static void main(String[] args) {
        SpringApplication.run(StreamProvider_8401_StartSpringCloudApplication.class, args);
    }
}

8、 【microcloud-stream-provider-8401】编写测试类:

· 保证你的 pom.xml 文件之中存在有测试的依赖程序包:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

· 编写具体的测试程序类:

package cn.study.microcloud.test;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import cn.study.microcloud.StreamProvider_8401_StartSpringCloudApplication;
import cn.study.microcloud.service.IMessageProvider;
import cn.study.vo.Company;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = StreamProvider_8401_StartSpringCloudApplication.class)
@WebAppConfiguration
public class TestMessageProvider {
    @Resource
    private IMessageProvider messageProvider;

    @Test
    public void testSend() {
        Company company = new Company();
        company.setTitle("studyjava");
        company.setNote("更多资源请登录:www.study.cn");
        this.messageProvider.send(company); // 消息发送
    }
}

9、 启动 RabbitMQ 以及相应的微服务进行消息的发送处理,如果可以检测到 RabbitMQ 上的活动信息就表示该微服务创建成功。

2.3、创建消息消费者

在之前已经成功的实现了消息的发送处理,但是这个消息由于只是一个临时消息并且只是发送到了 RabbitMQ 之中,那么现在 如果要想进行该消息的接收就必须通过 RabbitMQ 获取消息内容。

1、 【microcloud-stream-consumer-8402】通过“microcloud-stream-provider-8401”模块复制本模块;

2、 【microcloud-stream-consumer-8402】一定要保证 pom.xml 文件之中拥有如下的依赖包:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

3、 修改 hosts 主机映射,追加新的主机名称:

127.0.0.1 receive-8402.com

4、 【microcloud-stream-consumer-8402】修改 application.yml 配置文件:

server:
  port: 8402
eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://edmin:[email protected]:7001/eureka,http://edmin:[email protected]:7002/eureka,http://edmin:[email protected]:7003/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: receive-8402.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址
spring:
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
              addresses: rabbitmq-server
              username: studyjava
              password: hello
              virtual-host: /
      bindings: # 服务的整合处理
        input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
  application:
    name: microcloud-stream-consumer

5、 【microcloud-stream-consumer-8402】定义一个消息的监听程序类:

package cn.study.microcloud.service;

import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import cn.study.vo.Company;

@Component
@EnableBinding(Sink.class)
public class MessageListener {
    @StreamListener(Sink.INPUT)
    public void input(Message<Company> message) {
        System.err.println("【*** 消息接收 ***】" + message.getPayload());
    }
}

6、 【microcloud-stream-consumer-8402】观察 Sink 源代码:

public interface Sink {

    String INPUT = "input";

    @Input(Sink.INPUT)
    SubscribableChannel input();

}

7、 首先启动消息的消费端,而后再启动消息的生产者发送消息。

那么此时实现了了一个基于 RabbitMQ 定义的 SpringCloudStream 基本操作功能。

2.4、自定义消息通道

现在已经实现了一个基础的 SpringCloudStream 处理操作,但是在本次操作之中一直使用的都是系统中提供好的 Source (output)、Sink(input),如果说现在用户有需要也可以定义自己的通道名称。

1、 【micocloud-api】由于现在有两个模块都需要使用到自定义消息通道的配置,所以应该将这个配置定义为一个公共的程序处理 类,修改 pom.xml 配置文件,引入相应的开发包:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

2、 【micocloud-api】使用一个自定义的通道:

package cn.study.channel;

import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;

public interface DefaultProcess {
    public static final String OUTPUT = "study_output"; // 输出通道名称
    public static final String INPUT = "study_input"; // 输入通道名称

    @Input(DefaultProcess.INPUT)
    public SubscribableChannel input();

    @Output(DefaultProcess.OUTPUT)
    public MessageChannel output();
}

3、 【microcloud-stream-provider-8401】修改 application.yml 配置文件:

spring:
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
              addresses: rabbitmq-server
              username: studyjava
              password: hello
              virtual-host: /
      bindings: # 服务的整合处理
        study_output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置

4、 【microcloud-stream-consumer-8402】修改 application.yml 配置文件:

spring:
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
              addresses: rabbitmq-server
              username: studyjava
              password: hello
              virtual-host: /
      bindings: # 服务的整合处理
        study_input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置

5、 【microcloud-stream-provider-8401】修改消息的发送子类:

package cn.study.microcloud.service.impl;

import javax.annotation.Resource;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;

import cn.study.channel.DefaultProcess;
import cn.study.microcloud.service.IMessageProvider;
import cn.study.vo.Company;

@EnableBinding(DefaultProcess.class) // 可以理解为是一个消息的发送管道的定义
public class MessageProviderImpl implements IMessageProvider {
    @Resource
    private MessageChannel output; // 消息的发送管道

    @Override
    public void send(Company company) {
        this.output.send(MessageBuilder.withPayload(company).build()); // 创建并发送消息
    }
}

6、 【microcloud-stream-consumer-8402】修改 MessageListener 程序类:

package cn.study.microcloud.service;

import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import cn.study.channel.DefaultProcess;
import cn.study.vo.Company;

@Component
@EnableBinding(DefaultProcess.class)
public class MessageListener {
    @StreamListener(Sink.INPUT)
    public void input(Message<Company> message) {
        System.err.println("【*** 消息接收 ***】" + message.getPayload());
    }
}

7、 随后就可以使用自定义的新的通道名称进行 Stream 处理操作了。

2.5、分组与持久化

在上面的程序里面成功的实现了消息的发送以及接收,但是需要注意一个问题,所发送的消息在默认情况下它都属于一种临时消息,也就是说如果现在没有消费者进行消费处理,那么该消息是不会被保留的。

如果要想实现持久化的消息处理,重点在于消息的消费端配置,同时也需要考虑到一个分组的情况(有分组就表示该消息可以进行持久化)。

1、 【microcloud-stream-consumer-8402】修改 application.yml 配置文件,追加分组配置:

spring:
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
              addresses: rabbitmq-server
              username: studyjava
              password: hello
              virtual-host: /
      bindings: # 服务的整合处理
        study_input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
          group: study-group # 进行操作的分组,实际上就表示持久化

在 SpringCloudStream 之中如果要设置持久化队列,则名称为“destination.group”。此时关闭掉消费端的微服务之后该队列信息依然会被保留在 RabbitMQ 之中。而后在关闭消费端的情况下去运行消息生产者,发送完消息后再运行消息的消费端仍然可以接收到之前的消息。

2.6、设置 RoutingKey

默认情况下之前的程序都是属于广播消息,也就是说所有的消费者都可以接收发送消息内容,在 RabbitMQ 里面支持有直连消息,而直连消息主要是通过 RoutingKey 来实现,利用直连消息可以实现准确的消息消费端的接收处理。

1、 【microcloud-stream-consumer-8402】修改 application.yml 配置文件:

server:
  port: 8402
eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://edmin:[email protected]:7001/eureka,http://edmin:[email protected]:7002/eureka,http://edmin:[email protected]:7003/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: receive-8402.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址
spring:
  cloud:
    stream:
      rabbit: # 进行rabbit的相关绑定配置
        bindings:
          study_input:
            consumer: # 进行消费端配置
              bindingRoutingKey: study-key # 设置一个RoutingKey信息
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
              addresses: rabbitmq-server
              username: studyjava
              password: hello
              virtual-host: /
      bindings: # 服务的整合处理
        study_input: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: RKExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
          group: study-group # 进行操作的分组,实际上就表示持久化

  application:
    name: microcloud-stream-consumer

2、 【microcloud-stream-provider-8401】定义 RoutingKey 的表达式配置:

server:
  port: 8401
eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://edmin:[email protected]:7001/eureka,http://edmin:[email protected]:7002/eureka,http://edmin:[email protected]:7003/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: send-8401.com  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址
spring:
  cloud:
    stream:
      rabbit: # 进行rabbit的相关绑定配置
        bindings:
          study_output:
            producer: # 进行消费端配置
              routing-key-expression: ‘‘‘study-key‘‘‘ #定义 RoutingKey 的表达式配置
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
              addresses: rabbitmq-server
              username: studyjava
              password: hello
              virtual-host: /
      bindings: # 服务的整合处理
        study_output: # 这个名字是一个通道的名称,在分析具体源代码的时候会进行说明
          destination: RKExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit # 设置要绑定的消息服务的具体设置
  application:
    name: microcloud-stream-provider

3、 首先运行消费端程序,随后在运行生产端,只有 RoutingKey 匹配了之后才可以正常进行消息的接收处理。

原文地址:https://www.cnblogs.com/leeSmall/p/8900518.html

时间: 2024-10-02 19:37:53

SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介、创建消息生产者、创建消息消费者、自定义消息通道、分组与持久化、设置 RoutingKey)的相关文章

ActiveMQ发消息和收消息

来自:http://blog.163.com/chengwei_1104/blog/static/53645274201382315625329/ ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位. 下面详细的解释常用类的作用 ConnectionFactory 接口(连接工厂) 用

RabbitMq+Spring boot 消息生产者向队列发送消息 (一)

本人学习新框架方法. 一.先学习框架基本知识,也就是看这本书的前三章,了解基本概念.比如这个Rabbitmq,我会先看一些概念,比如,交换机,路由器,队列,虚拟机. 二.然后写代码,写demo,有哪些不懂的地方直接再去翻书或者google找资料,带着问题去学习,学的更快更扎实一些. 三.然后再看这个框架的应用场景,自己能否独立的写一些简单的项目,来验证自己的成果. 四.实际项目积累经验. RabbitMq 消息生产者向队列发送消息 (一) MQ分为消息生产者和消息消费者,这次做的主要是消息的生产

JMS消息服务器——Message消息分析(1)

一.Message结构 Message消息是整个JMS规范最为重要的部分.一个JMS应用程序中的所有数据和事件都是使用消息进行通信的,同时JMS的其余部分也都在为消息传输服务.因此可以说,消息时一个系统的命脉所在. 一个Message对象有3个部分:消息头.消息属性,最后就是消息数据内容,它称为负载或消息体. 二.消息头 每条JMS消息都有一组标准的消息头.每个消息头都由一组取值函数和赋值函数所标识.这些方法名称紧随在术语setJMS**(),getJMS**()方法之后.如下图: JMS消息可

跟我学SpringCloud | 第十一篇:使用Spring Cloud Sleuth和Zipkin进行分布式链路跟踪

SpringCloud系列教程 | 第十一篇:使用Spring Cloud Sleuth和Zipkin进行分布式链路跟踪 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特殊说明,本系列教程全采用以上版本 在分布式服务架构中,需要对分布式服务进行治理--在分布式服务协同向用户提供服务时,每个请求都被哪些服务处理?在遇到问题时,在调用哪个服务上发生了问题?在分析性能时,调用各个服务都花了多长时间?哪些调用可以并行执行?-- 为此,分布式

struts2官方 中文教程 系列十一:使用XML进行表单验证

在本教程中,我们将讨论如何使用Struts 2的XML验证方法来验证表单字段中用户的输入.在前面的教程中,我们讨论了在Action类中使用validate方法验证用户的输入.使用单独的XML验证文件让您可以内置到Struts 2框架的验证器. 贴个本帖的地址,以免被爬:struts2官方 中文教程 系列十一:使用XML进行表单验证  即 http://www.cnblogs.com/linghaoxinpian/p/6938720.html 下载本章节代码 为了使用户能够编辑存储在Person对

C#微信公众号开发系列教程五(接收事件推送与消息排重)

微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C#微信公众号开发系列教程四(接收普通消息) C#微信公众号开发系列教程五(接收事件推送与消息排重) 在上一篇的博文中讲到,微信的消息可以大体分为两种类型,一种是包括:文本,语音,图片等的普通消息,另一种就是本篇要将的事件类型.包括:关注/取消关注事件,扫描带参数二维码事件,上报地理位置事件,自定义菜

嵌入式 Linux进程间通信(十一)——多线程简介

嵌入式 Linux进程间通信(十一)--多线程简介 一.线程简介 线程有四种:内核线程.轻量级进程.用户线程.加强版用户线程 1.内核线程 内核线程就是内核的分身,一个分身可以处理一件特定事情.内核线程的使用是廉价的,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间.支持多线程的内核叫做多线程内核(Multi-Threads kernel ). 2.轻量级进程LWP 轻量级进程(LWP)是一种由内核支持的用户线程,是基于内核线程的高级抽象,只有先支持内核线程,才能有轻量级进程LWP.每一个

白话SpringCloud | 第十一章:路由网关(Zuul):利用swagger2聚合API文档

前言 通过之前的两篇文章,可以简单的搭建一个路由网关了.而我们知道,现在都奉行前后端分离开发,前后端开发的沟通成本就增加了,所以一般上我们都是通过swagger进行api文档生成的.现在由于使用了统一路由网关了,都希望各微服务的api文档统一的聚合在网关服务中,也方便前端用户查阅,不需要每个服务单独查看.当然了,也是可以做一个文档索引网页进行各微服务的api文档链接的.今天,我们就来讲下使用swagger实现自动化聚合微服务文档功能. 注:关于Swagger的介绍和使用,由于在之前的Spring

Android学习路线(二十一)运用Fragment构建动态UI——创建一个Fragment

你可以把fragment看成是activity的模块化部分,它拥有自己的生命周期,接受它自己的输入事件,你可以在activity运行时添加或者删除它(有点像是一个"子activity",你可以在不同的activity中重用它).本课将向你展示如何使用Support Libaray继承 Fragment 类来让你的应用能够兼容正在运行Android 1.6的设备. 提示: 如果你决定你的应用需求的最低API级别是11或者更高,那么你不需要使用Support Library,你可以直接使用