Home Dubbo

0 17
一 排查思路
  • 平台错误提示
    • 发布平台获取错误信息(平台会有相关发布失败信息,用于辅助排查问题+8000咨询提供给值班同事,便与值班同事定位问题)
  • 应用程序是否启动
    • 查看进程是否存在

ps -ef|grep 应用名称

  • 业务日志排查
    • 查看控制台日志/home/publish_product/server_java/${application}/${version}/logs/stdout.log,主要输出启动过程中输出到终端的日志,应用启动失败,首要看这个日志(prod不生成,每次启动成功会删除,启动过程中去查看
    • 框架error日志

(/home/product/logs/${application}_logs/frame/error_dubbo_framework.log,在框架层面记录下来的日志,一般启动失败,在这里也会有错误信息,不止是启动失败,应用运行过程中出现错误,也可以先去这个日志文件查看。)

    • 运维通道cli日志

(/var/log/cli.log从发布系统执行命令后,运维通道调用启动脚本过程中输出的日志)

    • 操作系统日志

(/var/log/message, 如果应用启动是申请的内存超过了OS 可用的内存,那么操作系统出于自我保护,会直接kill掉应用进程,同时会记录Kill process的日志,如果是docker进程,日志是记录在宿主机上)

    • dolphin启动日志

 /home/product/logs/{应用名_logs}/dolphin-executor-error.log

二 常见问题汇总
1 虚拟机类
1.1 代码异常问题

问题现场

解决方案

  • 业务jar包类找不到
    • 排查jar包是否存在,业务自行结合代码解决
  • 集团架构提供的组件jar包类找不到
    • base_component_all、dolphin等咨询架构同事辅助解决
1.2 健康检查不通过问题

问题现场

解决方案

  • 查看业务日志,确认是否有异常 , ps -ef |grep 应用名 查看进程是否存在(如果日志没明显错误且进程存在,则排查端口)

  • 端口是否启动(以下两种都可以查看端口暴露情况)
    • netstat -nlpt
    • telnet 127.0.0.1 应用rpc端口
      • 端口没暴露
        • 本地启动,看看端口是否暴露,本地调试解决问题(一般是dubbo-provider.xml文件中没有暴露的服务,没服务及时是dubbo应用,端口也不会启动)
      • 端口暴露
        • 说明程序正常运行 & 端口号暴露 ,但是启动耗时过程
          • 排查应用启动过程中是否有异常,导致启动耗时过长。如果没问题,业务启动耗时变成是正常的,可以调整应用发布超时时间
1.3 获取动态参数异常问题

问题现场

解决方案

  • 查看应用jvm参数是否配置

    • 若jvm参数未配置
      • 配置对应环境jvm参数后,重新发布即可
    • jvm参数已配置
      • 查看app.properties里的application.name是否等于应用名
        • 不等于,则修改保持一致
        • 等于&jvm参数配置了,则重试几次,若几次还不行,咨询8000,问乐效值班同事
1.4 发布失败,缺少启动脚本文件

问题现场

解决方案

  • 确认是否需要启动脚本文件
    • 启动类应用(需要)
      • java
      • go
      • python
      • c/c++
      • nodejs
    • 非启动类应用(不需要)
      • config
      • static
  • 启动类解决方案(补全缺少脚本文件,参考通组其他工程)

  • 非启动类解决方案

1.5 发布失败,服务未启动问题

问题现场

问题原因

  • restart脚本复用了shell上下文,stop脚本exit 1时,会退出shell上下文,导致start脚本不执行

类似案例:

(查看工程restart.sh脚本,核对真实执行启动脚本)

解决方案

  • 临时方案:乐效启停页面,先把应用程序启动
  • 长期方案:修改restart脚本实现
1.6 发布失败,后端服务超时未回应问题

问题现场

问题原因

  • 调用cli通道执行发布操作,cli通过没响应,可以登录机器,查看/var/log/cli.logs

解决方案

  • 查看cli日志,分析是否cli返回有延迟
  • 重试(若重试还不行,找8000咨询乐效值班)
1.7 发布失败,提示check old xxxx failed问题

问题现场

解决方案

联系8000找架构处理,组件包检测不通过

1.8 发布失败,实际应用程序启动成功

问题现场

问题原因

  • start脚本自定义了发布检测超时时间,检测逻辑不通过,导致发布失败

解决方案

  • 调整自定义检测超时时间
1.9 发布失败,后端服务超时未回应,命令超时

问题现场

问题原因

  • 推送、发布实际真实执行过程:乐效调用cli服务器,把推送、发布脚本“推送”到宿主机上,然后在宿主机上执行脚本,返回执行结果
  • 如果脚本执行异常,没有回调发布系统,页面会显示命令超时
  • 如果脚本执行成功or失败,会返回对应信息,在乐效上会看到对应状态和信息提示

排查过程

  • 登录部署机器,监听cli执行过程日志(tail -f /var/log/cli.log)
  • 乐效重试推送or发布操作,在cli日志中会输出脚本执行过程日志

解决方案

  • 重试
  • 联系8000值班
2 容器发类

 

0 16

配置

provider配置xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://dubbo.apache.org/schema/dubbo        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application   name="service-provider2"   owner="xiaoming" />

    <!-- 使用zookeeper注册中心暴露服务地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" id="r1"  timeout="10000"/>

    <!-- 用dubbo协议在20882端口暴露服务
    <dubbo:protocol name="dubbo" port="20882" /> -->
    <!-- 用dubbo协议在20883端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20883" />

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.lagou.service.HelloService"    ref="helloService"  />

    <!-- 和本地bean一样实现服务 -->
    <bean id="helloService" class="com.lagou.service.impl.HelloServiceImpl" />
</beans>

consumer配置xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://dubbo.apache.org/schema/dubbo        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="dubbo-consumer" owner="lisi" >
         <dubbo:parameter key="qos.enable" value="true" ></dubbo:parameter>
         <dubbo:parameter key="qos.port" value="33333"></dubbo:parameter>
         <dubbo:parameter key="qos.accept.foreign.ip" value="true" ></dubbo:parameter>
    </dubbo:application>
    <!--    -->
     <dubbo:consumer timeout="2000" check="false">
     </dubbo:consumer>

    <!-- 使用zookeeper注册中心暴露发现服务地址 -->
    <dubbo:registry address="106.75.144.210:2181"  timeout="10000"  protocol="zookeeper" id="myRegistry">
    </dubbo:registry>

    <dubbo:protocol name="dubbo"/>

    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="service" interface="com.my.study.service.Service" registry="myRegistry" timeout="4000" retries="2" version="0.0.0"/>

    <dubbo:annotation package="com.my.study"></dubbo:annotation>
</beans>

配置讲解xml形式

1.dubbo:application 当前应用的信息

1. name: 当前应用程序的名称,在dubbo-admin中我们也可以看到,这个代表这个应用名称。我们 在真正时是时也会根据这个参数来进行聚合应用请求。

2. owner: 当前应用程序的负责人,可以通过这个负责人找到其相关的应用列表,用于快速定位到责 任人。

3. qosEnable : 是否启动QoS 默认true。

4. qosPort : 启动QoS绑定的端口 默认22222 5. qosAcceptForeignIp: 是否允许远程访问 默认是false。

2.dubbo:registry 注册中心的信息

1. id : 当当前服务中provider或者consumer中存在多个注册中心时,则使用需要增加该配置。在一 些公司,会通过业务线的不同选择不同的注册中心,所以一般都会配置该值。

2. address : 当前注册中心的访问地址。

3. protocol : 当前注册中心所使用的协议是什么。也可以直接在 address 中写入,比如使用 zookeeper,就可以写成 zookeeper://xx.xx.xx.xx:2181。

4. timeout : 当与注册中心不再同一个机房时,大多会把该参数延长。

3.dubbo:protocol 数据传输使用的协议

1. id : 在大公司,可能因为各个部门技术栈不同,所以可能会选择使用不同的协议进行交互。这里 在多个协议使用时,需要指定。

2. name : 指定协议名称。默认使用 dubbo 。

4.dubbo:service 提供者能提供的服务

1. interface : 指定当前需要进行对外暴露的接口是什么。

2. ref : 具体实现对象的引用,一般我们在生产级别都是使用Spring去进行Bean托管的,所以这里面 一般也指的是Spring中的BeanId。

3. version : 对外暴露的版本号。不同的版本号,消费者在消费的时候只会根据固定的版本号进行消费。

4. executes: 用于在提供者做配置,来确保最大的并行度。
1. 可能导致集群功能无法充分利用或者堵塞 。
2. 但是也可以启动部分对应用的保护功能 。
3. 可以不做配置,结合后面的熔断限流使用。

5.dubbo:reference 消费者配置

1. mock: 用于在方法调用出现错误时,当做服务降级来统一对外返回结果,后面我们也会对这个方 法做更多的介绍。

2. timeout: 用于指定当前方法或者接口中所有方法的超时时间。我们一般都会根据提供者的时长来 具体规定。比如我们在进行第三方服务依赖时可能会对接口的时长做放宽,防止第三方服务不稳定 导致服务受损。

3. check: 用于在启动时,检查生产者是否有该服务。我们一般都会将这个值设置为false,不让其进 行检查。因为如果出现模块之间循环引用的话,那么则可能会出现相互依赖,都进行check的话, 那么这两个服务永远也启动不起来。

4. retries: 用于指定当前服务在执行时出现错误或者超时时的重试机制。
1. 注意提供者是否有幂等,否则可能出现数据一致性问题。
2. 注意提供者是否有类似缓存机制,如出现大面积错误时,可能因为不停重试导致雪崩。

5. id : 指定该Bean在注册到Spring中的id。

6. interface: 服务接口名 3. version : 指定当前服务版本,与服务提供者的版本一致。

7. registry : 指定所具体使用的注册中心地址。这里面也就是使用上面在 dubbo:registry 中所声 明的id。
8.cache:声明式缓存。

6 dubbo:method 指定具体方法级别在进行RPC操作时候的配置

1. name : 指定方法名称,用于对这个方法名称的RPC调用进行特殊配置。

2. async: 是否异步 默认false

配置讲解注解+properties形式

consumer配置

配置和启动类

public class ConsumerMain {
    // 启动方法
    public static void main(String[] args) throws IOException {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
        context.start();
        // 获取消费者组件
        ConsumerComponent service = context.getBean(ConsumerComponent.class);
        Executor executor = (Executor) context.getBean("taskExecutor");
        while(true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 35; i++) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        String result = service.methodA();
                    }
                });
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        String result = service.methodB();
                    }
                });
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        String result = service.methodC();
                    }
                });
            }
        }
    }

    // 配置静态类
    @Configuration
    @PropertySource("classpath:/dubbo-consumer.properties")
    @ComponentScan(basePackages = "com.my.study")
    @EnableDubbo
    static  class  ConsumerConfiguration{

    }
}

properties文件

dubbo.application.name=dubbo-provider
dubbo.protocol.name=dubbo
dubbo.protocol.port=20889
dubbo.application.owner=zhangsan
dubbo.registry.address=zookeeper://106.75.144.210:2181
dubbo.application.qosEnable=false
dubbo.application.qosPort=33334
dubbo.application.qosAcceptForeignIp=false

provider配置

provider配置application

dubbo.application.name=dubbo-provider
dubbo.protocol.name=dubbo
dubbo.protocol.port=20889
dubbo.application.owner=zhangsan
dubbo.registry.address=zookeeper://106.75.144.210:2181

dubbo.application.qosEnable=false
dubbo.application.qosPort=33334
dubbo.application.qosAcceptForeignIp=false

provider配置和启动类

public class DubboPureMain {
    // 启动方法
    public static void main(String[] args) throws  Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
        context.start();
        System.in.read();
    }

    // 配置静态类
    @Configuration
    @EnableDubbo(scanBasePackages = "com.my.study.service")
    @PropertySource("classpath:/dubbo-provider.properties")
    static  class  ProviderConfiguration{
        @Bean
        public RegistryConfig   registryConfig(){
            RegistryConfig  registryConfig  = new RegistryConfig();
            registryConfig.setAddress("zookeeper://106.75.144.210:2181?timeout=10000");
            //registryConfig.setTimeout(10000);
            return   registryConfig;
        }
    }
}}

1.@EnableDubbo(scanBasePackages =”com.my.study.service”)

提供者需要对外提供的方法直接通过包扫描的方式去进行注册到ioc中。

2.@Configuration

代表当前是个配置类

3.@PropertySource(“classpath:/dubbo-provider.properties”)

导入外部的文件并解析

4.@ComponentScan(basePackages =”com.my.study”)

将需要的类包扫描的方式去进行注册到ioc中。

总结

本文介绍的只是部分常用的配置,更多详细配置可以参考dubbo官方文档,配置模块的文档去了解学习。

0 14

如果你问我,实习期间最紧张最害怕的时刻是什么?

那一定是上线发版的时候。

 

年少轻狂三连击,服务全挂我挨批

公司的服务采用集群部署,发版时需要部署多台机器。当我第一次发版前,导师曾再三叮嘱我,项目发慢点,一台一台的发。那时我年少轻狂,觉得呆呆等着很无聊,于是一个三连击,仅有的三台机器同时发布,结果服务调用异常的报错铺天盖地而来

服务器部署服务的流程

服务部署在机器上,那么该机器就成了服务器,所有的用户请求都会发送到服务器上被处理。而当前互联网环境下,服务基本都是分布式/集群部署,也就是有多台服务器。各互联网企业在分布式/集群部署的环境下发布版本时,一定不会像我一样三连击,因为服务器部署服务的流程如下:

旧服务正在运行—>停掉旧服务—>部署新服务—>新服务启动

试想,三台服务器A,B,C工作的好好的,我先点击发布A机器,此时A机器先向注册中心发送消息——”我先走了哈,别把请求路由到我这里了”,然后Dubbo会将A机器从负载均衡策略中排除,如果A机器还有未处理的请求,它会先进行处理,之后服务彻底停止。(详细可参考Dubbo-优雅停机)停止后,A机器会部署新服务,也就是你发布的新版本,但是服务不是瞬间启动的它需要启动服务提供者,服务提供者在启动时还要向注册中心注册自己提供的服务,同时订阅自己需要的服务,等完成这些步骤后,A机器上的新服务才算是正式启动,才可以接收用户的请求(详细可参考Dubbo的简要执行流程)。显而易见,【停掉旧服务—>新服务启动】之间是需要耗费不少时间的,大概几分钟。

三连击为什么会导致服务挂掉呢?

原因就是 【停掉旧服务—>新服务启动】的这几分钟。A机器的服务还在启动中,此时A服务器不可用,而我又点击发布B机器,B机器的服务也进入了【停掉旧服务—>新服务启动】这个阶段,B服务器不可用,C机器同理。三连击导致A,B,C三台机器全部不可用,用户请求一过来就会报服务调用异常的错误

正确的流程应该是发布一台,观察一台的日志。A机器发布后,观察A机器的日志,确保A机器上的服务已经启动且有流量进入,这样的话不仅可以保证A机器可用,如果你的新版本出现了问题还可以立刻发现,此时就算需要回滚也只会影响A机器上的请求,B,C机器的服务是不受影响的,当然,最好的情况是任意一台机器都没有事故。

之所以服务器要进行分布式/集群部署,正是为了避免服务不可用。试想,如果淘宝618时用户无法下单,短短的几分钟可能会造成数以亿计的损失。所以一定要牢记,服务不可用是非常严重的事故。因此,涉及到集群环境下的服务部署,我们必须要考虑可用性及可靠性。

一台一台的发,我有一千台机器岂不是要发好几天?

非也,此处的一台一台发,强调的是一个百分比。我们知道,客户端请求会通过Dubbo的负载均衡策略选择路由到哪一台具体的服务器,如果你有A,B,C三台机器提供服务,一台一台的发可以保证任意时刻有2/3的机器可用,只要2/3的机器可以顶住当前的客户端流量,那就没有问题。(当然,如果2/3的机器顶不住,那你必须要加机器,不然的话流量会击垮B,C两台机器,服务彻底不可用)如果你有一千台机器,你完全可以一批10台或者20台的去发,尽管有10台或20台的机器不可用,但仍剩有99%或98%的机器可用,只要剩下的99%的机器可以顶得住当前流量,那就一点问题都没有。

一句话,多少台机器一起发,取决于发布时剩下可用的机器能否顶得住当前客户端流量。顶得住,没有任何问题;大大顶得住,甚至可以加大同时发布的机器数量,比如1000台只需要500台就足够顶住流量的话,直接50台50台的发布;顶不住的话,对不起,你还是老老实实的减少同时发布的机器数量吧~。

Dubbo-优雅停机

背景

对于任何一个线上应用,如何在服务更新部署过程中保证客户端无感知是开发者必须要解决的问题,即从应用停止到重启恢复服务这个阶段不能影响正常的业务请求。理想条件下,在没有请求的时候再进行更新是最安全可靠的,然而互联网应用必须要保证可用性,因此在技术层面上优化应用更新流程来保证服务在更新时无损是必要的。

传统的解决方式是通过将应用更新流程划分为手工摘流量、停应用、更新重启三个步骤,由人工操作实现客户端无对更新感知。这种方式简单而有效,但是限制较多:不仅需要使用借助网关的支持来摘流量,还需要在停应用前人工判断来保证在途请求已经处理完毕。这种需要人工介入的方式运维复杂度较高,只能适用规模较小的应用,无法在大规模系统上使用。

因此,如果在容器/框架级别提供某种自动化机制,来自动进行摘流量并确保处理完以到达的请求,不仅能保证业务不受更新影响,还可以极大地提升更新应用时的运维效率。

这个机制也就是优雅停机,目前Tomcat/Undertow/Dubbo等容器/框架都有提供相关实现。下面给出正式一些的定义:优雅停机是指在停止应用时,执行的一系列保证应用正常关闭的操作。这些操作往往包括等待已有请求执行完成、关闭线程、关闭连接和释放资源等,优雅停机可以避免非正常关闭程序可能造成数据异常或丢失,应用异常等问题。优雅停机本质上是JVM即将关闭前执行的一些额外的处理代码。

适用场景

  • JVM主动关闭(System.exit(int)
  • JVM由于资源问题退出(OOM);
  • 应用程序接受到SIGTERMSIGINT信号。

配置方式

服务的优雅停机

在Dubbo中,优雅停机是默认开启的,停机等待时间为10000毫秒。可以通过配置dubbo.service.shutdown.wait来修改等待时间。

例如将等待时间设置为20秒可通过增加以下配置实现:

dubbo.service.shutdown.wait=20000

容器的优雅停机

当使用org.apache.dubbo.container.Main这种容器方式来使用 Dubbo 时,也可以通过配置dubbo.shutdown.hooktrue来开启优雅停机。

通过QOS优雅上下线

基于ShutdownHook方式的优雅停机无法确保所有关闭流程一定执行完,所以 Dubbo 推出了多段关闭的方式来保证服务完全无损。

多段关闭即将停止应用分为多个步骤,通过运维自动化脚本或手工操作的方式来保证脚本每一阶段都能执行完毕。

在关闭应用前,首先通过 QOS 的offline指令下线所有服务,然后等待一定时间确保已经到达请求全部处理完毕,由于服务已经在注册中心下线,当前应用不会有新的请求。这时再执行真正的关闭(SIGTERM 或 SIGINT)流程,就能保证服务无损。

QOS可通过 telnet 或 HTTP 方式使用,具体方式请见Dubbo-QOS命令使用说明

流程

Provider在接收到停机指令后

  • 从注册中心上注销所有服务;
  • 从配置中心取消监听动态配置;
  • 向所有连接的客户端发送只读事件,停止接收新请求;
  • 等待一段时间以处理已到达的请求,然后关闭请求处理线程池;
  • 断开所有客户端连接。

Consumer在接收到停机指令后

  • 拒绝新到请求,直接返回调用异常;
  • 等待当前已发送请求执行完毕,如果响应超时则强制关闭连接。

当使用容器方式运行 Dubbo 时,在容器准备退出前,可进行一系列的资源释放和清理工。

例如使用 SpringContainer时,Dubbo 的ShutdownHook线程会执行ApplicationContextstopclose方法,保证 Bean的生命周期完整。

实现原理

Dubbo 优雅停机 | Apache Dubbo

 

Dubbo的简要启动流程

1. 服务器启动,运行服务提供者。

2. 服务提供者在启动时,向注册中心(zookeeper)注册自己提供的服务。

3. 服务消费者在启动时,向注册中心订阅自己所需的服务。

4. 注册中心返回服务提供者地址列表给消费者,(若有变更,注册中心将基于长连接推送变更数据给消费者)

5. 服务的消费者,从地址列表中,基于负载均衡,选一台提供者的服务器进行调用,若是失败,在从 地址列表中,选择另一台调用.

6. 期间Dubbo的监控中心,会记录定时消费者和提供者,的调用次数和时间

Dubbo的简要执行流程 – 简书 (jianshu.com)

0 38

问题出现的原因

由于Parallel Scavenge收集器的自适应能力,在环境改变的情况下,新生代内配比动态变化至不合理的状态(反应在文章中则是 Eden 与 Survivor的比例为100:1:1)
在这种状态下,Eden 区中存活下来的对象会迅速填满 Survivor 区,而我们知道,Survivor 区存在的意义就是减少被送到老年代的对象,进而减少 Full GC 的发生,当 Survivor 区太小,Young GC后存活下来的对象太多,无法放入 Survivor 区的时候,这些对象会被直接转移到老年代去,从而会加快 Old 区的填满速度,触发 Full GC
很明显,如果 Eden 与 Survivor 的比例始终异常,那么会频繁触发Full GC(这也正是文中提到的问题出现的原因之一)
当然,我们需要考虑到的是,Eden 与 Survivor 的比例异常有多种情况,如:

1.Survivor 太小(即100:1:1),这种情况会频繁触发 Full GC(因为削弱了S 区的垃圾拦截能力)
2.Survivor 够大,可能正常,也可能有其他情况

对应到文中,即为前辈所提到的 环境 ,即 因为问题触发是在代码未发生变化的大前提下产生,与当前环境有直接关系,而环境是一个变量,It could be better, it could be worse,如果针对现状进行参数整改,可能也仅仅只能解决一时。

我对环境一词的理解

该项目在运行过程中状态的不断改变,就叫环境
因为我们无法完整的监控运行状态的改变,因此环境具有不确定性
而调整策略:部分机器配置调整,新生代收集器由Parallel Scavenge切换为ParNew(并行收集器,全程STP,停顿少,效率高,没有自适应功能,可以保证比例不变),是为了通过解决问题一:稳定Eden 与 Survivor 区内配比,减少环境的不确定性

后续优化的方向

通过模拟,监控,观察运行状态的规律,如峰值,波形等,确定一些参数,从而减少环境的不确定性

补充:-XX:PretenureSizeThreshold
-XX:PretenureSizeThreshold,设置大对象直接进入年老代的阈值。-XX:PretenureSizeThreshold只对串行回收器和ParNew有效,对ParallGC无效。默认该值为0,即不指定最大的晋升大小,一切由运行情况决定。
该参数对ParNEW收集器有效,如果我们能确定(规律也可)运行状态下的大对象的个数范围和大小,可以设置该参数,可避免年轻代里出现大对象,屡次躲过GC,在两个Survivor区域里来回复制多次之后才能进入老年代的情况,从而得到优化

0 16

久仰 Dubbo 大名,正好公司需要使用,特此学习

 

一、学习方法 —> 带有目的去看官方文档

因为我本身了解过RPC框架的大体架构和原理(理论+简单的实现),零散的学习过分布式,微服务的概念,使用 Dubbo+zookeeper 实现了简单的远程调用,有一定的基础,因此现阶段最需要的是 系统的梳理 + 知识的整合。

官方文档是最全面(利于整合),最顶层(利于梳理)的。

因此,我建议在开发过程中,如果需要学习一门新的技术,先思考自己是否有一定的基础,如果有,那么在学习官方文档的时候,就应该带有两个目的去学习

  1. 系统的梳理 
  2. 知识的整合(缺少的则趁此补充)

这样下来,不仅学会了其使用方法,也夯实了所有知识,打通全身脉络。

 

二、开始分析

Apache Dubbo 是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力。这

意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通信能力, 同时利用 Dubbo 提供的丰富服务治理能力,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。同时 Dubbo 是高度可扩展的,用户几乎可以在任意功能点去定制自己的实现,以改变框架的默认行为来满足自己的业务需求。Dubbo3 基于 Dubbo2 演进而来,在保持原有核心功能特性的同时, Dubbo3 在易用性、超大规模微服务实践、云原生基础设施适配、安全设计等几大方向上进行了全面升级。 以下文档都将基于 Dubbo3 展开。

上述为Dubbo3简介的第一段话,可分析得出:

(1)Dubbo服务于 微服务开发框架

1.什么是微服务架构(组件化,服务化,以关联的业务逻辑为边界)

微服务架构强调“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发,涉及,运行的小应用,这些小应用之间通过服务完成交互和集成微服务架构将相关联的业务逻辑及数据放在一起形成独立的边界,其目的是能在不影响其他应用组件(微服务)的情况下更快地交付并推出市

举例:航班预定应用

将航班预订应用划分为预订航班、时间表查询、计算票价、分配座位、管理奖励、更新客户、调整库存七个微服务实施

举例:先享后付应用

将先享后付应用划分为信用审核,资格申请,商家接入,交易完成四个微服务实施。

2.总结

Dubbo服务于 微服务架构,通过Dubbo可以将应用业务彻底的组件化和服务化,通过组件化和服务化,各个微服务可以自行部署,设计,开发,使得应用更加灵活,开发更加敏捷,服务的可用性更高。(例如信用审核由A小组开发,资格申请由B小组开发,这样两个小组同时进行,可加快开发效率;业务的组件化增强服务可用性,例如商家接入组件的更新不会影响到用户的信用审核及资格申请;微服务的语言无关性使应用更加灵活,例如商家接入组件使用Java语言开发,完成交易组件可以使用追求效率的Go语言)

 

(2)Dubbo提供的两大关键能力—RPC通信 与 微服务治理

RPC通信

1.首先明确RPC通信是一种通信方式(进程间8种通信方式详解 – 云+社区 – 腾讯云 (tencent.com)进程间通信的几种方式 – 云+社区 – 腾讯云 (tencent.com)

通信方式包括:

  • 管道(pipe)
  • 消息队列(消息传递系统)
  • 信号量通信(消息传递系统)
  • 信号(消息传递系统)
  • 共享内存通信(共享存储器系统)
  • 套接字通信(C/S系统)
  • RPC(C/S系统)

2.RPC通信具体描述

RPC—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

3.RPC通信所带来的问题(谁能用通俗的语言解释一下什么是 RPC 框架? – 知乎 (zhihu.com)

  • Call ID映射(即服务注册,发现)
  • 序列化和反序列化(序列化协议,如hessian,dubbo)
  • 网络传输(数据发送模型)

4.总结

进程间的通信方式有多种,而RPC通信是一种基于C/S系统的通信方式,RPC通信屏蔽应用层和传输层(可理解为RPC框架完成了这两层的功能,实现方式可以自定义),这种方式使得远程调用和本地调用一样简单,但与此同时,RPC通信带来一些问题,如服务注册,服务发现,序列化和网络传输等;

Dubbo则是RPC通信的一种实现,提供Client-Based的服务发现机制,通过部署额外的第三方注册中心组件来协调服务发现过程,如Nacos,Zookeeper等;它支持多种通信协议(如Dubbo3,Dubbo2)实现序列化+网络传输。

 

微服务治理

1.什么是服务治理?

因为某些原因,我们选择了微服务架构,而微服务架构的特点和实现决定了它有一些待解决的问题。我们的目的是使项目通过微服务架构运行起来,那么我们就必须解决这些问题。

可以用这个例子来思考:

微服务运行起来—>人是健康的

微服务待解决的问题—>人生病了(可能是咳嗽(服务不问题))…

服务治理—>给人治病,而且是对症下药

总结:服务治理就是为了完成项目在微服务架构下的部署和运行这个目的,而对该架构的问题的解决。

2.服务治理究竟要治的是什么?

让我们先放下微服务,像《微服务设计》那本书中说的一样,把自己想象成一个城市规划师,我们的目标不是治理微服务,而是要治理一个城市的交通,那么我们会怎么思考?

 

在进行城市交通规划之前首先要做的第一个事情是收集信息,要能够知道这个城市发生了什么,所以在各个路口需要安装采集探头,记录车来车往的信息。有了信息以后就需要对信息进行分析,那么就需要可视化的图形界面,能够一眼就看出什么地方出了问题,通往哪个工厂的路坏了。发现了问题就要解决问题了,限制一下拥堵路段的流量,把去往一个公园的车辆导向到另外一个类似的公园。最后,如果把城市作为一个国家来考虑,那么每个进入这个城市的车辆都需要进行检查,看看有没有携带违禁品,最后给这些不熟悉道路的外地车规划路线。通过上面这个思考的过程,我们发现要对一个城市进行治理的时候,第一要采集信息,然后要能够对采集的信息进行监控和分析,最后根据分析的结果采取对应的治理策略。另外从整体安全的角度考虑还需要一个守门人

守门人—>采集信息—>监控和分析—>治理

因此我们也用同样的思路来思考服务治理,网关就是整个整体的守门人,日志采集,追踪工具,服务注册发现都是用来采集信息的,然后需要监控平台来展现这些采集的信息,并进行监控和分析。最后根据分析的结果采取治理策略,有的服务快撑不住了要限流,有的服务坏了要熔断,并且还能够及时的调整这些服务的配置。

下面的脑图就从这四个方面构建了一个简易的服务治理体系:请求网关,信息采集,信息分析,治理策略总结:微服务治理可以简易的分成四个方面,分别是请求网关,信息采集,信息分析,治理策略

 三、参考

0 26

环境介绍

  • Windows 10
  • Jdk1.8
  • Maven 3.6.3
  • zookeeper 3.6.2
  • dubbo 2.7

Zookeeper安装

zookeepr下载

zookeeper3.6.2 下载路径

zookeeper安装

参考

Windows下安装Zookeeper – Our home (yangbili.co)

 

启动zookeeper

 

dubbo-admin安装

下载dubbo-admin

dubbo-admin下载地址

在GitHub上下载dubbo admin,选择zip压缩包方式下载

目录结构如下:

 

前端打包运行

dubbo-admin的新版本已经采用了前后端分离的方式,所以我们部署时也要采用这种方式

进入dubbo-admin-ui目录下,执行以下命令:

npm install
npm run dev
注:如提示 npm 非可用的命令则表示你需要先安装node js,并正确配置其环境

npm run dev 成功后,会出现两个访问连接,点击任何一个都可以

 

后端打包运行

配置修改

进入目录 dubbo-admin-server/src/main/resources,修改application.properties配置文件

这里对于zookeeper默认的端口是2183,之前我们配置zookeeper的时候,设置的是2181,所以需要将这里也改成2181,不然admin会找不到zookeeper服务器。

# centers in dubbo2.7
admin.registry.address=zookeeper://127.0.0.1:2181
admin.config-center=zookeeper://127.0.0.1:2181
admin.metadata-report.address=zookeeper://127.0.0.1:2181

改完保存即可

打包运行

进入到dubbo-admin-server目录下,执行命令:

# 第一次执行需要先安装maven
mvn clean package

最后看到BUILD SUCCESS说明构建成功了

构建成功后运行,进行到dubbo-admin-server\target的目录下,执行jar包:

java -jar dubbo-admin-server-0.4.0.jar

jar包执行成功后,通过前端地址就可以进行访问了(http://localhost:8082/

总结四部曲:

1.启动zookeeper

2.启动dubbo-admin-ui

3.启动dubbo-admin-server

4.进入前端页面即可查看

Windows下dubbo-admin安装 – skytechfyh – 博客园 (cnblogs.com)