spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
searchPaths: foo,bar*
菜鸟刚接触Spring Cloud,摸着石头过河。
添加Eureka依赖:org.springframework.boot spring-boot-starter-parent 1.5.4.RELEASE org.springframework.cloud spring-cloud-dependencies Dalston.SR1 pom import org.springframework.cloud spring-cloud-starter-config
org.springframework.cloud spring-cloud-starter-eureka-server //访问Eureka需要用户名,密码 org.springframework.cloud spring-cloud-starter-security
server: port: 8991 eureka: client: service-url: defaultZone: http://localhost:8991/eureka #不当成eureka client,本身eureka server就有client register-with-eureka: false fetch-registry: false security: basic: enabled: true user: name: user password: 123456Eureka本身也是一个客户端,所以需要剔除
#不当成eureka client,本身eureka server就有client register-with-eureka: false fetch-registry: false
@SpringBootApplication @EnableEurekaServer public class Discovery { public static void main(String[] args){ SpringApplication.run(Discovery.class,args); } }
org.springframework.cloud spring-cloud-starter-eureka
//这个用于健康检查org.springframework.boot spring-boot-starter-actuator
server: port: 7904 eureka: 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 @EnableEurekaClient public class UserService { public static void main(String[] args){ SpringApplication.run(UserService.class,args); } }这样就将服务注册到Eureka中
spring: profiles: peer1 eureka: instance: hostname: peer1 client: serviceUrl: defaultZone: http://peer2/eureka/ --- spring: profiles: peer2 eureka: instance: hostname: peer2 client: serviceUrl: defaultZone: http://peer1/eureka/修改本地hosts文件,将127.0.0.1映射到peer1,peer2,
@Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
@Controller public 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
ribbonServerList:ConfigurationBasedServerList
ServerListFilter
ribbonServerListFilter:ZonePreferenceServerListFilter
ILoadBalancer
ribbonLoadBalancer:ZoneAwareLoadBalancer
ServerListUpdater
ribbonServerListUpdater:PollingServerListUpdater
users: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRuleusers指服务名称。
ribbon: eureka: enabled: false
stores: ribbon: listOfServers: example.com,google.com
ribbon: eager-load: enabled: true clients: client1, client2, client3
开启Feignorg.springframework.cloud spring-cloud-starter-feign org.springframework.cloud spring-cloud-starter-eureka
@SpringBootApplication @EnableFeignClients @EnableEurekaClient public 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客户端。
feign.okhttp.enabled
或
feign.httpclient.enabled
设置为
true
,并将它们放在类路径上来使用OkHttpClient和ApacheHttpClient feign客户端。 // 设置用什么HttpClient访问
@FeignClient(name = "${feign.name}", url = "${feign.url}")
Feign也可以这么配置,如果使用 URL属性,则一定需要配上name属性
@Configuration
public 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();
}
@Component
static class HystrixClientFallbackFactory implements FallbackFactory {
@Override
public HystrixClient create(Throwable cause) {
return new HystrixClientWithFallBackFactory() {
@Override
public Hello iFailSometimes() {
return new Hello("fallback; reason was: " + cause.getMessage());
}
};
}
} //使用断路器,使用fallbackFactory属性,可以在Throwable cause中的到回退原因
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
feign.compression.response.enabled=true // Feign请求压缩
org.springframework.cloud spring-cloud-starter-zuul org.springframework.cloud spring-cloud-starter-eureka
@SpringBootApplication @EnableZuulProxy public class ZuulApplication { public static void main(String[] args){ SpringApplication.run(ZuulApplication.class,args); } } //开启zuul
server: port: 7777 #context-path: /demo 这个配置是等于tomcat中的项目路径,http://localhost:8080/demo eureka: 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.stream spring: application: name: microservice-getaway-zuul zuul: #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还是有点不懂,还需要看。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000 //配置超时时间
Zuul支持Hystrix的回退(即通过Zuul访问服务,如果服务挂了,可以做后续处理)
@Component public 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
。每个serviceId
从DiscoveryClient
创建路由。随着新服务的添加,路由将被刷新。
除了上述过滤器之外,还安装了以下过滤器(正常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()
。
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相关的应用程序上下文正在加载。
org.springframework.cloud spring-cloud-starter-hystrix
@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需要
org.springframework.boot
spring-boot-starter-actuator
如果用Ribbon来处理Hystrix命令,则需要将Hystrix的超时时间长与Ribbon的时间
访问/hystrix.stream即可看到数据。org.springframework.cloud spring-cloud-starter-hystrix-dashboard
/hystrix.stream
端点聚合到Hystrix仪表板中使用的/turbine.stream
的应用程序
application.yml配置org.springframework.cloud spring-cloud-starter-turbine
spring: application: name: microservice-turbine turbine: 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.streamhttp://my.turbine.sever:8080/turbine.stream?cluster=
@SpringBootApplication @EnableTurbine //开启Turbine public class TurbineApplication { public static void main(String[] args){ SpringApplication.run(TurbineApplication.class,args); } }Turbine基本就是用来查看访问远程服务的次数,频率什么的。
Environment
和PropertySource
抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用。
随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。
服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。(主要还是用于从Git上或者其他地方拉取配置文件)
/{application}/{profile}[/{label}] /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties
application.yml配置:org.springframework.cloud spring-cloud-config-server //服务端
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 @EnableConfigServer public class ConfigServer { public static void main(String[] args){ SpringApplication.run(ConfigServer.class,args); } }客户端:
application.yml配置,由于Spring Cloud有限扫描bootstrap.yml,所以我们需要新建一个bootstrap.yml,org.springframework.cloud spring-cloud-starter-config
spring: cloud: config: uri: http://localhost:7913 //服务端地址 label: master //这个是分支 profile: default //视频说应该这个配,将访问项目名配成application.name,profile配成-后面的东西,我不是很理解 application: name: simple #我怎么才能让client可以访问多个server server: port: 7914对了 这里还有一个坑,如果服务端的配置文件中配置了端口,会将客户端配置的端口号覆盖。
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
searchPaths: foo,bar*
在此示例中,服务器搜索顶级和“foo /”子目录以及名称以“bar”开头的任何子目录中的配置文件。
dependencies>org.springframework.cloud spring-cloud-config-server org.springframework.cloud spring-cloud-starter-security dependencies>
cloud: config: server: git: uri: https://git.oschina.net/8277/spring-cloud-server-test security: 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可以访问多个server server: port: 7918加密解密:
encrypt: key: abc 对称加密 这个密钥好像和文件也有点关系,如果密钥是abc,那么文件也要以abc开头将server.jks放在classpath下
encrypt: keyStore: location: classpath:/server.jks password: letmein //这些属性都是使用curl的时候自己写的 alias: mytestkey secret: changeme