微服务springcloud

分布式架构缺点

easymall的服务调用:

分布式框架的服务调用

系统不断根据业务逻辑进行扩充,添加任务,更新之后,系统结构变得非常复杂;

任何系统的强耦合,都会造成后期维护的困难;为了保证每一个服务的调用高可用

都会在调用端或者被调用端处理负载均衡的逻辑(nginx),负载均衡维护了一批服务的ip list,这种静态文件的配置,无论引文调用者发生变动,还是被调用者发生变动,大量的静态文件指向的数据都需要修改;

   

nginx强耦合

spring:spring,spring-data(数据层中间件),spring-session,spring-boot,spring-mvc,spring-cloud

扫描二维码关注公众号,回复: 6814910 查看本文章

   

微服务

微体现小(功能小);可以将系统中能够独立运行的各种功能拆分开来,各自围绕一个主题工程实现解耦和独立调用;

   

   

   

easymall的强耦合:

负载均衡时,通过nginx的upstream;

开发者在已经形成的微服务集群中,直接调用需要的逻辑或者数据;

springcloud介绍

spring家族的一员,可以开发实现一个轻量级的微服务集群(开发成本低),提供的组件功能非常丰富,可以实现注册,发现,熔断等等诸多功能的基于springboot的微服务框架工具;

   

   

springCloud的微服务框架具有很多的功能组件:

1 服务治理 eureka 所有工程都可以在eureak中注册自己的服务名称,如果名称一致,将会被eureka作为同一个服务来使用;

2 负载均衡调用组件:ribbon, 前端的客户端的组件

3 熔断器:Hystrix, 当服务调用出现任何异常或者问题时,可以利用熔断的逻辑完成错误的解决;类似代码中的try catch

4 接口客户端组件: feign 底层依赖ribbon+template实现的调用。看不到实际调用的方法,利用接口,注解

5 分布式配置:config,分布式配置组件;

6 网关组件:zuul,实现网关路由,监听,对当前的需要的服务进行网关治理;

   

学习SpringCloud之前,必须掌握SpringBoot的搭建和使用

   

微服务治理组件eureka

springcloud中的核心组件spring netflix的二次封装,没有它就无法形成微服务的框架;有服务治理中心,有服务注册客户端;

Eureka的角色

服务端:称为注册中心,管理所有在注册中心注册了服务名称的eureka客户端

客户端:服务的真正提供者,在注册中心注册服务,提交节点信息

   

外部访问者:调用服务,访问注册中心,获取服务提供者的list列表,并且间隔一段时间,从注册中心更新列表,调用端实现负载均衡的访问这个服务的提供集群;

   

   

搭建一个服务注册中心(03-代码(新)--Eureka-server-center)

1 springboot工程(quickstart)

2 pom依赖(标准的springboot,但是必须springboot版本1.5.9.Release,和springcloud版本兼容 Edgware Dalston)

3 application.properties

server.port=8090

eureka.instance.hostname=localhost //当前中心访问的域名

如果想要配置别的,必须通过hosts文件完成IP地址映射

eureka.client.registerWithEureka=false

eureka.client.fetchRegistry=false //当前的注册中心默认情况会在自己启动的中心注册一个自己的服务

eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka/ //匹配eureka.instance.hostname的值得中心访问地址,服务注册中心的页面可以通过这个地址访问,给其他的服务使用的,浏览器直接访问localhost:8090

3 编写启动类,查看注册中心内容

@SpringBootApplication

@EnableEurekaServer

public class StarterEurekaCenter {

public static void main(String[] args) {

SpringApplication.run(StarterEurekaCenter.class, args);}}

localhost:8090访问测试

   

eureka客户端(服务调用的服务提供者)

1 quickstart的maven骨架

2 pom依赖

3 application.properites

spring.application.name=serviceHi //在eureka中心注册一个service-hi的服务

eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka/ //指向注册中心,与eureka center一致

   

4 编写启动类(注册服务,利用注解)

@SpringBootApplication

@EnableEurekaClient

public class StarterEurekaClient {

public static void main(String[] args) {

SpringApplication.run(StarterEurekaClient.class, args);

}

}

5 编写一个测试controller

@Value("${server.port}")

private String port;

   

@RequestMapping("hi")

@ResponseBody

public String sayHello(String name){

return "hi,"+name+", i am from port "+port;

}

   

eureka报警

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

   

当提供服务的eureka client断开连接,程序关闭,宕机等问题,导致服务治理中心无法发现或连接通信服务提供者时,可连接的服务提供者占用所有服务提供者的85%(默认值)以下时,出现以上预警,并且拒绝剔除;

   

EUREKA高可用

基本原理:多个eureka服务之间相互注册,当服务提供者注册在任意一个注册中心时,服务列表信息会同步.

搭建步骤

  • 准备2个注册中心
  • 将配置文件的
  • spring.application.name=eurekaServer

    eureka.client.registerWithEureka=true

    eureka.client.fetchRegistry=true

  • 相互注册到对方的服务列表中

    在各自的配置文件中,分别指向对方的defaultZone地址

       

    服务提供者:

    续约: 注册在注册中心的服务提供者,相隔30秒发送一次心跳;给注册中心告知存活状态

    注册中心

    剔除:90秒之内没有收到注册提供者发送的心跳检测,将会把服务剔除出列表

    自我保护机制:微服务注册中心的自我保护机制,就是防止意外的大范围宕机造成的服务剔除,会影响整体集群的使用(又不是真的宕机,网络波动);同时心跳检测连接失败的15%以上,会造成自我保护机制的开启(测试环境非常容易达到);剔除的逻辑就不执行,等待恢复;

   

Ribbon组件+restTemplate

实现通过springcloud内部服务调用,从eureka注册中心获取服务list,完成负载均衡的访问(默认是轮询),从服务提供者调用工程代码/数据,就是为了解决微服务集群中某个独立的服务无法单独完成一个任务,需要别的服务帮助的情况;

   

代码

1 quickstart 的骨架

2 pom依赖

3 application.properties

4 启动类

@SpringBootApplication

@EnableEurekaClient

public class StarterRibbon {

public static void main(String[] args) {

SpringApplication.run(StarterRibbon.class, args);

}

@Bean

@LoadBalanced //启用负载均衡,做轮训访问

public RestTemplate getRes(){

return new RestTemplate();

}

}

   

5 完成负载均衡的访问

   

Controller 实现服务的调用,调用client01,client02工程的数据,需要实现条用的对象注入,RestTemplate

1 创建这个RestTemplate,指明它的负载逻辑(Balanced)

2 注入使用

@Autowired

private RestTemplate template;

//测试方法,hi

@RequestMapping("hi")

public String sayHello(String name){

//url访问的服务地址 service-hi

//name=haha http://service-hi/hi?name=haha

String response = template.getForObject("http://service-hi/hi?name="+name,

String.class);

//response,hi haha, im from 8091/8092

return response;

}

   

6 启动额外的服务提供者,直接注册service-Hi测试访问

eureka-client03直接加入集群,访问的负载均衡可以直接访问;动态添加,其他的结构任何位置都没有发生任何变动;

   

RestTemplate方法的解析

GET请求:

getForEntity;getForObject;

getForEntity(URI url,Class responseType);

getForEntity(String url,Class responseType,Object…urlVariables);

getForEntity(String url,Class responseType,Map urlVariables)

参数意义:

URI url:JAVA类中的URI对象,可以是一个普通的url地址字符串;

responseType:响应体封装的数据类型

Object…urlVariables:底层是个数组,会将所有的参数拼接成一个多个元素的数组;

和url地址中的参数位置的代替数字有关;

Map urlVariables:map对象,key就是url中的代替符号;

   

getForObject同样存在三个重载方法,参数意义和getForEntity一模一样;

前者返回的是响应体的数据,后者返回的是封装了响应所有数据的entity对象;

getForObject=getForEntity.getBody;

   

POST请求

postForEntity三个重载方法

postForObject三个重载方法;关系和getForObject与getForEntity一样的;

postForEntity(String url,Object request,Class responseType,Map urlVariables)

Object request如果是普通的数据类型,user,product,cart,order,将会作为请求体的内容

进行发送请求;请求头等信息,根据当前的技术自动封装;

HttpEntity 类型的requet就是作为一个完整的request对象,封装想要的各种内容;

   

负载均衡策略

原理:ribbon客户端在使用restTemplate对象之前,进行的发送请求的拦截;

随机策略 radomRule

在启动类中,添加IRule的对象返回,返回一个randomRule的对象;

权重策略 WeightedResponseTimeRule

每次访问实例时,记录响应时间,根据不同的实例的响应时间内部计算权重逻辑;

响应时间越长(处理能力越低) 访问次数越少

   

easymall中的微服务拆分,整合到组件中

eureka server 不用动;

搭建2个工程

第一个工程处理商品的id查询;(eureka client)

创建quickstart

pom依赖

代码拷贝

配置文件拷贝启动类添加注解EnableEurekaCLient

删除除了商品id查询以外的所有内容

第二个工程处理购物车的新增;(用户访问的系统);无法单独完成用户的新增购物车需求

缺少了三个属性price,name,img(eureka client,ribbon组件)

   

Hystrix

熔断器,容错管理工具,当服务集群中出现访问服务的异常,或者错误,或者http请求的断开,可以利用熔断的机制完成各种方法的封装,调用方法,实现错误的管理逻辑;

可以使用熔断器解决

熔断/断熔:

觉不允许集群中局部的问题导致整体的瘫痪;一旦局部出现问题,微服务集群将会

抛弃/牺牲这个部分;

   

服务降级:

在局部出现问题后,采用熔断的处理逻辑,必定导致服务的依赖/使用降级;

采用第二种/次种处理响应的措施;

   

搭建一个ribbon+hystrix的工程

1 quickstart

2 pom

3 application

4 启动类

5测试代码

Controller

@RestController

public class HelloController {

@Autowired

private HelloService helloService;

@RequestMapping("hi")

public String sayHello(String name){

String hello=helloService.sayHello(name);

return "RIBBON:"+hello;

}

}

Service

@Service

public class HelloService {

@Autowired

private RestTemplate template;

//当前方法调用时,跑出的问题,或者异常,可以利用熔断的注解

//实现错误的调用,错误的方法执行错误出现后的逻辑

//fallbackMethod,在当前方法出现问题后,当前类会调用erroHi同名方法

//传递给sayHello的所有参数,会一并交给errorHi处理

@HystrixCommand(fallbackMethod="errorHi")

public String sayHello(String name) {

ResponseEntity<String> entity = template.getForEntity("http://service-hi/hi?name="+name,

String.class);

String response=entity.getBody();

//response,hi haha, im from 8091/8092

   

return response;

}

   

public String errorHi(String name){

//写消息到rabbitmq

//返回当前的错误报信

return "hi,"+name+",sorry error happened";

}}

   

断路逻辑:处理支持访问失败的降级逻辑,支持超时的降级逻辑(由于网络波动,出现短时间的响应超时),1秒/2秒,超时也进行服务降级处理;

client里的代码中,随机生成毫秒数 Random.nectInt(5000);

   

Feign

负载均衡调用服务的客户端组件,声明式(注解)客户端。使得调用更简单(无需关心底层调用的api getForEntity getForObject post..);底层基于ribbon+restTemplate(内部整合了容错的断容器Hystrix)

搭建

1 quickstart

2 pom

3 properties

4 启动类

@SpringBootApplication

@EnableEurekaClient

@EnableFeignClients

public class StarterFeign {

public static void main(String[] args) {

SpringApplication.run(StarterFeign.class, args);

}

}

   

Controller

@RestController

public class HelloController {

@Autowired

private HelloService helloService;

//测试案例

@RequestMapping("hi")

public String sayHello(String name){

String hello=helloService.sayHello(name);

return "FEIGN:"+hello;

}

}

   

Service

@FeignClient("service-hi")

public interface HelloService {

   

@RequestMapping(value="hi",method=RequestMethod.GET)

String sayHello(@RequestParam(value="name") String name);

}

   

   

   

SRPING CLOUD CONFIG

分布式配置中心

在大量的集群中,各种工程都需要属性的配置properties文件

一旦出现属性的共享,例如redis配置,es配置,数据库配置;各自工程维护起来比较麻烦,而且更新不及时;

微服务框架提供一个共享的分布式配置中心,所有的服务注册者都可以是分布式配置中心的客户端,通过中心管理的github上的配置文件,实现共享配置;

github: 开源的资源,代码,框架,技术分享的网站

和git有个相同的特点,就是资源可以实现回滚和版本控制;

每个不同的用户可以拥有免费的和付费的github资源,使用线下的git向github传递数据;

   

git:软件版本管理器,资源管理器

   

config组件的结构

一个中心,多个客户端;

   

1 配置中心工程(读取共享的配置文件)

  • quickstart
  • pom
  • applicatin.properties

    spring.cloud.config.server.git.uri=https://github.com/xiaoxuwei1986/jtcloud //开元的repository的链接地址,可以直接通过浏览器访问共享资源

    spring.cloud.config.server.git.searchPaths=/haha

    //共享的repository中可以由多级的路径文件存在

    spring.cloud.config.label=master

  • 启动类
  • 测试访问

    文件名称info-test.properties

    info--application

    test--profile

       

    localhost:8000/{application}/{profile}

       

    配置中心就会到github访问application-profile.properties

    2 配置的客户端工程(读取中心工程的共享资源)

    配置文件

    bootstrap.properties

    spring.application.name=info //读取配置中心文件文件的前缀application

    spring.cloud.config.profile=test //读取前缀profile application-profile.properties

    spring.cloud.config.label=master

    spring.cloud.config.uri=http://localhost:8098

    //配置中心的来源

    server.port=8099

       

    测试controller

    @Controller

    public class TestController {

    @Value("${spring.redis.nodes}")

    private String name;

       

    @RequestMapping("test")

    @ResponseBody

    public String getName(){

    return name;

    }}

       

将京淘的某个功能的系统的配置文件从config中读取

   

ZUUL

微服务集群提供的网关,监听等功能的微服务组件;

访问的时候根据url路径,过滤网关拦截的信息,访问指向的服务

   

   

1 quickstart

2 pom

3 properties

server.port=8097

spring.application.name=service-zuul

zuul.routes.user.path=/user/**

zuul.routes.user.serviceId=SERVICE-RIBBON-HYSTRIX

//访问并不是直接访问ribbon客户端,feign客户端,而是利用url中域名+端口访问zuul工程,routes.*** 其中*代表的字符串,必须和路由网关的匹配字符串一致,api-a,如果key中的routes.order必须对应匹配的是/order/**

routes.api-a.serviceId指向过滤了网关路由key的地址,访问的服务

localhost:8097/api-a/hi?name=haha 访问的是zuul

service-ribbon

localhost:8097/api-b/hi?name=haha

指向服务SERVICE-FEIGN

http://service-feign/hi?name=haha

zuul.routes.api-b.path=/api-b/**

zuul.routes.api-b.serviceId=SERVICE-FEIGN

4 启动类

@SpringBootApplication

@EnableEurekaClient

@EnableZuulProxy

public class StarterZuul {

public static void main(String[] args) {

SpringApplication.run(StarterZuul.class, args);

}

}

   

5 测试网关转发路由

localhost:8097/api-a/hi

返回结果:

RIBBON:hi null, I am from 8091-8093/error

localhost:8097/api-b/hi

FEIGN: hi null, I am from 8091-8093/白错误页面

//zuul当前测试案例中无法实现后端服务的hystrix的调用。

8091宕机后,通过网关zuul,只能进入错误页面

   

   

ZUUL网管接口文件

请求地址

http://localhost:9000/api-d/cart/save

请求方式

post

请求参数

Cart 对象 String userId,String productId,Integer num

返回数据

成功和失败200,sysResult

   

   

作业:

easymall其他功能按照逻辑,整理添加springcloud组件实现微服务集群的完整easymall工程;

   

   

   

   

   

   

   

   

猜你喜欢

转载自www.cnblogs.com/shuzhiwei/p/11204786.html