本文来自网易云社区,转载务必请注明出处。
Spring Cloud 是spring团队推出的基于SpringBoot的分布式微服务框架,为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性 Token、全局锁、决策竞选、分布式会话和集群状态)操作的开发工具。
随着部门内的产品,包括对外提供的一些服务越来越多,另外有一些基础的功能需要抽象出来,团队内部就开始对一些接口和业务进行服务化的改造,经过一些对比,初步采用的方案就是spring cloud。现对spring cloud的使用做一些简单的总结。
基本配置
maven配置
项目本身都是基于maven的,首先可以利用maven的parent project的特性来管理spring cloud依赖的版本,spring cloud本身也提供了几个starter project的maven依赖管理的基础jar包。大致的配置如下:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> </exclusions> </dependency> ... </dependencies>
服务注册中心
dubbo的服务的注册和发现可以依赖于zk或者redis来实现,spring cloud官方提供了自己的解决方案,使用eureka来做的,所以我们需要一个eureka server,实现起来很简单,按照示例来即可:
pom中添加
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency>
主程序如下
@SpringBootApplication@EnableEurekaClientpublic class EurekaServer { public static void main(String[] args) { SpringApplication.run(EurekaServer.class, args); } }
在application.properties中添加监听的端口号,如server.port=8761,然后启动程序即可
注册一个服务
在main函数所在程序中添加 @SpringBootApplication注解
在application.properties中添加上面注册中心的地址,比如说, eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 注意,生产环境这个注册中心是需要多节点的
设置服务注册的名称,以及监听的端口,也是在application.properties中的,如:
spring.application.name=spam-detect-service server.port=8082
在controller上添加 @RestController及方法的@RequestMapping注解
启动main函数,我们的服务就启动并注册到eureka server上了
发现并调用服务
在主程序的入口添加注解
@SpringBootApplication@EnableEurekaClient
添加一个RestTemplate实例(在主程序中添加即可),声明为bean,方便别的服务进行autowired注入,用来进行HTTP调用
@LoadBalanced@BeanRestTemplate restTemplate() { return new RestTemplate(); }
配置application.properties,主要是配置注册中心的地址 eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
在程序的代码中使用restTemplate根据服务名称访问服务
@AutowiredRestTemplate restTemplate;static final String SERVICE_NAME = "spam-detect-service";public MMResult spamDetect(String type, String image) { try { .... MMResult r = restTemplate.postForObject("http://" + SERVICE_NAME + "/xxxx", request, MMResult.class); return r; } catch (Throwable t) { .... } }
服务注册/发现
Spring Cloud的一个重要贡献者是Netflix,它提供了构建一个分布式rpc系统的关键的一些核心模块,在spring cloud 中,我们可以通过几个简单的注释,就能构造一个分布式系统。系统中提供的模式包括服务发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载平衡等。
服务发现
Spring Cloud默认使用netflix贡献的eureka来作为服务注册和发现的。 服务发现默认采用EurekaClient,使用方式是:
@Autowiredprivate EurekaClient discoveryClient;
可能是觉得EurekaClient不太好用,spring同时提供了替代的方式,就是基于Feign和上面提到的RestTemplate,在实例上添加@RestTemplate注解即可。
服务注册
在应用程序的main函数上添加如下注解即可
@SpringBootApplication@EnableEurekaServer
Ribbon
Spring Cloud采用ribbon来实现负载均衡loadbalance,使用restTemplate的时候添加@LoadBalance注解即可。服务的失败重试retry、超时配置等,可以在application.properties中做一下配置即可
ribbon.ConnectTimeout=500ribbon.ReadTimeout=5000ribbon.MaxAutoRetries=1ribbon.MaxAutoRetriesNextServer=1ribbon.OkToRetryOnAllOperations=true
ribbon还可以不使用服务名称的方式进行调用,可以把服务配置为固定的物理地址列表进行访问,为服务名称
.ribbon.listOfServers= 127.0.0.1:1234,127.0.0.1:1235
断路器(Circuit Breaker)
当服务不可用的时候,或者需要进行并发访问控制的时候使用的,spring cloud采用Hystrix来实现,在业务方法上加上@HystrixCommand 注解
服务不可用事默认回复
配置@HystrixCommand的fallback属性,如@HystrixCommand(fallbackMethod = "systemError"),注意systemError方法需要与业务方法的参数是一致的
并发访问控制
配置@HystrixCommand的properties属性
commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000") }, threadPoolProperties = { @HystrixProperty(name = "coreSize", value = "5"), @HystrixProperty(name = "maxQueueSize", value = "10") }
服务路由zuul
zuul是基于jvm的路由转发和负载均衡,有点类似于nginx,但是是基于jvm的,我们java程序员可以很方便的在上面做一些事情,它通常是放在入口,可以做一些转发、安全校验等统一的事情。它既可以转发到本地的服务,也可以转发到互联网上其它url(使用ribbon的固定物理地址方式)。
配置转发
在application.properties中配置
zuul.routes.<users>.path = /myusers/** zuul.routes.<users>.serviceId = users
在代码中定义转发
@Beanpublic PatternServiceRouteMapper serviceRouteMapper() { return new PatternServiceRouteMapper( "(?<name>^.+)-(?<version>v.+$)", "${version}/${name}"); }
其它
可以配置zuul.host.maxTotalConnections 和 zuul.host.maxPerRouteConnections 可以控制路由的并发量
其它常用配置项
ip prefer and ignore
SpringCloud注册服务的时候使用的是InetUtils的findFirstNonLoopbackAddress()方法,有时候我们的服务器被发现的地址,偏偏不是机房内的互通ip,导致服务注册上了,调用的时候访问不通,这时候我们就需要设置忽略这个ip了,在配置文件中 spring.cloud.inetutils.ignoredInterfaces=eth0
跨域
不讨论跨域的必要性,如果需要用到跨域请求,需要做以下配置
在代码中设置 response.addHeader("Access-Control-Allow-Origin", "*");
添加option处理类
@RestControllerpublic class OptionBean { @RequestMapping(method = RequestMethod.OPTIONS, value = "/**") public ResponseEntity manageOptions(HttpServletResponse response) { response.addHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Allow", "HEAD,GET,PUT,OPTIONS"); return new ResponseEntity(HttpStatus.OK); } }
3.设置 spring.mvc.dispatch-options-request=true
tomcat的一些配置
如需要设置post size,upload file dize 等
@Bean public MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); factory.setMaxFileSize("20MB"); factory.setMaxRequestSize("20MB"); return factory.createMultipartConfig(); } @Bean public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() { TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory(); tomcatFactory.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override public void customize(Connector connector) { // tomcat default nio connector Http11NioProtocol handler = (Http11NioProtocol) connector .getProtocolHandler(); // acceptCount is backlog, default value is 100, you can change // which you want value in here handler.setBacklog(100); handler.setMaxThreads(1000); connector.setMaxPostSize(-1); } }); return tomcatFactory; }
服务存活检查
eureka.client.healthcheck.enabled=true
Spring Cloud其它功能及后续关注
配置中心,原生时基于git,感觉不太好用,所以暂时没有更多关注
与zookeeper、netty等的交互。目前主要是基于http的,对于实时性要求比较高的场合,可以研究一下
本文来自网易云社区 ,经作者王洪伟授权发布。
网易云免费体验馆,0成本体验20+款云产品!
更多网易研发、产品、运营经验分享请访问网易云社区。
相关文章:
【推荐】 NOS直传加速服务