springcloud的一些自己想法

 了解一个框架你要这样想问题:如果是你要做一个springcloud一个微服务的框架,首先你得明白这个框架解决了什么问题,有什么样的市场是单体架构、分布式架构处理不了,或者处理不好的?

       首先我们要想想单体架构中所带来的问题,所有的代码集中在同一个项目中。虽然便于管理,但是当项目足够庞大时,所有的业务模块都集中在一个JVM进程中,会面临很多问题: 1、项目过于臃肿,难以维护 2、资源无法隔离,某个资源出现问题,整个系统崩溃 3、拓展性差,通常只能水平拓展,缺乏灵活性。4.处理高并发的项目基本就会崩掉,坑不住大量请求的压力

        那我们就需要一个可以根据业务模块划分服务、每个服务可以独立部署并且互相隔离、通过轻量的 API 调用服务、服务需要保证良好的高可用、高性能、高并发的框架

1.如何保证高并发

        我们可以把每个单独的模块形成一个服务,而且还有一个好处哪怕某个服务崩了也不会影响其他的业务服务。就像直播系统崩了,聊天模块还能聊天的道理一样。就算请求量太大一个服务还是集群形成多台服务器可以实现在大量请求的情况下抗住请求压力。但是这样去实现的话会出现调用问题,服务和服务之间的调用本质上用的还是是http请求调用的,既然是通过http请求调用就要知道被调用者的ip地址,而且每个服务又可能都是集群,IP地址的管理就太繁琐了?

        这个时候我们可以用到一个服务注册中心(eureka),当前每个微服务都会去注册中心服务注册把 ip地址给他管理,这样服务之间的调用就可以去服务注册中心拿到IP地址,如果被调用者是一个集群,那么调用者就会拿到集群数量的ip地址。

 eureka的实现:

       既然是所有的服务都要把地址交给eureka管理那么父工程。因为是springboot工程,和springcloud继承<artifactId>spring-boot-starter-parent</artifactId>依赖<artifactId>spring-cloud-dependencies</artifactId>,和在启动类上加上@SpringBootApplication启动类,@EnableEurekaServer服务注册中心。在配置文件上,配置注册中心的端口,配置微服务的名字,配置注册中心的地址,配置当前微服务是否可以去调用其他微服务

微服务的实现:

当然两个框架的依赖跑不了<artifactId>spring-boot-starter-web</artifactId>,在eureka看来微服务是属于客户端 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>,

配置文件也需要加载 <artifactId>spring-cloud-starter-config</artifactId>,需要谁的东西就依赖谁,启动类上也需要@SpringBootApplication(scanBasePackages = "com.qf"),@EnableEurekaClient

在配置文件上需要配置端口号,配置服务名,配置服务地址。

 

疑问:那客户端该怎么发送请求呢?给谁呢?客户端技术可以把请求发给服务注册中心嘛?

显然客户端是无法把请求的地址发送给eureka的,那我们就可以考虑有什么技术,可以帮我们把这个请求地址发送给eureka,这个就可以用到一个gateway客户端的负载均衡技术去实现

        当浏览器调用的服务是一个集群改怎么办,如果把localhost:8080换成微服务的名字,这可行嘛?很明显这是不行的,你要写一个微服务名字的前提,是你的浏览器是能够

注册访问注册中心的才能读到微服务的地址,浏览器是不太可能读到eureak的。那url地址只能写死地址该怎么办?路由网关会作为微服务架构体系的入口组件,所有的外部请

求,都必须经过路由网关分发(内部互相访问没有影响),这样可以屏蔽微服务体系结构复杂性,并且可以提供请求路由、负载访问、请求过滤整形等功能。

既然这个gateway先拦截了请求那他还可以做一些什么业务呢?

1.动态路由

2.过滤器链

3.局部过滤器链

4.全局过滤器链 

 

基于过滤器的请求限流

 

限流的实现方案

 

请求计数限流

漏桶算法限流

令牌桶算法限流

 

实现gateway:

       因为这是一个springboot工程所以他得依赖Eureka-Client、Gateway; 既然gateway是负责把客户端的请求地址发送给eureka的,那么gateway就要要注册到注册中心中那么就使用启动类注解@EnableEurekaClient,既然是服务他还得配置微服务的地址,需要注册中心的服务地址,或者其他需要用到的地址,在不配置getaway的路由功能,是会暴露我们的微服务名称和接口的安全性不太好,有些时候我们也有需求不想暴露我们的api,所以就有配置路由转发,或者对路由进行过滤。

 

疑问:那服务之间该怎么调用呢?服务的地址都发给了注册中心,两个服务该怎么调用呢?

          那就可以用Feign服务之间的同步调用,因为注册地址都是在注册中心中这就说明feign也要注册到注册中心中。

 什么是客户端负载均衡和服务器端负载均衡:(gateway是服务器端的负载均衡,feign是客户端负载均衡)

服务器端负载均衡 :现在我的客户端要去请某一个服务器,要去准备一个负载均衡服务器-Nginx,然后客户端只要维护好Nginx的ip地址就好了,就会发发送请求到Nginx,然后Nginx把请求分发给服务器,这种叫服务器端负载均衡,相对于客户端只知道Nginx的IP地址甚至都不知道服务器有多少台机器。


   客户端负载均衡: 没有Nginx负载均衡服务器,服务器的ip地址直接写死在客户端,然后利用ribbon或feign为客户端负载均衡,因为本身是由客户端调用那台机器的好处就是少部署一台Nginx了,就少了负载均衡的压了,但是他本身的问题是如果我的服务器的加一台机器客户端就要改一次代码,所以往往都会伴随着注册中心使用,机器都注册到注册中心上,然后客户端去请求注册中心的地址

feign之间的调用实现:

         因为feign是微服务之间的同步调用,要调用其他微服务就得知道他们的注册名,就得通过注解,那就说明要依赖<artifactId>spring-cloud-starter-openfeign</artifactId>

因为他也是一个微服务所以他也要让注册中心发现,并扫描到该服务,@EnableFeignClients(basePackages = "com.qf.feign"),两个服务之间的调用还得需要配置,所以还得@Configuration

随项目启动就加载

2.问题如何提高拓展性保证良好的高可用?

疑问:有一个致命的问题万一eureka挂了怎么办,这可是整个项目都会挂了的?

          这个·时候我们Eureka集群,eureka集群最大的好处就是最多可以挂掉n-1台机器,仍然可以对外提供服务,实现eureka的高可用。
微服务注册请求的分流,就是微服务会随机注册eureka服务。

疑问:那eureka集群了那服务的地址给了eureka注册中心,那么他怎么知道是哪台呢?万一有一台挂了,服务是不是还是一发送请求,还是有什么用的机制可以知道他挂了,我要找别的eureka了?
       

           eureka集群间的机器会自动同步数据,如果微服务a要调微服务d是怎么样的过程,首先eureka服务发送http请求要调微服务d的地址,微服务d接收请求再返回结果,但是微服务d注册的eureka服务和微服务a注册的eureka服务不是同一个eureka。但是呢?eureka集群间的机器会自动同步数据。这样就能调到微服务的d了。那eureka服务挂了微服务a,是不是就意味着不能用了,但是他们会重新连接可用的eureka服务上,但是他们是怎么知道原先的eureka挂了,因为有一个心跳机制。他会默认发一个心跳包eureka服务默认是半分钟,eureka服务收到之后会回一个心跳包,如果是第一次eureka服务接收不到心跳包,会认为是网络问题导致丢包如果长时间收不到就会认为微服务a挂掉了,那他们彼此就知道双方都活着的。如果确认了eureka服务挂掉了,微服务a就会重启重连的机制重连一台eureka的服务。这些操作都是自动的不用我们去操作。但是这样也有一个问题,没办法立刻感知到对方挂了。因此心跳机制下的当前互联网模式下是没办法立马感知到的。这就像一拔网线,QQ不会立马断网,会过一段时间才会显示断网的标志。在实际开发中写一次代码打成war包部署到服务器上。伪集群在一机器上开启多个进程形成集群。

断路器 - Hystrix:

        所谓的微服务其实就是跑在微服务里面的,不管是其他微服务调用这个微服务还是浏览器调用这个微服务其实都是在请求tomcat,然后都会有controller去接收请求(本质是servlet),假如有三个浏览器都在访问这个tomcat,都在请求controller里面的同一个方法,这三个浏览器是同一个对象还是三个对象?spring默认是单列的也就是说在不做任何处理下都只有一个controller,不管你有多少个客户端,当前controller只有一个对象,但是这个方法是一个线程在调用还是三个线程再调用这个方法?首先必然在线程里执行,其实是当前一个客户端发送请求给tomcat,tomcat会从线程池里面拿一个空余线程去处理你这个请求,处理完了在放回去线程池,下次在拿出来用,因为线程是比较重要的资源也是比较稀缺的资源因此如果无限制的开启线程是对服务器的性能是开销比较大的,因为他要上下文切换,还有内存的开销等。所以这里是多线程的。假设有一个浏览器去调用一个服务a,那么要调用服务a里面的controller的方法也就意味着会占用tomcat里的一个线程池,会从线程池里面拿一个线程处理这个请求然后这个请求会去调用controller里面的方法,我在controller里面在做一件事,他在去访问服务b,这个服务处问题了,在服务b返回结果这段时间之内这个线程会被阻塞,那这里会等多久取决与你的读超时,读超时时间默认是1秒,这个服务b出问题了就一定会出现读超时,在这1秒的时间万一有大量的客户端个服务a发请求,那他们都会去拿线程在调用方法,方法又会在访问服务b,然后又因为服务b出问题了就又出现了读超时了,那么这个线程池一旦被拿空又没有回收,那么这个微服务a奔溃有会祸害其他调用服务a的服务所以这个时候就要Hystrix断路器 机制。(就是电路保险的意思)

3.问题那该怎么把项目轻量化呢保证性能?

 

 

posted @ 2020-08-02 11:18  ascas  阅读(169)  评论(0)    收藏  举报