springcloud微服务架构搭建
SpringCloud微服务框架搭建
⼀、微服务架构
1.1什么是分布式
不同模块部署在不同服务器上
作⽤:分布式解决⽹站⾼并发带来问题
1.2什么是集
多台服务器部署相同应⽤构成⼀个集
作⽤:通过负载均衡设备共同对外提供服务
1.3什么是RPC
RPC 的全称是 Remote Procedure Call 是⼀种进程间通信⽅式。
它允许程序调⽤另⼀个地址空间(通常是共享⽹络的另⼀台机器上)的过程或函数,⽽不⽤程序员显式编码这个远程调⽤的细节。即⽆论是调⽤本地接⼝/服务的还是远程的接⼝/服务,本质上编写的调⽤代码基本相同。⽐如两台服务器A,B,⼀个应⽤部署在A服务器上,想要调⽤B服务器上应⽤提供的函数或者⽅法,由于不在⼀个内存空间,不能直接调⽤,这时候需要通过就可以应⽤RPC框架的实现来解决
1.3.1restful、soap、rpc
(1)RESTful是⼀种架构设计风格,提供了设计原则和约束条件,⽽不是架构。⽽满⾜这些约束条件和原则的应⽤程序或设计就是 RESTful架构或服务。
(2)SOAP,简单对象访问协议是⼀种数据交换协议规范,
是⼀种轻量的、简单的、基于XML的协议的规范。SOAP协议和HTTP协议⼀样,都是底层的通信协议,只是请求包的格式不同⽽已,SOAP包是XML格式的。
SOAP的消息是基于xml并封装成了符合http协议,因此,它符合任何路由器、防⽕墙或代理服务器的要求。
soap可以使⽤任何语⾔来完成,只要发送正确的soap请求即可,基于soap的服务可以在任何平台⽆需
修改即可正常使⽤。
(3)RPC就是从⼀台机器(客户端)上通过参数传递的⽅式调⽤另⼀台机器(服务器)上的⼀个函数或⽅法(可以统称为服务)并得到返回的结果。
RPC 会隐藏底层的通讯细节(不需要直接处理Socket通讯或Http通讯)
RPC 是⼀个请求响应模型。客户端发起请求,服务器返回响应(类似于Http的⼯作⽅式)
RPC 在使⽤形式上像调⽤本地函数(或⽅法)⼀样去调⽤远程的函数(或⽅法)。
1.3.2rpc远程调⽤框架
⼏种⽐较典型的RPC的实现和调⽤框架。
(1)RMI实现,利⽤i包实现,基于Java远程⽅法协议(Java Remote Method Protocol)
和java的原⽣序列化。
(2)Hessian,是⼀个轻量级的remoting onhttp⼯具,使⽤简单的⽅法提供了RMI的功能。基于HTTP协议,采⽤⼆进制编解码。
(3)thrift是⼀种可伸缩的跨语⾔服务的软件框架。thrift允许你定义⼀个描述⽂件,描述数据类型和服务接⼝。依据该⽂件,编译器⽅便地⽣成RPC客户端和服务器通信代码。
(4)SpringCloud 为开发⼈员提供了快速构建分布式系统的⼀些⼯具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。
1.4什么是SOA
业务系统分解为多个组件,让每个组件都独⽴提供离散,⾃治,可复⽤的服务能⼒
通过服务的组合和编排来实现上层的业务流程
作⽤:简化维护,降低整体风险,伸缩灵活
1.5什么是微服务
架构设计概念,各服务间隔离(分布式也是隔离),⾃治(分布式依赖整体组合)其它特性(单⼀职责,边界,异步通信,独⽴部署)是分布式概念的跟严格执⾏
SOA到微服务架构的演进过程
作⽤:各服务可独⽴应⽤,组合服务也可系统应⽤(巨⽯应⽤[monolith]的简化实现策略-平台思想)
1.6使⽤RPC http技术实现会员与订单系统通讯
⼆、微服务架构
三、SpringCloud
SpringCloud 为开发⼈员提供了快速构建分布式系统的⼀些⼯具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它运⾏环境简单,可以在开发⼈员的电脑上跑。
四、服务提供者与消费关系
服务提供者:提供服务被⼈调⽤
消费者:调⽤被⼈服务
五、服务的注册与发现(Eureka )
在这⾥,我们需要⽤的的组件上Spring Cloud Netflix的Eureka ,eureka是⼀个服务注册和发现模块。
4.1 服务注册
4.1.1创建eurekaserver 项⽬
4.1.2引⼊maven依赖
以上都是概念。
image.png
以上是我的springcloud项⽬,eureka是注册中⼼,zuul是注册⽹关,ribbon和feign都是cloud的rpc远程调⽤。
zuul主要是⽤来配置⽹关
<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>
&porting.outputEncoding>UTF-8</porting.outputEncoding>
<java.version>1.8</java.version>
<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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
4.3配置l
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: ${eureka.instance.hostname}:${server.port}/eureka/
4.4启动EurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
1.isterWithEureka=true #是否将⾃⾝注册
2.eureka.client.fetchRegistry=false #如果为true,启动时报警.
4.5打开eureka server 界⾯的
image.png
4.2 服务提供者
创建⼀个服务提供者 (eureka client),当client向server注册时,它会提供⼀些元数据,例如主机和端⼝,URL,主页等。Eureka server 从每个client实例接收⼼跳消息。如果⼼跳超时,则通常将该实例从注册server中删除。
4.2.1 创建项⽬eurekaclient
4.2.2 引⼊maven依赖
<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>
分布式和微服务的关系&porting.outputEncoding>UTF-8</porting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
4.2.l配置
eureka:
client:
serviceUrl:
defaultZone: localhost:8761/eureka/
server:
port: 8762
spring:
application:
name: service-hi
4.2.4 发布服务
通过注解@EnableEurekaClient 表明⾃⼰是⼀个eurekaclient.
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHiApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceHiApplication.class, args);
}
@Value("${server.port}")
String port;
@RequestMapping("/hi")
public String home(@RequestParam String name) {
return "hi " + name + ",i am from port:" + port;
}
}
4.2.5演⽰效果
需要指明spring.application.name,这个很重要,这在以后的服务与服务之间相互调⽤⼀般都是根据这个name 。启动⼯程,打开,即eureka server 的⽹址:image.png
你会发现⼀个服务已经注册在服务中了,服务名为SERVICE-HI ,端⼝为7862
这时打开,你会在浏览器上看到 :
hi forezp,i am from port:8762
⼀、
什么是Feign
Feign是⼀个声明式的伪Http客户端,它使得写Http客户端变得更简单。使⽤Feign,只需要创建⼀个接⼝并注解。
它具有可插拔的注解特性,可使⽤Feign 注解和JAX-RS注解。Feign⽀持可插拔的编码器和解码器。
Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。
简⽽⾔之:
Feign 采⽤的是基于接⼝的注解
Feign 整合了ribbon
准备⼯作
继续⽤上⼀节的⼯程,启动eureka-server,端⼝为8761; 启动service-hi 两次,端⼝分别为8762 、8773.
准备⼯创建⼀个feign的服务
新建⼀个spring-boot⼯程,取名为serice-feign,在它的pom⽂件引⼊Feign的起步依赖spring-cloud-starter-feign、Eureka的起步依赖
spring-cloud-starter-eureka、Web的起步依赖spring-boot-starter-web,代码如下:
<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>
&porting.outputEncoding>UTF-8</porting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
在⼯程的配置⽂件l⽂件,指定程序名为service-feign,端⼝号为8765,服务注册地址为,代码如下:eureka:
client:
serviceUrl:
defaultZone: localhost:8761/eureka/
server:
port: 8765
spring:
application:
name: service-feign
定义⼀个feign接⼝
@FeignClient(value = "service-hi")
public interface SchedualServiceHi {
@RequestMapping(value = "/hi", method = RequestMethod.GET)
String sayHiFromClientOne(@RequestParam(value = "name") String name);
}
⼀个”/hi”的API接⼝
@RestController
public class HiController {
@Autowired
SchedualServiceHi schedualServiceHi;
@RequestMapping(value = "/hi",method = RequestMethod.GET)
public String sayHi(@RequestParam String name){
return schedualServiceHi.sayHiFromClientOne(name);
}
}
启动⽅式
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SericeFeign {
public static void main(String[] args) {
SpringApplication.run(SericeFeign.class, args);
}
}
演⽰效果
启动程序,多次访问localhost:8765/hi?name=forezp(localhost:8765/hi?name=forezp),浏览器交替显⽰:
hi forezp,i am from port:8762
hi forezp,i am from port:8763
Hystrix断路器
在微服务架构中,根据业务来拆分成⼀个个的服务,服务与服务之间可以相互调⽤(RPC),在Spring Cloud可以⽤RestTemplate+Ribbon和Feign来调⽤。为了保证其⾼可⽤,单个服务通常会集部署。由于⽹络原因或者⾃⾝的原因,服务并不能保证100%可⽤,如果单个服务出现问题,调⽤这个服务就会出现线程阻塞,此时若有⼤量的请求涌⼊,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。
为了解决这个问题,业界提出了断路器模型。
7.1 什么是Hystrix
Netflix开源了Hystrix组件,实现了断路器模式,SpringCloud对这⼀组件进⾏了整合。在微服务架构中,⼀个请求需要调⽤多个服务是⾮常常见的,如下图:
image.png
较底层的服务如果出现故障,会导致连锁故障。当对特定的服务的调⽤的不可⽤达到⼀个阀值(Hystric 是5秒20次)断路器将会被打开。
image.png
断路打开后,可⽤避免连锁故障,fallback⽅法可以直接返回⼀个固定值。
准备⼯作
这篇⽂章基于上⼀篇⽂章的⼯程,⾸先启动上⼀篇⽂章的⼯程,启动eureka-server ⼯程;启动service-hi⼯程,它的端⼝为8762。
在ribbon使⽤断路器
改造serice-ribbon ⼯程的代码,⾸先在l⽂件中加⼊spring-cloud-starter-hystrix的起步依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
改造service
改造HelloService类,在hiService⽅法上加上@HystrixCommand注解。该注解对该⽅法创建了熔断器的功能,并指定了fallbackMethod熔断⽅法,熔断⽅法直接返回了⼀个字符串,字符串为”hi,”+name+”,sorry,error!”,代码如下:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError")
public String hiService(String name) {
ForObject("SERVICE-HI/hi?name=" + name, String.class);
}
public String hiError(String name) {
return "hi," + name + ",sorry,error!";
}
}
在启动类上加⼊
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix  //断路器
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
演⽰效果

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。