微服务框架SpringCloud学习--记录

目录

一、微服务框架简介

1.阿里系

2.SpringCloud系

3.微服务涉及的其它技术

二、SpringCloud图解

三、SpringCloud实操步骤

1.新建SpringBoot项目,SpringCloud是建立在SpringBoot基础之上的,所以以下所有工程都是SpingBoot工程

官方向导搭建boot应用:http://start.spring.io

普通maven工程搭建boot应用

2.建立Eureka(服务注册与发现)服务端与客户端,客户端既为实际微服务,也就是写业务代码的地方

服务端:加入spring cloud父POM及spring-cloud-starter-eureka-server

服务端:application.properties

服务端:启动类增加注解@EnableEurekaServer

客户端:加入spring cloud父POM及spring-cloud-starter-eureka

客户端:application.properties

客户端:启动类增加注解@EnableEurekaClient

客户端:增加负载均衡配置(默认策略为轮询),eureka默认引入了Ribbon依赖包,所以这里不需要显性引入

3、引入Hystrix(豪猪),提高系统容错性

消费端引入Springcloud Hystrix依赖

使用Hystrix注解@HystrixCommand实现降级逻辑 

Hystrix超时、熔断配置

Hystrix限流配置

 Feign整合Hystrix

Histrix监控

Hystrix Dashboard可视化监控数据

使用Turbine聚合监控数据(这里需要新建一个SpringBoot项目)

4.zuul微服务网关

添加依赖并在启动类上增加注解@EnableZuulProxy,并将自己注册到Eureka

zuul聚合微服务,在zuul网关项目中编写controller

zuul的路由配置

zuul过滤器

zuul的容错与回退

5.SpringCloudConfig分布式集中配置中心

新建SpringCloudConfig服务端,添加依赖、添加配置

编写config配置中心客户端

配置信息的加解密安全处理

配置信息手动刷新

配置信息自动刷新(需安装rabbitMQ)

6.Sleuth分布式链路跟踪

客户端整合sleuth,添加依赖

新建Zipkin Server项目,添加依赖

客服端整合Zipkin,添加依赖,配置文件

用Elasticsearch存储Zipkin的数据(需安装Elasticsearch)


一、微服务框架简介

微服务框架包括阿里系和SpringCloud系(C一致性,A可用性,P容错性),其中容错性是必须的,阿里系偏向于一致性,SpringCloud系偏向于可用性,本文主要介绍SpringCloud。

1.阿里系

  • Zookeeper(hadoop,服务注册与发现,CP)
  • Dubbo(客户端负载均衡)
  • ……(待补充)

2.SpringCloud系

  • Eureka(服务注册与发现,AP):Ribbon(客户端负载均衡)、Feign(PRC,声明式http客户端)
  • Hystrix(服务隔离组件,容错,防止雪崩,降级,超时,熔断,限流):Hystrix与Feign结合、DashBoard(监控面板)与Turbine聚合
  • Zuul(微服务网关,默认集成了Ribbon和Hystrix):聚合、裁减、路由、过滤、限流、容错、监控、认证
  • SpringCloudConfig(配置中心):JEC(加密工具)、SpringBootActuator(单个手动刷新)、SpringCloudBus(统一自动刷新,需安装RabbitMQ)
  • Sleuth(分布式链路跟踪):整合zipkin、用Elasticsearch存储zipkin数据(需安装Elasticsearch,也可以用ELK)

3.微服务涉及的其它技术

  • 消息中间件:RabbitMQ、ActiveMQ、RocketMQ、Kafka
  • 容器引擎:docker(部署工具K8s或jinkins)

二、SpringCloud图解

PS:自己画的图,不完善,有机会再更新

三、SpringCloud实操步骤

1.新建SpringBoot项目,SpringCloud是建立在SpringBoot基础之上的,所以以下所有工程都是SpingBoot工程

  • 官方向导搭建boot应用:http://start.spring.io

  • 普通maven工程搭建boot应用

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.10.RELEASE</version>
</parent>

2.建立Eureka(服务注册与发现)服务端与客户端,客户端既为实际微服务,也就是写业务代码的地方

  • 服务端:加入spring cloud父POM及spring-cloud-starter-eureka-server

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>Edgware.SR3</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
    </dependencies>
</dependencyManagement>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
  • 服务端:application.properties

server.port=8761
#取消向eureka server(注册中心)注册
eureka.client.register-with-eureka=false
#取消向eureka server(注册中心)获取注册信息
eureka.client.fetch-registry=false
#eureka 提供服务发现的地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
  • 服务端:启动类增加注解@EnableEurekaServer


  • 客户端:加入spring cloud父POM及spring-cloud-starter-eureka

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>Edgware.SR3</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  • 客户端:application.properties

spring.application.name=microservice-order
server.port=8081

eureka.client.serviceUrl.defaultZone=http://user:password@localhost:8761/eureka
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=${spring.application.name}:${spring.application.instance_id:${server.port}}
  • 客户端:启动类增加注解@EnableEurekaClient


  • 客户端:增加负载均衡配置(默认策略为轮询),eureka默认引入了Ribbon依赖包,所以这里不需要显性引入

@Configuration
public class CommonConfig {
	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
	    return new RestTemplate();
	}
}

3、引入Hystrix(豪猪),提高系统容错性

  • 消费端引入Springcloud Hystrix依赖

<dependency>
	<groupId>org.spring-frameword.cloud</groupId>
	<artifactId>spring-cloud_starter-netflix-hystrix</artifactId>
</dependency>
  • 使用Hystrix注解@HystrixCommand实现降级逻辑 

@RestController
public class OrderController {
  @Autowired
  private RestTemplate restTemplate;

  @HystrixCommand(fallbackMethod = "findByIdFallback")
  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
	// 请求用户中心接口
    return this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
  }

  public User findByIdFallback(Long id) { 
    User user = new User();
    user.setId(-1L);
    user.setName("默认用户");
    return user;
  }
}
  • Hystrix超时、熔断配置

#超时时间(默认2000毫秒)
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000

#熔断阈值(默认20次)
hystrix.command.default.circuitBreaker.requestVolumeThreshold=20

#熔断时间(默认5000毫秒)
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000
  • Hystrix限流配置

@RestController
public class OrderController {

	@Autowired
	private RestTemplate restTemplate;

	@HystrixCommand(fallbackMethod = "findByIdFallback", // 全局唯一标识服务分组
					groupKey = "orderUserGroup", // 全局唯一标识服务名称
					threadPoolKey = "orderUserIdThreadPool", // 全局唯一标识线程池名称
					threadPoolProperties = {
	        			@HystrixProperty(name = "coreSize", value = "2"), // 线程池大小,一般只配置这一个就可以了
	        			// @HystrixProperty(name = "maxQueueSize", value = "2"), // 线程池队列最大大小
	        			// @HystrixProperty(name = "queueSizeRejectionThreshold", value = "1") // 限定当前队列大小,即实际队列大小由这个参数决定
                     })
	@GetMapping("/user/{id}")
	public User findById(@PathVariable Long id) {
		// 请求用户中心接口
		return restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
	}

	public User findByIdFallback(Long id) {
		User user = new User();
		user.setId(-1L);
		user.setName("默认用户");
		return user;
	}
}

  •  Feign整合Hystrix

/**
 * Feign的fallback测试
 * 使用@FeignClient的fallback属性指定回退类
 */
@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class/*, configuration = FeignDisableHystrixConfiguration.class*/)
public interface UserFeignClient {
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
     public User findById(@PathVariable("id") Long id);
}

/**
 * 回退类FeignClientFallback需实现Feign Client接口
 * FeignClientFallback也可以是public class,没有区别
 */
@Component
class FeignClientFallback implements UserFeignClient {
    @Override
    public User findById(Long id) {
        User user = new User();
        user.setId(-1L);
        user.setUsername("默认用户");
        return user;
    }
}
  • Histrix监控

在启动类上增加@EnableCircuitBreaker,这样就可以使用 /hystrix.stream 端点监控 Hystrix了

  • Hystrix Dashboard可视化监控数据

引入依赖,并在启动类上增加注解@EnableHystrixDashboard,通过 /hystrix 访问

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
</dependencies>

  • 使用Turbine聚合监控数据(这里需要新建一个SpringBoot项目

添加依赖,并在启动类上增加注解@EnableTurbine

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
    </dependency>
</dependencies>

编写配置文件application.properties

turbine.appConfig=microservice-order1,microservice-order2
turbine.clusterNameExpression=default

访问turbine监控地址 /turbine.stream,可以看到turbine的聚合监控数据

访问dashboard地址 /hystrix,将该turbine的监控地址输入 dashboard,查看可视化监控数据

4.zuul微服务网关

  • 添加依赖并在启动类上增加注解@EnableZuulProxy,并将自己注册到Eureka

zuul会代理所有注册到eureka server的微服务,并使用ribbon做负载均衡,zuul的路由规则如下:

http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**

zuul还自动整合了hystrix,访问地址:http://ZUUL_HOST:ZUUL_PORT/hystrix.stream

<dependencies>
    <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>
  • zuul聚合微服务,在zuul网关项目中编写controller

示例如下:

@RestController
public class AggregationController {

  @Autowired
  private RestTemplate restTemplate;
	
  @GetMapping("/aggregate/{id}")
  public Map<String, User> findById(@PathVariable Long id) throws Exception {
	  Map<String, User> dataMap = new HashMap<>();
	  User user = restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
	  User orderUser = restTemplate.getForObject("http://microservice-consumer-order/user/" + id, User.class);
	  dataMap.put("user", user);
	  dataMap.put("orderUser", orderUser);
	  return dataMap;
  }
}
  • zuul的路由配置

#指定微服务地址,既改变微服务的原地址
zuul.routes=microservice-provider-user:/user/**

#忽略指定微服务(黑名单)
zuul.ignored-services=microservice-provider-user

#忽略所有微服务,只路由指定的微服务(白名单)
zuul.ignored-services=*
zuul.routes=microservice-provider-user:/user/**

#指定特定微服务的service-id和路径,其中user-route是自定义名称
zuul.routes.user-route.service-id=microservice-provider-user
zuul.routes.user-route.path=/user/**
#指定URL,这种方式访问不会作为HystrixCommand执行,也不能使用ribbon来负载多个URL
zuul.routes.user-route.url=localhost:8080

#上面如果想要指定URL,而不破坏zuul的Hystrix和Ribbon特性,可以如下配置
#禁用掉ribbon的eureka使用
ribbon.eureka.enabled=false
microservice-provider-user.ribbon.listOfServers=localhost:8000,localhost:8001

#给zuul添加映射前缀
zuul.prefix=/api
zuul.strip-prefix=false

#给单个微服务添加映射前缀
zuul.routes.microservice-provider-user.path=/user/**
zuul.routes.microservice-provider-user.strip-prefix=false

#忽略某些路径
zuul.ignoredPatterns=/**/admin/**

#本地转发
zuul.routes.route-name.path=/path-a/**
zuul.routes.route-name.url=forward:/path-b
  • zuul过滤器

zuul过滤器的类型有:pre、 route、 post、 erro

  • zuul的容错与回退

zuul默认已经整合了hystrix,也就是zuul也是可以利用hystrix做降级容错处理的,但是 zuul监控的粒度是微服务级别,而不是某个API

5.SpringCloudConfig分布式集中配置中心

  • 新建SpringCloudConfig服务端,添加依赖、添加配置

添加依赖

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

添加配置 

spring.application.name=microservice-config-server

#配置Git仓库的地址
spring.cloud.config.server.git.uri=https://gitee.com/user/spring-cloud-config.git
#Git仓库的账号
spring.cloud.config.server.git.username=username
#Git仓库的密码
spring.cloud.config.server.git.password=123456

启动项目,访问地址:http://localhost:8080/ms-config/dev,得到整个项目的配置信息

访问地址:http://localhost:8080/ms-config-dev.properties,得到配置文件内容

  • 编写config配置中心客户端

添加依赖

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

添加配置

spring.cloud.config.uri: http://localhost:8080
#profile对应config server所获取的配置文件中的{profile}
spring.cloud.config.profile=dev
#指定Git仓库的分支,对应config server所获取的配置文件的{label}
spring.cloud.config.label=master

启动项目,访问地址:http://localhost:8081/profile,得到config配置中心的配置文件内容

  • 配置信息的加解密安全处理

安装JCE

config server的加解密功能依赖Java Cryptography Extension(JCE) Java8 JCE

下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download2133166.html

下载JCE并解压,将其中的jar包覆盖到JDK/jre/lib/security目录中

对称加密

config server提供了加密与解密的接口,分别是/encrypt与/decrypt

增加一个配置文件bootstrap.properties,配置对称加密的密钥

#设置对称密钥
encrypt.key=mykey

运行项目,验证加解密

加密:curl http://localhost:8080/encrypt -d mySecret

解密:curl http://localhost:8080/decrypt -d 767552394ee539201214199d55b0a91b1485d959b667eeabad29a101b9c1c61e

config server能自动解密配置内容。一些场景下,想要让 config server直接返回密文本身,而并非解密后的内容,可设置 

spring.cloud.config.server.encrypt.enabled=false,这时可由 ConfigCIient自行解密

  • 配置信息手动刷新

客服端添加依赖如下,其中spring-boot-starter-actuator提供了/refresh端点,用于配置的刷新

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

在Controller上添加注解@RefreshScope,添加这个注解的类会在配置更改时得到特殊的处理

@RestController
@RefreshScope
public class ConfigClientController {
    @Value("${profile}")
    private String profile;

    @GetMapping("/profile")
    public String hello() {
        return this.profile;
    }
}

发送post请求:http://localhost:8081/refresh,手动刷新配置

  • 配置信息自动刷新(需安装rabbitMQ)

服务端和客户端都添加如下依赖

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

服务端和客户端的配置文件都增加rabbitmq配置

rabbitmq.host=localhost
rabbitmq.port=5672
rabbitmq.username=guest
rabbitmq.password=guest

post方式请求地址服务端地址:http://localhost:8080/bus/refresh,如果返回成功,则config的所有客户端的配置都会动态刷新

6.Sleuth分布式链路跟踪

  • 客户端整合sleuth,添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
  • 新建Zipkin Server项目,添加依赖

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
</dependency>

启动项目,访问地址:http://localhost:9411/zipkin/

  • 客服端整合Zipkin,添加依赖,配置文件

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
spring.zipkin.base-url=http://localhost:9411
#指定需采样的请求的百分比,默认值是0.1,即10%
spring.sleuth.sampler.percentage=1.0

然后再次查看Zipkin服务:http://localhost:9411/zipkin/,能查询到微服务调用的跟踪日志

  • 用Elasticsearch存储Zipkin的数据(需安装Elasticsearch)

服务端添加依赖,配置文件里增加elasticsearch连接配置

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
    <version>2.3.1</version>
</dependency>
zipkin.storage.type=elasticsearch
zipkin.storage.elasticsearch.cluster=elasticsearch
zipkin.storage.elasticsearch.hosts=http://localhost:9200
zipkin.storage.elasticsearch.index=zipkin
zipkin.storage.elasticsearch.index-shards=5
zipkin.storage.elasticsearch.index-replicas=1

如有错误,欢迎指正,万分感谢!

猜你喜欢

转载自blog.csdn.net/hjl0722/article/details/109641805