本文为我在工作中对spring cloud应用的理解,现在此归纳总结,如有缺陷请指出,在此感谢。
注:再开始spring cloud之前,必须要有spring boot的基础,因为spring cloud是建立在spring boot这套框架之上的技术糅合,学习spring boot其实主要去了解spring boot中的xxx-xxx-starter(拆箱即用,自动装配),actuator(端点)等相关知识。好了,闲话不多说了,开始正题。
什么是微服务?
架构设计概念,各服务间隔离(分布式也是隔离),自治(分布式依赖整体组合)其它特性(单一职责,边界,异步通信,独立部署)是分布式概念的更严格执行。
SOA到微服务架构的演进过程
SOA架构主要针对企业级、采用ESB服务(ESB企业服务总线),非常重,需要序列化和反序列化,采用XML格式传输。
微服务架构主要互联网公司,轻量级、小巧,独立运行,基于Http+Rest+JSON格式传输。
SpringCloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、负载均衡、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它运行环境简单,可以在开发人员的电脑上跑。另外说明spring cloud是基于Springboot的,所以需要开发中对Springboot有一定的了解
首先说明下,spring cloud分为两大家族:一、spring cloud netflix;二、spring cloud alibaba
接下来我先从netflix家族说起
1. 服务提供者与服务消费者
服务提供者:提供服务被人调用
消费者:调用被人服务
2. 服务的注册与发现
在这里,我们需要用的的组件上Spring Cloud Netflix的Eureka ,eureka是一个服务注册和发现模块。我先上个图吧!
什么是Eureka
官方的介绍在这里Eureka wiki。Eureka是Netflix开源的一个RESTful服务,主要用于服务的注册发现。Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。 Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状 态的加权负载均衡。
在我看来,Eureka的吸引力来源于以下几点:
开源:大家可以对实现一探究竟,甚至修改源码。
可靠:经过Netflix多年的生产环境考验,使用应该比较靠谱省心
功能齐全:不但提供了完整的注册发现服务,还有Ribbon等可以配合使用的服务。
基于Java:对于Java程序员来说,使用起来,心里比较有底。
spring cloud可以使用Spring Cloud, 与Eureka进行了很好的集成,使用起来非常方便。
3.实现服务注册
在服务注册之前首先需要先将注册中心搭建好
创建EureKaserver 项目添加坐标依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--eureka server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- spring boot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
配置application.yml
server:
port: 8888
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false //单注册中心,防止自我注册
fetchRegistry: false //无需从注册中心拉取
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
启动EurekaServer
1 @SpringBootApplication 2 @EnableEurekaServer 3 public class App { 4 public static void main(String[] args) { 5 SpringApplication.run(App.class, args); 6 } 7 }
打开eureka server 界面访问eureka
创建服务提供者添加依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> //eureka客户端依赖 <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> //web访问依赖 <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.RC1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
application.yml配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
server:
port: 8762
spring:
application:
name: service-member
服务接口
1 @RestController 2 public class MemberController { 3 4 @RequestMapping("/getUserList") 5 public List<String> getUserList() { 6 List<String> listUser = new ArrayList<String>(); 7 listUser.add("zhangsan"); 8 listUser.add("lisi"); 9 listUser.add("yushengjun"); 10 return listUser; 11 } 12 13 }
发布服务
1 @SpringBootApplication 2 @EnableEurekaClient //表明自己是一个eureka客户端 3 public class AppMember { 4 5 public static void main(String[] args) { 6 SpringApplication.run(AppMember.class, args); 7 } 8 9 }
注意:这里我打算将服务消费者中用到ribbon客户端负载均衡,因此先来了解下ribbon
ribbon
ribbon是一个负载均衡客户端 类似nginx反向代理,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon。feign后面马上介绍
服务消费者及添加依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> //eureka客户端依赖 <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> //ribbon客户端负载均衡器 <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> //web访问依赖 <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.RC1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
application.yml配置
server:
port: 8764
spring:
application:
name: service-order
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
编写service,调用服务提供者
@RestController public class MemberService { @Autowired RestTemplate restTemplate;
@RequestMapping("/getUserList") public List<String> getOrderByUserList() { return restTemplate.getForObject("http://service-member/getUserList", List.class); //调用注册中心中注册的服务提供者 } }
发布服务并开始访问调用
1 @EnableEurekaClient 2 @SpringBootApplication 3 public class AppOrder { 4 5 public static void main(String[] args) { 6 SpringApplication.run(AppOrder.class, args); 7 } 8 9 @Bean 10 @LoadBalanced //开启restTemplate的负载均衡功能 11 RestTemplate restTemplate() { 12 return new RestTemplate(); 13 } 14 15 }
服务消费者之Feign使用
首先说明下,在spring cloud微服务中进行http远程调用有两种方式:
第一种:就是上面刚刚讲到的 RestTemplate;(这种方式使用比较简单,这里不再赘述)第二种:Feign(声明式http客户端)
什么是Feign?
Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编 码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。
简言之:
1. Feign采用的是基于接口注解方式;
2. Feign中已经为我们整合了ribbon
创建使用Feign的服务消费者
添加坐标依赖,这里考虑到篇幅问题,就不大段粘贴了
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
application.yml文件配置:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
server:
port: 8765
spring:
application:
name: service-order-feign
编写service调用服务提供者:
@FeignClient("service-member") //Feign的http调用接口定义,这里表示要调用注册在注册中心的service-member服务 public interface MemberFeign { @RequestMapping("/getUserList") //调用service-member服务的 /getUserList接口 public List<String> getOrderByUserList(); }
发布服务:
@SpringBootApplication @EnableEurekaClient @EnableFeignClients //表示启用Feign client public class OrderFeignApp { public static void main(String[] args) { SpringApplication.run(OrderFeignApp.class, args); } }