SpringCloud 微服务简介

一、概述

微服务:一系列微小的服务共同形成,每个服务跑在自己的进程里,每个服务为独立的业务开发。

  • 一系列微小的服务共同组成
  • 单独部署,跑在自己的进程里
  • 每个服务为独立的业务开发
  • 分布式的管理

微服务的基础框架

国内实现微服务的两种主要方法

二、Eureka服务注册与发现

SpringCloud是使用Eureka进行服务注册与发现,Dubbo使用Zookeeper进行相应工作。并且自动实现了心跳检测,负载均衡等功能。

两个主要组件:

  1. Eureka Server 注册中心
  2. Eureka Client 服务注册

2.1 Eureka Server注册中心

Server端的配置yml文件样例如下:

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    register-with-eureka: false

spring:
  application:
    name: eureka
server:
  port: 8761

同时需要在Application类中添加注解@EnableEurekaServer

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

2.2 Eureka Client注册中心

Server端的配置yml文件样例如下:

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
spring:
  application:
    name: hello

同时需要在Application类中添加注解@EnableDiscoveryClient

@SpringBootApplication
@EnableDiscoveryClient
public class ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}

2.3 Eureka Server高可用

Eureka需要两两互相注册,相应的Client端写每个Eureka的地址,用逗号分割每个地址。

2.4 服务发现的两种方式

  • 客户端发现:由客户端从众多可用的服务列表中,挑选一个获取它的实际IP,并进行访问。这种实现方式要求客户端实现一套自己的选择机制。
  • 服务端发现:用代理的方式,由服务端帮客户端选择具体的某个服务器,对客户端透明

三、应用间通信

HTTP vs RPC,SpringCloud采用HTTP RESTful,而Dubbo采用RPC。

SpringCloud中服务RESTful两种调用方式

  • RestTemplate
  • Feign

3.1 RestTemplate的三种使用方式

第一种使用方式:

@GetMapping("/getProductMsg")
public String getProductMsg(){
    RestTemplate restTemplate=new RestTemplate();
    String response=restTemplate.getForObject("http://localhost:8080/msg",String.class);
    return response;
}

其中http://localhost:8080/msg为所需要的服务的url,String.class为该服务的返回值类型。

但是该种方式需要写死URL,且面临负载均衡多URL的情况。

第二种使用方式:

@Autowired
LoadBalancerClient loadBalancerClient;

@GetMapping("/getProductMsg")
public String getProductMsg(){
    RestTemplate restTemplate=new RestTemplate();
    ServiceInstance serviceInstance=loadBalancerClient.choose("PRODUCT");
    serviceInstance.getHost();
    String url=String.format("http://%s:%s/msg",serviceInstance.getUri(),serviceInstance.getPort());
    String response=restTemplate.getForObject(url,String.class);
    return response;
}

通过ServiceInstance动态获取指定服务的url。

第三种使用方式:

首先用bean的形式配置一下

@Component
public class RestTemplateConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

其次在逻辑中:

@Autowired
RestTemplate restTemplate;

@GetMapping("/getProductMsg")
public String getProductMsg(){
    String response=restTemplate.getForObject("http://PRODUCT/msg",String.class);
    return response;
}

这种使用方式更加简单

3.2 Feign的使用方式

Feign是一个声明式REST客户端(伪RPC),采用接口+注解的方式使用。

首先需要在POM文件当中,添加一个dependency

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-openfeign-core</artifactId>
    <version>2.1.0.M2</version>
</dependency>

其次在主类上添加注解

@EnableFeignClients

第三步,定义好需要使用的接口

@FeignClient(name="product")
public interface ProductClient {
    @GetMapping("/msg")
    String productMSG();
}

其中name为需要调用的服务名称,GetMapping为需要调用的具体url名称

第四步,在逻辑中使用

@Autowired
ProductClient productClient;

@GetMapping("/getProductMsg")
public String getProductMsg(){
    String response=productClient.productMsg();
    return response;
}

3.3 客户端负载均衡器:Ribbon

SpringCloud由于采用客户端负载均衡策略,由客户端从服务器拉取可用列表,并且选取某个服务,固采用Ribbon,以下服务均使用到了Ribbon:

  • RestTemplate
  • Feign
  • Zuul

Ribbon实现软负载均衡核心有三点:

  1. 服务发现
  2. 服务选择规则
  3. 服务监听

Ribbon主要组件:

  • ServerList,首先获取所有可用服务列表
  • IRule 最后在剩下的地址中,通过IRule选择一个实例作为最后的结果
  • ServerListFilter 第二部用ServerListFilter过滤掉部分地址

Ribbon默认负载均衡策略:

轮询,如果要更改策略去官网找相应的配置文件配置即可

四、统一配置中心

统一配置中心可以对项目的配置进行统一管理,很方便的在不同的配置间切换。统一配置中心也有相应的Server端和Client端。

Server端会从远端Git将配置拉取下来,放到本地Git中(如果远端git无法访问,则从本地git读取配置),之后其他服务会从Server端读取相应配置。

4.1 Config Server端

首先在创建项目的时候需要勾选Eureka Discovery以及Config Server,因为其本身也是一个微服务Client。

要在Application类中添加注解@EnableDiscoveryClient,@EnableConfigServer

@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}

在ConfigServer的yml文件中添加git的地址,git当中存放的应该是配置文件(yml文件)。

spring:
  cloud:
    config:
      server:
        git:
          uri: 地址
          username: 
          password:

配置完成之后,项目可以自动根据url仓库地址进行映射,例如访问localhost:8080/product-a.yml。后缀名可以转换,例如转换成.json或者.properties,都可以自动转换格式。

注意:

product-a.yml之中的-a是必须加的,否则访问不到。代表的是不同的环境,不同的环境通过在yml文件当中添加注解例如env:a来解决。

并且如果有一个文件名字为product.yml,那么在访问所有其他分支文件的时候,会自动将该文件中的内容合并到访问的文件中,即根文件应该用来放一些通用配置,避免在分支文件中重复书写。

4.2 Config Client端

同Server端一样,首先引入依赖

<dependency> 
      <groupId>org.springframework.cloud</groupId> 
      <artifactId>spring-cloud-config-client</artifactId> 
</dependency>

启动类上不需要加注解,在yml文件中添加相关配置项,并且需要将yml文件改名为bootstrap.yml,该名称可以让SpringBoot优先加载该配置文件。否则会出现数据库配置相关问题。

spring:
  application:
    name: order
  cloud:
    config:
      discovery:
        enabled: true
        service-id: Config//该项为ConfigServer在注册中心中注册的名称
      profile: dev

4.3 Bus自动刷新配置

通过Spring Cloud Bus自动刷新配置可以实现配置的热更新,即不重启服务的情况下更新配置。

 

4.3.1 原理分析

其原理是在添加了Bus组建后,ConfigServer会对外提供一个HTTP api接口,每次Git端更新配置后,访问该接口,ConfigServer便会将更新的配置通过MQ推送到各个Client端中。

4.3.2 Bus配置

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-bus-amqp</artifactId> 
</dependency>

在ConfigServer以及Client端中添加上述maven配置,然后再ConfigServer中配置yml文件,暴露接口。

management:
  endpoints:
    web:
      expose: "*"

坑点:

在更新配置后,需要在Client端使用配置的地方添加注解@RefreshScope。

每次更新完后,访问ConfigServer的localhost:8080/bus-refresh即可更新配置。