文章目录

平常心博客

平常心的日常积累

标签: SpringBoot (31)

【转载】Spring Cloud(四)服务提供者 Eureka + 服务消费者 Feign

上一篇文章,讲述了如何通过RestTemplate+Ribbon去消费服务,这篇文章主要讲述如何通过Feign去消费服务。

一、Feign简介

Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

Feign 具有如下特性:

  • 可插拔的注解支持,包括Feign注解和JAX-RS注解
  • 支持可插拔的HTTP编码器和解码器
  • 支持Hystrix和它的Fallback
  • 支持Ribbon的负载均衡
  • 支持HTTP请求和响应的压缩 Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。它整合了Ribbon和Hystrix,从而不再需要显式地使用这两个组件。Feign还提供了HTTP请求的模板,通过编写简单的接口和注解,就可以定义好HTTP请求的参数、格式、地址等信息。接下来,Feign会完全代理HTTP的请求,我们只需要像调用方法一样调用它就可以完成服务请求。

简而言之:Feign能干Ribbon和Hystrix的事情,但是要用Ribbon和Hystrix自带的注解必须要引入相应的jar包才可以。

Eureka Server

提供服务注册和发现服务

添加依赖

在项目 spring-cloud-eureka-service pom.xml中引入需要的依赖内容:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>

【转载】Spring Cloud(三)服务提供者 Eureka + 服务消费者(rest + Ribbon)

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTP和TCP的客户端负载均衡器。它可以通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的作用。

Ribbon是什么?

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。

LB方案分类

目前主流的LB方案可分成两类:一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;另一种是进程内LB,将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就属于后者,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

Ribbon的主要组件与工作流程

微服务架构的核心思想是,一个应用是由多个小的、相互独立的、微服务组成,这些服务运行在自己的进程中,开发和发布都没有依赖。 不同服务通过一些轻量级交互机制来通信,例如 RPC、HTTP 等,服务可独立扩展伸缩,每个服务定义了明确的边界,不同的服务甚至可以采用不同的编程语言来实现,由独立的团队来维护。 简单的来说,一个系统的不同模块转变成不同的服务!而且服务可以使用不同的技术加以实现!

Ribbon的核心组件

均为接口类型,有以下几个:

ServerList

  • 用于获取地址列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)。

ServerListFilter

  • 仅当使用动态ServerList时使用,用于在原始的服务列表中使用一定策略过虑掉一部分地址。

IRule

  • 选择一个最终的服务地址作为LB结果。选择策略有轮询、根据响应时间加权、断路器(当Hystrix可用时)等。

Ribbon在工作时首选会通过ServerList来获取所有可用的服务列表,然后通过ServerListFilter过虑掉一部分地址,最后在剩下的地址中通过IRule选择出一台服务器作为最终结果。

【转载】Spring Cloud(二)Consul 服务治理实现 有更新!

Spring Cloud Consul 项目是针对Consul的服务治理实现。Consul是一个分布式高可用的系统,具有分布式、高可用、高扩展性。

Consul 简介

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,Consul的方案更“一站式” ,内置了服务注册与发现框 架、具有以下性质:

  • 分布一致性协议实现、
  • 健康检查、
  • Key/Value存储、
  • 多数据中心方案,

不再需要依赖其他工具(比如ZooKeeper等)。

使用起来也较 为简单。Consul使用Go语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与Docker等轻量级容器可无缝配合 。 基于 Mozilla Public License 2.0 的协议进行开源. Consul 支持健康检查,并允许 HTTP 和 DNS 协议调用 API 存储键值对. 一致性协议采用 Raft 算法,用来保证服务的高可用. 使用 GOSSIP 协议管理成员和广播消息, 并且支持 ACL 访问控制.

Consul 的使用场景

  • docker 实例的注册与配置共享
  • coreos 实例的注册与配置共享
  • vitess 集群
  • SaaS 应用的配置共享
  • 与 confd 服务集成,动态生成 nginx 和 haproxy 配置文件

【转载】Spring/Boot/Cloud系列知识(7)——Spring Aspectj EL(3) 有更新!

(接上文《Spring/Boot/Cloud系列知识(6)——Spring EL(2)》)

3.3、Spring EL 与 AOP(Aspectj)

3.3.1、Spring 和 AOP的关系

AOP是面向切面编程的简称,Spring的设计思路受到这个思想的指导。所以我们在使用Spring各种组件的时候都能看到这个设计思路的影子。
2f4cdb3be2f842b0ac5612d8822ee96a-20171104181037554.png
再举一些实际的例子:我们使用Spring托管hibernate就是一个典型的AOP例子,事务的开启、提交、回滚操作无需业务开发人员进行,全部在业务方法之外自动完成;Spring Cache组件的使用也是一个典型的AOP实例,完成Spring Cache EL的配置后,对Redis/Memcache或者Google Cache的操作完全不需要书写额外代码,全部在业务方法以外完成;而我们之前介绍的Spring中使用的两种代理模式,也是基于AOP思想,无论是JAVA原生动态代理还是Cglib动态代理,都无需业务开发者书写一行额外代码即可完成代理过程。由此可见AOP思想在Spring中的体现是深入的、延续的且广泛的。

【转载】Spring/Boot/Cloud系列知识(6)——Spring EL(2) 有更新!

接上文《Spring/Boot/Cloud系列知识(5)——Spring EL(1)》)

3、Spring EL 与第三方信息

3.1、Spring EL 与 集合

Spring EL基本表达式可以对集合中的信息进行读取操作,包括Collection、Map性质的集合。请看如下实例:

/**
 * 在这个bean被初始化时,进行集合数据的添加
 * @author yinwenjie
 */
@Component("myCollection")
public class CollectionPojo {
  private List<String> myList;
  private Map<String, Object> myMap;
  /**
   * 保证spring在构造这个bean实例时
   * 就向两个集合中写入了数据
   */
  public CollectionPojo() {
    this.myList = Arrays.asList(new String[]{"数据1","数据2","数据3","数据4"});
    this.myMap = new HashMap<>();
    myMap.put("key1", "value1");
    myMap.put("key2", "value2");
    myMap.put("key3", "value3");
  }
  ......
}

【转载】Spring/Boot/Cloud系列知识(5)——Spring EL(1) 有更新!

1、Spring EL 概述

Spring EL是Spring Expression Language的简称,中文称作Spring表达式语言。Spring EL并不单单指代某一种特定的表达式格式,而是对Spring中字符串表达式的一个概要性称呼。Spring EL基本功能由Spring核心包提供支持(spring-core组件和spring-context组件),并且不同的组件还对Spring EL的基本功能提供扩展。本文(及后续一文)主要对读者会在实际工作中使用到的Spring EL 进行讲述,并在最后结合一个使用Spring EL 完成自定义注解实例。

2、Spring EL 基本使用

Spring EL 的使用非常灵活,并且主要由“@Value”注解标记进行支撑。“@Value”注解可以在属性、方法上使用,通过这个注解可以基于IOC容器中的bean对象、对象属性、对象方法、操作符计算结果、正则表达式匹配结果、应用程序配置结果、操作系统环境变量配置结果等等,对目标属性、方法入参进行赋值

【转载】Spring/Boot/Cloud系列知识(4)——代理模式(下) 有更新!

接上文《Spring/Boot/Cloud系列知识(3)——代理模式(中)》)

3.3 Proxy.newProxyInstance内部如何完成工作的

我们来看看org.mockito.cglib.proxy.Proxy.newProxyInstance这个方法内部的代码:

public class Proxy implements Serializable {
    ......

    // 这个常量BADOBJECTMETHOD_FILTER(代理选择器)的设定,等一下会用到
    // 实际上代码也清楚,一般情况下执行第0个代理器,如果是代理执行java.lang.Object中的方法
    // 且这些方法又不是hashCode()、equals()、toString(),则执行第1个代理器
    private static final CallbackFilter BADOBJECTMETHOD_FILTER = new CallbackFilter() {
        public int accept(Method method) {
            if (method.getDeclaringClass().getName().equals("java.lang.Object")) {
                String name = method.getName();
                if (!(name.equals("hashCode") ||
                      name.equals("equals") ||
                      name.equals("toString"))) {
                    return 1;
                }
            }
            return 0;
        }
    };

    ......

    // private for security of isProxyClass
    private static class ProxyImpl extends Proxy {
        protected ProxyImpl(InvocationHandler h) {
            super(h);
        }
    }

    ......

    // 该方法中使用了Cglib中对ASM freamework的封装,动态创建一个class定义
    public static Class getProxyClass(ClassLoader loader, Class[] interfaces) {
        Enhancer e = new Enhancer();
        // 为这个class设置一个父类,这个父类名叫ProxyImpl,其中定义了一个构造函数
        // 那个构造函数需要传入个代理器对象
        e.setSuperclass(ProxyImpl.class);
        // 然后为这个class设置接口,请注意,可以设置多个接口哦
        e.setInterfaces(interfaces);
        // 为这个动态class设置代理器类型,设定了这个方法就应该使用CallbackFilter设定代理选择器(过滤器)
        e.setCallbackTypes(new Class[]{
            InvocationHandler.class,
            NoOp.class,
        });
        // 这个我们使用了Proxy中,在前文定义好的BADOBJECTMETHOD_FILTER常量,请参见
        //  
        e.setCallbackFilter(BADOBJECTMETHOD_FILTER);
        e.setUseFactory(false);
        // 最后创建这个动态class(注意是创建class,并不是这个class的实例)
        return e.createClass();
    }

    ......

    // newProxyInstance方法中实际上就是两句话,重要的代码都在getProxyClass这个方法中。
    public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) {
        try {
            // 该方法用来动态创建一个class,请参考方法中的内容
            Class clazz = getProxyClass(loader, interfaces);
            // 很显然,通过以上方法我们拿到了一个动态class,这个class有三个重要特点,
            // 1、这个class有一个带有参数的构造函数,这个参数就是需要我们传入代理器接口的一个实现实例。
            // 2、这个class实现了我们需要它实现的一个或者多个接口——没有实现代码,但是有这样的类结构
            // 3、这个class设定了两个代理器,通常执行第0个代理器,就是我们传入的InvocationHandler h对象
            // 另外,如果是代理执行java.lang.Object中的方法
            // 且这些方法又不是hashCode()、equals()、toString(),则执行第1个代理器
            //
            // 接着,我们执行第二句代码,这句代码初始化一个这个动态类的示例,并传入代理器实例对象
            return clazz.getConstructor(new Class[]{ InvocationHandler.class }).newInstance(new Object[]{ h });
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        }
    }

    ......
}

要阅读本小节以上代码片段,请从上篇文章中newProxyInstance()方法开始看。

【转载】Spring/Boot/Cloud系列知识(3)——代理模式(中) 有更新!

接上文《Spring/Boot/Cloud系列知识(2)——代理模式(上)》)

2.2、代理模式在Spring中的应用

那么java中基于java.lang.reflect.Proxy的动态代理模式和Spring生态有什么关系呢?Spring中的所有Bean实例存储在一个名叫IOC容器(Inversion of Control 控制反转容器)中。这个容器中存在着接口和实现类的对应关系(也可以直接存储类的实例,无需这个类有任何接口的实现),而其中Bean实例的存储方式都默认采用单例保存。

一般情况下我们可以通过BeanFactory(Spring IOC容器工厂)接口中getBean()方法,直接获取到这个接口在IOC容器中对应的实例。但当我们需要为这个Bean实例附加AOP切面操作时,这个实例就会被代理——视这个实例实现接口的情况和Spring的配置情况,又可以区别为使用Proxy动态代理还是使用Cglib代理。如下图所示:

【转载】Spring/Boot/Cloud系列知识(2)——代理模式(上) 有更新!

代理模式是23种设计模式中的一种,属于一种结构模式。用一句大白话解释这个设计模式:当外部调用者调用A来完成一件事情/一个动作时,并不直接调用A本身,而是调用一个代理者,并再由代理者负责调用真实的执行者A,最终达到间接调用的目的。

代理模式(动态)和Cglib代理是Spring生态中的最基础设计原理之一,所以要了解Spring的工作原理就必须先讨论清楚代理模式的设计思路(无论是静态代理还是动态代理)。

1. 代理模式(静态)

5990d0eccc734dcca2dbb043443692fa-20170906204228195.png
(代理模式——静态)

上图显示了一个标准的代理模式(静态)类关系结构。在标准的代理模式(静态)中,至少存在以下角色:

  • Subject接口或抽象角色:对于外部调用者来说只关心调用操作是否被执行,而不会关心本次调用是被直接执行的还是被代理者间接执行的。所以一般来说代理执行者会实现和被代理者相同的接口(或抽象类),“伪装”成被代理的对象(上图中就是伪装成RealSubject类)。

  • RealSubject:被代理的真实业务执行者。简单来说就是真实业务由这个角色负责执行,只是为了在业务处理前后能够执行其它操作,所以真实业务执行者才会被代理(上图中就是被Proxy代理)。

  • Proxy:代理执行者。代理执行者内部引用了真实执行者,并根据需要在真实业务执行前后,执行其它操作:例如判断入参是否符合要求、打开数据库连接、捕获异常发送到事件搜集器中……

以下的代码片段说明了代理模式(静态)中以上几个工作角色的简单实现:

【转载】Spring/Boot/Cloud系列知识(1)——开篇 有更新!

1. 开篇序

各位支持我的朋友大家好啊,博客停了两个月处理了一些私人事务。从今天开始本人恢复技术博客更新。欢迎大家继续关注

1.1 写作难度在哪里

Spring系列知识这个博文专题实际上很早之前就想写写,但是一直没有动笔或者说没敢动笔。究其原因主要有几个:

1、这个系列的博文专题并不好写,Spring Framework知识体系太过庞大,远远超过本人之前所写的线程专题、系统间通讯专题、负载均衡专题和系统存储专题。Spring生态从很早的2.X版本到3.X版本再到当前的4.X版本、从最初的XML配置到注解性配置,再到现在最流行的Java Style配置、从单纯的Spring Framework到Spring Boot,再到目前流行的Spring Cloud服务治理生态……我一个小小的IT屌丝哪里能全部掌握……

【转载】SpringCloud(一) 服务的注册与发现(Eureka) 有更新!

SpringCloud 服务的注册与发现(Eureka)

Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式。

Spring Cloud简介

Spring Cloud包含了多个子项目(针对分布式系统中涉及的多个不同开源产品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud0 CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI等项目。

浏览次数:2733304   文章总数:80   评论总数:9   当前访客:7
平常心博客 © 2018 ×
¥
每天领支付宝红包
Powered by B3log 开源Solo 2.4.0