Spring Cloud 学习,整理

来源:互联网 发布:小米手柄映射软件 编辑:程序博客网 时间:2024/05/16 08:53

菜鸟刚接触Spring Cloud,摸着石头过河。


Eureka:

服务注册和发现中心。

介绍和各种配置可以看:https://www.oschina.net/search?scope=blog&q=Eureka&p=1
Eureka集群:http://www.cnblogs.com/fangfuhai/p/6102486.html

这是各种工具的通用配置:
<parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>1.5.4.RELEASE</version>    <relativePath/> <!-- lookup parent from repository --></parent><dependencyManagement>    <dependencies>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-dependencies</artifactId>            <version>Dalston.SR1</version>            <type>pom</type>            <scope>import</scope>        </dependency>    </dependencies></dependencyManagement><dependencies>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-config</artifactId>    </dependency></dependencies>
添加Eureka依赖:
<dependencies>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-eureka-server</artifactId>    </dependency>    //访问Eureka需要用户名,密码    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-security</artifactId>    </dependency></dependencies>

配置属性
server:  port: 8991eureka:  client:    service-url:      defaultZone: http://localhost:8991/eureka    #不当成eureka client,本身eureka server就有client    register-with-eureka: false    fetch-registry: falsesecurity:  basic:    enabled: true  user:    name: user    password: 123456
Eureka本身也是一个客户端,所以需要剔除
#不当成eureka client,本身eureka server就有client    register-with-eureka: false    fetch-registry: false
开启Eureka服务:
@SpringBootApplication@EnableEurekaServerpublic class Discovery {    public static void main(String[] args){        SpringApplication.run(Discovery.class,args);    }}


将服务注册到Eureka中:
添加依赖:
<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-eureka</artifactId></dependency>
//这个用于健康检查<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-actuator</artifactId></dependency>

添加属性:
server:  port: 7904eureka:  client:    healthcheck:          enabled: true    service-url:      defaultZone: http://user:123456@localhost:8991/eureka  instance:    prefer-ip-address: true #IP来做Status    #status-page-url-path: ${management.context-path}/info    #health-check-url-path: ${management.context-path}/health

@SpringBootApplication@EnableEurekaClientpublic class UserService {    public static void main(String[] args){        SpringApplication.run(UserService.class,args);    }}
这样就将服务注册到Eureka中
Eureka实现高可用

spring:  profiles: peer1eureka:  instance:    hostname: peer1  client:    serviceUrl:      defaultZone: http://peer2/eureka/---spring:  profiles: peer2eureka:  instance:    hostname: peer2  client:    serviceUrl:      defaultZone: http://peer1/eureka/
修改本地hosts文件,将127.0.0.1映射到peer1,peer2,

其实这个就是将Eureka服务相互注册,A注册到B中,B注册到A中,第一个启动Eureka会报错,因为会找不到注册中心,但是不用管他


Eureka各个属性详解:https://my.oschina.net/u/2529405/blog/736239


Ribbon:

客户端负载均衡器
具体可以看:https://www.oschina.net/search?scope=blog&q=Ribbon

由于Eureka依赖中已经有Ribbon的jar了,所以不需要添加其他依赖

Ribbon开启负载均衡:
@Bean@LoadBalancedpublic RestTemplate restTemplate(){    return new RestTemplate();}

@Controllerpublic class MovieController {    @Autowired    private RestTemplate restTemplate;    @Autowired    private LoadBalancerClient loadBalancerClient;    
    //通过Ribbon访问UserService的接口    @GetMapping("movie/{id}")    public User findUserById(@PathVariable Integer id){        return this.restTemplate.getForObject("http://userviceservice/getUser/"+id,User.class);    }
    //这个是Robbin的客户端,直接使用    @GetMapping("load/{id}")    @ResponseBody    public String Load(@PathVariable Integer id){        ServiceInstance userviceservice = loadBalancerClient.choose("userviceservice");        System.out.println(userviceservice.getServiceId()+"-----"+userviceservice.getHost()+"---------------"+userviceservice.getPort());    //    ServiceInstance userviceservice2 = loadBalancerClient.choose("userviceservice2");     //   System.out.println(userviceservice2.getServiceId()+"-----"+userviceservice2.getHost()+"---------------"+userviceservice2.getPort());        return "1";    }}
@RibbonClient(name = "foo", configuration = FooConfiguration.class)
使用注解来开启RibbonClient:name 对方服务,configuration:指定配置,里面可以自定义这些Bean
  • IClientConfig ribbonClientConfig:DefaultClientConfigImpl

  • IRule ribbonRule:ZoneAvoidanceRule

  • IPing ribbonPing:NoOpPing

  • ServerList<Server> ribbonServerList:ConfigurationBasedServerList

  • ServerListFilter<Server> ribbonServerListFilter:ZonePreferenceServerListFilter

  • ILoadBalancer ribbonLoadBalancer:ZoneAwareLoadBalancer

  • ServerListUpdater ribbonServerListUpdater:PollingServerListUpdater

也可以使用application.yml的属性配置Ribbon。
users:  ribbon:    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
users指服务名称。

只使用Ribbon,不使用Eureka:
ribbon:  eureka:   enabled: false
stores:  ribbon:    listOfServers: example.com,google.com

stores是只服务名,listOfServers:指定的服务路径,由于没有开启Eureka,所以需要添加这个

Ribbon使用缓存
ribbon:  eager-load:    enabled: true    clients: client1, client2, client3

Feign:

  声明式Rest客户端。】

具体问题可看:https://www.oschina.net/search?scope=blog&q=Feign
Spring Cloud集成Ribbon和Eureka以在使用Feign时提供负载均衡的http客户端

添加Feign依赖

<dependencies>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-feign</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-eureka</artifactId>    </dependency></dependencies>
开启Feign
@SpringBootApplication@EnableFeignClients@EnableEurekaClientpublic class Feign {    public static void main(String[] args){        SpringApplication.run(Feign.class,args);    }}

@FeignClient(name = "userservice",configuration = FeignConfig.class)public interface UserFeignClient {    @RequestMapping(value = "/getuser/{id}", method = RequestMethod.GET)    public User getUser(@PathVariable("id") Integer id);}
Feign的配置 name是服务名,configuration指定Feign配置 。Feign的默认配置是

Spring Cloud Netflix默认为feign(BeanType beanName:ClassName)提供以下bean:

  • Decoder feignDecoder:ResponseEntityDecoder(其中包含SpringDecoder

  • Encoder feignEncoder:SpringEncoder

  • Logger feignLogger:Slf4jLogger

  • Contract feignContract:SpringMvcContract //通过MVC的方式去调用其他服务的接口

  • Feign.Builder feignBuilder:HystrixFeign.Builder

  • Client feignClient:如果Ribbon启用,则为LoadBalancerFeignClient,否则将使用默认的feign客户端。

configuration:可以配置这些默认值。改用其他的配置

可以通过将feign.okhttp.enabledfeign.httpclient.enabled设置为true,并将它们放在类路径上来使用OkHttpClient和ApacheHttpClient feign客户端。 // 设置用什么HttpClient访问

注意:如果你配置了configuration,你不能将这个类放在Application的包以及他的子包下,不然会产生干扰。

@FeignClient(name = "${feign.name}", url = "${feign.url}")
Feign也可以这么配置,如果使用 URL属性,则一定需要配上name属性

feign.hystrix.enabled=true,//Feign开启断路器

@Configurationpublic class FooConfiguration {    @Bean@Scope("prototype")public Feign.Builder feignBuilder() {return Feign.builder();}} //禁用断路器,,即修改Feign的默认配置,
@FeignClient(name = "hello", fallback = HystrixClientFallback.class)protected interface HystrixClient {    @RequestMapping(method = RequestMethod.GET, value = "/hello")    Hello iFailSometimes();}static class HystrixClientFallback implements HystrixClient {    @Override    public Hello iFailSometimes() {        return new Hello("fallback");    }} // Feign中使用断路器,使用fallback属性。
@FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class)protected interface HystrixClient {@RequestMapping(method = RequestMethod.GET, value = "/hello")Hello iFailSometimes();}@Componentstatic class HystrixClientFallbackFactory implements FallbackFactory<HystrixClient> {@Overridepublic HystrixClient create(Throwable cause) {return new HystrixClientWithFallBackFactory() {@Overridepublic Hello iFailSometimes() {return new Hello("fallback; reason was: " + cause.getMessage());}};}} //使用断路器,使用fallbackFactory属性,可以在Throwable cause中的到回退原因

Primary属性,应该和Spring里面的Primary属性差不多,用于同一个接口的不同实现类

feign.compression.request.enabled=truefeign.compression.request.mime-types=text/xml,application/xml,application/jsonfeign.compression.request.min-request-size=2048
feign.compression.response.enabled=true   // Feign请求压缩

Zuul:

简介:http://lxlong.iteye.com/blog/2267985, https://www.oschina.net/search?scope=blog&q=Zuul
路由器

添加依赖:
<dependencies>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-zuul</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-eureka</artifactId>    </dependency></dependencies>
@SpringBootApplication@EnableZuulProxypublic class ZuulApplication {    public static void main(String[] args){        SpringApplication.run(ZuulApplication.class,args);    }}  //开启zuul

Zuul的application.yml配置
server:  port: 7777  #context-path: /demo 这个配置是等于tomcat中的项目路径,http://localhost:8080/demoeureka:  client:    service-url:      defaultZone: http://user:123456@localhost:8991/eureka  instance:    prefer-ip-address: true    #IP来做Status    #status-page-url-path: ${management.context-path}/info    #health-check-url-path: ${management.context-path}/health    #instance-id:    #home-page-url-path: /demo 如果配了context-path,这样配置可以让eureka直接访问/hystrix.stream,而不用/demo/hystrix.streamspring:  application:    name: microservice-getaway-zuulzuul:  #prefix: /getuser  #strip-prefix: false  这个可以用在zuul代理的服务有content-path,这样就可以不用在写content-path了,全局配置logging:  level:    com.netflix: debug  #ignoredServices: '*'  #routes:    #abc:   #更细粒度,这里可以随便写,只要唯一      #path: /user/**      #serviceId: user-service-hystrix    #userservice: /myusers/** userservice映射为myusers,可以通过/myusers访问    #zuul:      #routes:        #users:          #path: /myusers/**        #legacy:          #path: /**  users/myusers/**这么访问,其他的用/**访问        #sensitiveHeaders 不让http请求的带有的Cookie,Set-Cookie,Authorization等属性传到后端
Zuul不能发现客户端,所以需要Eureka来提供。Zuul还是有点不懂,还需要看。

通过Zuul来上传大文件需要在URL之前加上/Zuul,接着:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000ribbon:  ConnectTimeout: 3000  ReadTimeout: 60000   //配置超时时间
Zuul支持Hystrix的回退(即通过Zuul访问服务,如果服务挂了,可以做后续处理)
@Componentpublic class MyFallbackProvider implements ZuulFallbackProvider {    @Override    public String getRoute() {        return "userservice";  //远程的服务,如果需要所有远程服务都支持回退,则这边应 return “*” 或者return null    }    @Override    public ClientHttpResponse fallbackResponse() {        return new ClientHttpResponse() {            @Override            public HttpStatus getStatusCode() throws IOException {                return HttpStatus.OK; //状态码            }            @Override            public int getRawStatusCode() throws IOException {                return 200; //状态码            }            @Override            public String getStatusText() throws IOException {                return "OK";  //状态            }            @Override            public void close() {            }            @Override            public InputStream getBody() throws IOException {                return new ByteArrayInputStream("fallback".getBytes());            }  //返回的内容            @Override            public HttpHeaders getHeaders() {                HttpHeaders headers = new HttpHeaders();                headers.setContentType(MediaType.APPLICATION_JSON);                return headers;            }        };    }}
Zuul过滤器:

@EnableZuulProxy@EnableZuulServer

Spring Cloud Netflix根据使用何种注释来启用Zuul安装多个过滤器。@EnableZuulProxy@EnableZuulServer的超集。换句话说,@EnableZuulProxy包含@EnableZuulServer安装的所有过滤器。“代理”中的其他过滤器启用路由功能。如果你想要一个“空白”Zuul,你应该使用@EnableZuulServer

@EnableZuulServer过滤器

创建从Spring Boot配置文件加载路由定义的SimpleRouteLocator

安装了以下过滤器(正常Spring豆类):

前置过滤器

  • ServletDetectionFilter:检测请求是否通过Spring调度程序。使用键FilterConstants.IS_DISPATCHER_SERVLET_REQUEST_KEY设置布尔值。

  • FormBodyWrapperFilter:解析表单数据,并对下游请求进行重新编码。

  • DebugFilter:如果设置debug请求参数,则此过滤器将RequestContext.setDebugRouting()RequestContext.setDebugRequest()设置为true。

路由过滤器

  • SendForwardFilter:此过滤器使用Servlet RequestDispatcher转发请求。转发位置存储在RequestContext属性FilterConstants.FORWARD_TO_KEY中。这对于转发到当前应用程序中的端点很有用。

过滤器:

  • SendResponseFilter:将代理请求的响应写入当前响应。

错误过滤器:

  • SendErrorFilter:如果RequestContext.getThrowable()不为null,则转发到/错误(默认情况下)。可以通过设置error.path属性来更改默认转发路径(/error)。

@EnableZuulProxy过滤器

创建从DiscoveryClient(如Eureka)以及属性加载路由定义的DiscoveryClientRouteLocator每个serviceIdDiscoveryClient创建路由。随着新服务的添加,路由将被刷新。

除了上述过滤器之外,还安装了以下过滤器(正常Spring豆类):

前置过滤器

  • PreDecorationFilter:此过滤器根据提供的RouteLocator确定在哪里和如何路由。它还为下游请求设置各种与代理相关的头。

路由过滤器

  • RibbonRoutingFilter:此过滤器使用Ribbon,Hystrix和可插拔HTTP客户端发送请求。服务ID位于RequestContext属性FilterConstants.SERVICE_ID_KEY中。此过滤器可以使用不同的HTTP客户端。他们是:

    • Apache HttpClient这是默认的客户端。

    • Squareup OkHttpClient v3。通过在类路径上设置com.squareup.okhttp3:okhttp库并设置ribbon.okhttp.enabled=true来启用此功能。

    • Netflix Ribbon HTTP客户端。这可以通过设置ribbon.restclient.enabled=true来启用。这个客户端有限制,比如它不支持PATCH方法,还有内置的重试。

  • SimpleHostRoutingFilter:此过滤器通过Apache HttpClient发送请求到预定的URL。URL位于RequestContext.getRouteHost()

自定义Filter:
public class MyFliter extends ZuulFilter {    //filter:4,pre,post,route,error    @Override    public String filterType() {        return "pre";  //在访问服务之前    }    @Override    public int filterOrder() {        return 0;    }    //是否开启Fliter    @Override    public boolean shouldFilter() {        return true;    }    @Override    public Object run() {        HttpServletRequest request = RequestContext.getCurrentContext().getRequest(); //注意这个类RequestContext        String remoteHost = request.getRemoteHost();        int remotePort = request.getRemotePort();        String remoteAddr = request.getRemoteAddr();        System.out.println(remoteAddr+"---------"+remoteHost+"---------"+remotePort);        return null;    }}
Zuul内部使用Ribbon调用远程URL,并且Ribbon客户端默认在第一次调用时由Spring Cloud加载。可以使用以下配置更改Zuul的此行为,并将导致在应用程序启动时,子Ribbon相关的应用程序上下文正在加载。


Hystrix:

断路器:当远程服务访问不了的时候会触发。
看:https://www.oschina.net/search?scope=blog&q=Hystrix
添加依赖:
<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-hystrix</artifactId></dependency>
@SpringBootApplication@EnableEurekaClient@EnableFeignClients@EnableCircuitBreaker    //开启断路器@EnableHystrixDashboard  //仪表盘public class MovieServiceHystrix {    public static void main(String[] args){        SpringApplication.run(MovieServiceHystrix.class,args);    }}
@HystrixCommand(fallbackMethod = "stubMyService",    commandProperties = {      @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE") //指定策略    }) //这个属性应该是用在Ribbon中的,远程服务访问不了时候执行的方法
hystrix查看health和hyxtrix.stream需要
<dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-actuator</artifactId>    </dependency>
如果用Ribbon来处理Hystrix命令,则需要将Hystrix的超时时间长与Ribbon的时间
 (1)使用Hystrix仪表盘:
  添加依赖:
<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId></dependency>
访问/hystrix.stream即可看到数据。
 (2)使用Turbine:
   Turbine是将所有相关/hystrix.stream端点聚合到Hystrix仪表板中使用的/turbine.stream的应用程序
 添加依赖:
<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-turbine</artifactId></dependency>
application.yml配置






spring:  application:    name: microservice-turbineturbine:  aggregator:    clusterConfig: MOVIE-SERVICE-HYSTRIX  appConfig: movie-service-hystrix  #这是监控多个服务的配置   #aggregator:      #clusterConfig: default   #appConfig: customers,stores    #clusterNameExpression: "'default'"#turbine.instanceUrlSuffix.MOVIE-SERVICE-HYSTRIX: /demo/hystrix.stream   配置完context-path之后,配置这个就可以直接/hystrix.stream
http://my.turbine.sever:8080/turbine.stream?cluster=<CLUSTERNAME>;使用Turbine地址加配置的clusterConfig去访问
@SpringBootApplication@EnableTurbine  //开启Turbinepublic class TurbineApplication {    public static void main(String[] args){        SpringApplication.run(TurbineApplication.class,args);    }}
Turbine基本就是用来查看访问远程服务的次数,频率什么的。

Spring Cloud Config :

Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以在所有环境中管理应用程序的外部属性。客户端和服务器上的概念映射与Spring EnvironmentPropertySource抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用。随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。(主要还是用于从Git上或者其他地方拉取配置文件)
介绍:https://www.oschina.net/search?scope=blog&q=Spring+Cloud+Config

用下列形式的方式进行访问:
/{application}/{profile}[/{label}]/{application}-{profile}.yml/{label}/{application}-{profile}.yml/{application}-{profile}.properties/{label}/{application}-{profile}.properties

添加依赖:
<dependencies>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-config-server</artifactId>  //服务端    </dependency></dependencies>
application.yml配置:
  cloud:    config:      server:        git:          #uri: https://git.oschina.net/8277/{application} //通配符          uri: https://git.oschina.net/8277/spring-cloud-server-test  //远程库#这个client会读取git上的application.properties的文件,比如端口号,导致本地的被覆盖掉了  #cloud:    #config:      #server:        #git:          #uri: https://git.oschina.net/8277/spring-cloud-server-test //默认,如果访问不到就访问这个          #repos:            #simple: https://git.oschina.net/8277/simple            #special:              #pattern: special*/dev*,*special*/dev*  //匹配,满足这些才能被访问              #uri: https://git.oschina.net/8277/special
开启Server:
@SpringBootApplication@EnableConfigServerpublic class ConfigServer {    public static void main(String[] args){        SpringApplication.run(ConfigServer.class,args);    }}
客户端:
添加依赖:
<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-config</artifactId></dependency>
application.yml配置,由于Spring Cloud有限扫描bootstrap.yml,所以我们需要新建一个bootstrap.yml,
配置:
spring:  cloud:    config:      uri: http://localhost:7913   //服务端地址      label: master  //这个是分支      profile: default //视频说应该这个配,将访问项目名配成application.name,profile配成-后面的东西,我不是很理解  application:    name: simple   #我怎么才能让client可以访问多个serverserver:  port: 7914
对了 这里还有一个坑,如果服务端的配置文件中配置了端口,会将客户端配置的端口号覆盖。
spring:  cloud:    config:      server:        git:          uri: https://github.com/spring-cloud-samples/config-repo          searchPaths: foo,bar*

在此示例中,服务器搜索顶级和“foo /”子目录以及名称以“bar”开头的任何子目录中的配置文件。

认证:
服务端:
dependencies>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-config-server</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-security</artifactId>    </dependency></dependencies>
  cloud:    config:      server:        git:          uri: https://git.oschina.net/8277/spring-cloud-server-testsecurity:  user:    password: 123456    name: user  basic:    enabled: true
客户端:
spring:  cloud:    config:      uri: http://user:123456@localhost:7917      label: master      profile: dev      #username: user      #password: 123456 属性优先级比URL  application:    name: foobar   #我怎么才能让client可以访问多个serverserver:  port: 7918
加密解密:
需要Server.jks,具体生成可以看文档,需要CURL工具。
服务端:
encrypt:  key: abc 对称加密 这个密钥好像和文件也有点关系,如果密钥是abc,那么文件也要以abc开头
将server.jks放在classpath下

在远程的文件中放的是加密后的信息,用client访问就可以得到解密后的信息
properties:profile={cipher}d82961bcd0b29c3289e032f7811077d3ec711df0802c9529843b1492cd9f6b2b
yml:profile:‘{cipher}d82961bcd0b29c3289e032f7811077d3ec711df0802c9529843b1492cd9f6b2b’

非对称加密:
encrypt:  keyStore:    location: classpath:/server.jks    password: letmein  //这些属性都是使用curl的时候自己写的    alias: mytestkey    secret: changeme

用 远程文件更改后, 用BUS刷新项目中获取的值。用的是RabbitMQ,具体操作 我蒙蔽了 实在有点不懂

原创粉丝点击