SpringCloud
应用架构
第三阶段
:
RPC调用问题:早期就是webservice(通过网络发送SOAP协议)
RPC SOA(service orented Architecture) :面向服务的开发
存在的问题就是:服务的提供方需要响应的请求量越来越多 同时资源也可能浪费
解决的办法就是:上多台 webservice只支持P2P 没法上多台
第四阶段
:
服务降级:一旦一个服务节点 down了 让接入的用户还能用
服务熔断:对应用做一个合理的保护 如果负载过大 就让后面的请求去掉 保护已经接入的用户的使用
第五阶段
:
微服务治理(Marco Service Manager):轻量级,易部署,维护成本低。
Dubbo | SpringCloud
Dubbo (阿里) 电商 现已经成为Apache的顶级项目
Dubbo擅长的是主内(擅长Service层对外提供服务)TCP/IP-NIO网络通信(通信性能极高
)
SpringCloud擅长的是主外(擅长对Controller层对外提供服务)HTTP(应用层) (易用性更胜一筹
)
总结:伴随着互联网的发展,人们对这种微服务的开发的呼声越来越大,在互联网的萌芽了两款重量级的SOA治理框架阿里巴巴Dubbo
和SpringFrameWork提供的SpringCloud
由于Spring的广大使用群体也间接的使的Spring Cloud的市场占用率一路飙升。阿里巴巴的Dubbo
也开始发力,由于阿里巴巴的优秀的技术团队和国内较高的知名度,也对Dubbo
框架的发展起到一定的推广的作用,但是相比较于SpringCloud而言,dubbo由于易用性上和对程序员的要求都比Spring Cloud要高一些,因此目前很多互联网公司在做微服务组件开发的时候一般还是使用SpringCloud
居多。
SpringCloud Ribbon组件-负载均衡
Spring Cloud Ribbon 是一个基于Http和TCP的客服端负载均衡工具,它是基于Netflix Ribbon实现的。通过SpringCloud的自动配置使得项目可以自动的给RestTemplate添加拦截器
- 导入依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
- application.properties(第一种方式是通过配置文件)
USER-SERVICE.ribbon.listOfServers=localhost:8080,localhost:9090
USER-SERVICE.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
2.2 configuration(第二种方式通过配置类)
@Configuration
public class UserSerivceRibbonConfigure {
@Bean
public ServerList<Server> ribbonServerList(){
Server server1 = new Server("localhost", 8080);
server1.setZone("beijing");
Server server2 = new Server("localhost", 9090);
server2.setZone("shanghai");
return new StaticServerList<Server>(server1,server2);
}
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
@Bean
public ZonePreferenceServerListFilter ribbonServerListFilter(){
ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
filter.setZone("beijing");
return filter;
}
}
@SpringBootApplication
@RibbonClient(name = "USER-SERVICE",configuration = {UserSerivceRibbonConfigure.class})
public class SpringRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRibbonApplication.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- controller中的调用
String url="http://USER-SERVER/....."
restTemplate.getForObject(url,User.class);
ribbon底层会将ResTemplate进行加强,实质上是对RestTemplate添加拦截器,用于修改URL中的服务。
注意
这个存在的问题是一旦服务下线 故障节点还在。
如果listOfServers可以动态变更,达到服务节点的热部署
SpringCloud-Eureka
Spring Cloud Eureka 是 Spring Cloud Netflix 微服务套件中的一部分, 它基于 Netflix Eureka 做了二次封装, 主要负责完成微服务架构中的服务治理功能。 Spring Cloud 通过为Eureka 增加了 Spring Boot 风格的自动化配置,我们只需通过简单引入依赖和注解配置就能让 Spring Boot构建的微服务应用轻松地与 Eureka 服务治理体系进行整合。
- Eureka就相当于一个注册中心,注册中心不能只是一个一旦出问题就找不到服务了,于是启动多个Eureka就相互注册。(就像你mysql双主服务一样,不会出现单点写的故障了)
- 心跳包保证你在正常运行
- CAP原则 :
C:一致性 A:可用性 P:分区容错
- CA 一般就是单机的光杆司令
- AP 正常情况下我的Eureka节点数据是一致的,但是一旦Eureka的状态出现问题,运行其中各个服务的数据不一致,以便保证可用性。无敌高可用。
- CP 就是一致性和分区容错结合 就像一个国家的管理,一旦一个出错所有都得停 所有的nosql目前都是cp的
Euireka的HA
pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
EurekaServerApplication
package com.jiangzz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceApplication.class,args);
}
}
application-eureka-1.properties
server.port=1111
# 指定当前注册中心的服务名称
spring.application.name=eurekaregistry
## 启用注册中心主动失效,并且每次主动失效检测间隔为5s 默认值60s
eureka.server.eviction-interval-timer-in-ms= 5000
## 设置eureka注册中心的响应更新时间
eureka.server.responseCacheUpdateIntervalMs=3000
eureka.server.responseCacheAutoExpirationInSeconds=60
## 配置注册中心的主机名
eureka.instance.instance-id = eureka-1
eureka.instance.hostname = CentOSA
## 服务刷新时间配置,每隔这个时间会主动心跳一次
eureka.instance.lease-renewal-interval-in-seconds= 5
## 服务提供者被认定为丢失心跳超时,失效多久后被删除
eureka.instance.lease-expiration-duration-in-seconds=15
## 配置定时获取|抓取注册中心的数据时间
eureka.client.registry-fetch-interval-seconds= 5
eureka.client.instance-info-replication-interval-seconds= 5
## 配置集群中其他eureka实例,用于本eureka实例的注册方。
eureka.client.region=beijing
eureka.client.availability-zones.beijing=zone-2,zone-3
eureka.client.service-url.zone-2=http://CentOSB:1111/eureka/
eureka.client.service-url.zone-3=http://CentOSC:1111/eureka/
application-eureka-2.properties
server.port=1111
# 指定当前注册中心的服务名称
spring.application.name=eurekaregistry
## 启用注册中心主动失效,并且每次主动失效检测间隔为5s 默认值60s
eureka.server.eviction-interval-timer-in-ms= 5000
## 设置eureka注册中心的响应更新时间
eureka.server.responseCacheUpdateIntervalMs=3000
eureka.server.responseCacheAutoExpirationInSeconds=60
## 配置注册中心的主机名
eureka.instance.instance-id = eureka-2
eureka.instance.hostname = CentOSB
## 服务刷新时间配置,每隔这个时间会主动心跳一次
eureka.instance.lease-renewal-interval-in-seconds= 5
## 服务提供者被认定为丢失心跳超时,失效多久后被删除
eureka.instance.lease-expiration-duration-in-seconds=15
## 配置定时获取|抓取注册中心的数据时间
eureka.client.registry-fetch-interval-seconds= 5
eureka.client.instance-info-replication-interval-seconds= 5
## 配置集群中其他eureka实例,用于本eureka实例的注册方。
eureka.client.region=beijing
eureka.client.availability-zones.beijing=zone-1,zone-3
eureka.client.service-url.zone-1=http://CentOSA:1111/eureka/
eureka.client.service-url.zone-3=http://CentOSC:1111/eureka/
application-eureka-3.properties
server.port=1111
# 指定当前注册中心的服务名称
spring.application.name=eurekaregistry
## 启用注册中心主动失效,并且每次主动失效检测间隔为5s 默认值60s
eureka.server.eviction-interval-timer-in-ms= 5000
## 设置eureka注册中心的响应更新时间
eureka.server.responseCacheUpdateIntervalMs=3000
eureka.server.responseCacheAutoExpirationInSeconds=60
## 配置注册中心的主机名
eureka.instance.instance-id = eureka-3
eureka.instance.hostname = CentOSC
## 服务刷新时间配置,每隔这个时间会主动心跳一次
eureka.instance.lease-renewal-interval-in-seconds= 5
## 服务提供者被认定为丢失心跳超时,失效多久后被删除
eureka.instance.lease-expiration-duration-in-seconds=15
## 配置定时获取|抓取注册中心的数据时间
eureka.client.registry-fetch-interval-seconds= 5
eureka.client.instance-info-replication-interval-seconds= 5
## 配置集群中其他eureka实例,用于本eureka实例的注册方。
eureka.client.region=beijing
eureka.client.availability-zones.beijing=zone-1,zone-2
eureka.client.service-url.zone-1=http://CentOSA:1111/eureka/
eureka.client.service-url.zone-2=http://CentOSB:1111/eureka/
然后打包上传到集群服务器上就行了
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
[root@CentOSA ~]# java -jar eurekacloud-1.0-SNAPSHOT.jar --spring.profiles.active=eureka-1
[root@CentOSB ~]# java -jar eurekacloud-1.0-SNAPSHOT.jar --spring.profiles.active=eureka-2
[root@CentOSC ~]# java -jar eurekacloud-1.0-SNAPSHOT.jar --spring.profiles.active=eureka-3
访问CentOSA:1111
注意这里有一个面试点
Eureka是如和辨别我们的机器是出于正常状态的—Eureka的自我保护机制
由于Eureka在设计上是遵循AP的设计原则的,一旦我们的Eureka的服务节点检测到异常Renew (心跳阈值)<Renew thread接收心跳
Eureka会进行自我保护进制(就是允许你脑裂了),一旦进入自我保护机制就会失去剔除失效节点的功能
。直到检测到我自己正常的时候。
Renew threshold:的计算方式
1 如果你是集群 Renews threshold = 2 × n × 0.85
2 单机版的是:Renews threshold = 2 × (n+1) × 0.85
这个0.85指的是 eureka.server.renewal-percent-threshold=0.85
- 默认自我保护机制是开启的
如果配置的话是:eureka.server.enable-self-preservation=true
如果是单机模式很容易触发因为我们的renews.threshold=2(1+1).0.85=3
但是我们Renews(last min)=(60/eureka.instance.lease-renewal-interval-in-seconds= 30)*1=2
如果构建的单机版本的话很容易触发自我保护所以单机版建议关闭自我保护机制
服务提供方注册服务
- 发布服务
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 配置服务发布信息
spring.application.name=USER-SERVICE
#发布服务的实例id
eureka.instance.instance-id=001
eureka.instance.prefer-ip-address=true
eureka.instance.lease-expiration-duration-in-seconds=20
eureka.instance.lease-renewal-interval-in-seconds=10
eureka.client.register-with-eureka=true
eureka.client.healthcheck.enabled=true
#光注册 提供服务 不获取其他服务
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://CentOSA:1111/eureka/,http://CentOSB:1111/eureka/,http://CentOSC:1111/eureka/
服务引用方引用服务
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入Eureka后自动引入ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- application.properties
#只拿不注册
eureka.client.fetch-registry=true
eureka.client.register-with-eureka=false
#和注册方一致
eureka.client.service-url.defaultZone=http://CentOSA:1111/eureka/,http://CentOSB:1111/eureka/,http://CentOSC:1111/eureka/
- SpringBootApplication
@SpringBootApplication
public class EurekaSpringBootConsumer {
public static void main(String[] args) {
SpringApplication.run(EurekaSpringBootConsumer.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- RestTemplateTest
@SpringBootTest(classes = EurekaSpringBootConsumer.class)
@RunWith(SpringRunner.class)
public class RestTemplateTests {
@Autowired
private RestTemplate restTemplate;
@Test
public void testQueryUserById(){
//这个里面的USER-SERVICE一定要和注册方保持一致
String url="http://USER-SERVICE/manager/user/8";
User user = restTemplate.getForObject(url, User.class);
System.out.println(user);
}
}