Skip to main content

微服务应用

服务注册#

服务注册中心自动发现,集群全节点分布式注册中心,不依赖第三方注册中心。基于本框架开发微服务,无须刻意的关注注册中心的概念,因为这些工作都是自动进行的。

@EnableCloud
public class Node1 extends Application {
public static final String name = "test-01";
public static final String version = "1.0.1.210601";
public static final String apiVersion = "v1.0";
public void cloudConfig(CloudConfig config){
config.setNodeId("Node-1");
}
@Override
protected void globalConfig(ApplicationConfig config) {
config.getServer().setHttpPort(8080);
}
public static void main(String[] args) {
Ready.For(Node1.class).Work(args);
}
}

上面引用前面的例子,只要应用启动器加上@EnableCloud注解即可自动寻找到注册中心并注册该应用的服务。name是对外提供服务的serviceId,也就是注册到注册中心的名字,这里指定服务id为"test-01"。如果不设置,默认是启动器类名即"Node1"。 version是服务版本号,可以允许同一个服务的多个版本注册到注册中心,在微服务调用的时候可以通过serviceVersion来指定某个版本的服务。版本号强制要求必须符合医疗软件规范,这一规范对其他行业也没有副作用。

服务发现#

如同服务注册,本框架中不用关注注册中心的概念,所以也不用关注服务发现的概念。只需要定义一个service类继承自BusinessService,给方法加上一个@Call注解即可自动完成。请看下面的实例:

@Service
public class DemoService extends BusinessService {
@Call(serviceId = "test-01", method = RequestMethod.GET, url = "/api/hello")
public String hello() {
return IfFailure.get(null);
}
@Call(serviceId = "test-01", method = RequestMethod.POST, url = "/api/hi")
public String hi() {
return IfFailure.get(null);
}
}

除了定义的类需要继承自BusinessService外,还需要注意3件事件:

  1. 方法的返回类型
    请务必注意返回值类型的选择需要匹配或包容实际API服务实例的返回值,如果类型和API服务实例的返回类型完全匹配,那是最好,系统将自动封装为指定返回类型。 如有需要可以进行包容设置,例如Long型可以包容Integer,String可以包容所有类型,因为无论API返回什么类型都可以是Json字符串格式,然后再自行对字符串做解析。

  2. 方法的入参
    如果API服务需要入参,那么这里需要定义和API入参匹配的参数,如果请求是json,参数可以是复杂类型的对象,如果请求类型是form表单,参数类型只能是简单类型。 如果需要动态传入的url路径参数,可以看下面的实例:

    技巧
    @Call(serviceId = "test-01", url = "/api/{method}")
    public Record dynamicMethod(String method){
    return IfFailure.get(null);
    }

    上面的例子,根据方法入参,动态选择请求具体API,也可以是其他API需要的参数,支持同时多个动态入参。参数无顺序要求,参数名匹配即可。

  3. @Call注解
    @Call注解包揽了服务发现和负载均衡的工作,它有许多参数可供设定:

  • serviceId 即注册中心注册的服务id,对应于启动器中设定的name。

  • url 每个服务下面通过Controller暴露具体的API,url对应于一个具体API的url。

  • method 每个API都指定了访问的method类型,例如GET/POST等,这里method需要对应API的设定类型。

  • protocol 每个服务都可以设定开启或关闭http、https,默认开启http。这里的protocol需要匹配API服务实例的配置。

  • project 每个服务都可以设定项目名称,如果集群中有多个项目,那么这里的project可以选择指定的项目的服务。

  • serviceVersion 每个服务都有版本号,默认是1.0.0.000000,如果有多个版本的服务注册,那么这里的serviceVersion可以选择指定版本的服务。

  • projectVersion 每个服务都可以设定项目的版本号,如果集群中有多版本的项目,那么这里的projectVersion可以选择指定版本的项目的服务。

  • profile 通常我们有不同的运行环境,例如dev/test/prod等,系统自动会调用和自己当前环境一致的版本的服务,但也可以通过profile指定调用特定环境版本的服务。

  • type 通常API的设计支持json或者常规的form请求,默认是json,如果API是接收form表单的,这里type可以设置为form。

    技巧

    这里附带讲解一下外部请求,通过将serviceId设为空,然后url指定外部url,即可打通和外部站点的服务。注意这里指定type=Call.RequestType.json,如果外部站点是传统form表单的API,需要指定type=Call.RequestType.form。

    @Call(serviceId = "", type=Call.RequestType.json, url = "https://getman.cn/echo")
    public String externalApi(String q){
    return IfFailure.get(null);
    }
  • timeout 该值用于设定请求超时,在readyCloud配置下面的httpClient中有timeout的全局配置,默认是6000毫秒,如果需要针对特定API单独设置,可以通过这里设定timeout值。

  • retry 该值用于设定请求失败后重试次数,在readyCloud配置下面的httpClient中有retry的全局配置,默认是0次,因为重试需要确定API做好了幂等。如果确定特定API做好了幂等,可以通过这里设定retry次数。

以上是@Call注解的常规使用,只列举了部分重点内容,还有更多设定和应用尚未展开讲解,后续逐步完善更多具体的文档,并对重点内容进行专题描述。

健康检查#

当前健康检查工作自动由最老的节点负责,即启动最早的或者活的最久的那个节点。如果该节点下线了或者关闭了,那么下一个比它活的更久的节点会接替它的工作。后续版本将不再由最老的节点负责,而是可以指定多个节点共同分担健康检查任务。 和其他框架要求服务主动以心跳的形式上报健康状态不同,本框架采用主动请求服务来确定真实健康状态。因为主动上报心跳,只是一个线程以固定频率发送请求,可能业务线程已经出故障了而心跳线程还在正常工作。

本框架的健康检查默认是全自动的,url默认映射在/health-check,可以通过application config->server->healthCheckPath来设定,检查周期默认为10秒为,可以通过readyCloud->registry->checkInterval来设定。 该检查方式只能检查web服务器的健康状态,如果需要进一步检查业务逻辑健康状态,可以设计一个可以检查业务逻辑健康的api,然后通过application config->server->crucialCheckPath来指定该api。 注意健康检查API方法最后返回内容必须是字符串"READY",如果返回其他内容则认为业务逻辑检查出错。

服务降级熔断#

健康检查出现超时或返回值错误时会对该微服务进行降级,每出现一次降级20%,即减少20%的负载,当达到3次时该服务会被临时移除。健康检查会对该服务继续检查,如果连续检查成功,则每次恢复5%,如果在恢复过程中再次出现不稳定情况,立即移除该服务,然后继续对其健康检查。 该服务降级策略目前是固定不可变,后续会支持更多服务降级策略,并可配置。

如果是服务调用过程中出现故障,超时每次降级20%,默认设定是5分钟内超过3次,熔断器开启,对该实例的请求直接fallback。如果健康检查该实例逐渐恢复,会尝试将熔断器设置为半熔断状态,给予该实例一次机会,如果再次失败,熔断器立即熔断,继续等待健康检查,如果连续3次成功,熔断器关闭。

更多细节#

由于微服务相关内容较多,以上只列举部分重点内容。后续逐步完善更多具体的文档,并对重点内容进行专题描述。例如:通过程序主动注册特定的服务到注册中心、通过程序主动发现服务并选择服务实例而不通过负载均衡、通过程序对服务进行降级或熔断等。