springboot项目创建

来源:互联网 发布:cf刷枪软件免费版 编辑:程序博客网 时间:2024/06/05 23:50

1.File->new Projectt->Spring Initializr->勾选web,lombok(需要安装插件使用File->Settings->Plugins->Browse repositories)

2.编写controller

@RestControllerpublic class HelloWorld {    @RequestMapping("/")    String helloWorld(){        return "Hello World";    }}
3.启动

@SpringBootApplicationpublic class YyApplication {public static void main(String[] args) {SpringApplication.run(YyApplication.class, args);}}
4.启动成功

2017-09-13 13:49:14.233  INFO 2380 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-09-13 13:49:14.236  INFO 2380 --- [           main] com.wacmx.yy.YyApplication               : Started YyApplication in 2.471 seconds (JVM running for 4.397)

5.Eureka Service(服务注册中心)

右键工程->NEW->Module->spring initialir->勾选eureka server

启动服务注册中心@EnableEurekaServer

@EnableEurekaServer@SpringBootApplicationpublic class ServerApplication {public static void main(String[] args) {SpringApplication.run(ServerApplication.class, args);}}
application.yml(两个false表示是eureka server)

server:  port: 8761eureka:  instance:    hostname: localhost  client:    registerWithEureka: false    fetchRegistry: false    serviceUrl:      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
点击启动类访问 http://localhost:8761/

此刻Application显示 No instances available

6.Eureka Client(服务提供者)
当client向server注册时,它会提供一些元数据,例如主机和端口,URL,主页等。Eureka server 从每个client实例接收心跳消息。 如果心跳超时,则通常将该实例从注册server中删除。

创建过程与server类似,勾选eureka discovery进入

启动类添加注解

@EnableEurekaClient@SpringBootApplication@RestControllerpublic class ClientApplication {public static void main(String[] args) {SpringApplication.run(ClientApplication.class, args);}@Value("${server.port}")String port;@RequestMapping("/hi")public String home(String name){return "hi"+name+"i'm from port:"+port;}

application.yml

eureka: client:   serviceUrl:     defaultZone: http://localhost:8761/eureka/server: port: 8762spring: application:   name: service-hi

启动后访问 http://localhost:8761/
此时Apllicaion则为 SERVICE-HI,端口为8762

访问http://localhost:8762/hi?name=wacmx

显示:

hiwacmxi'm from port:8762

7.ribbon+restTemplate(服务消费者Ⅰ)

简介:

在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于httprestful的。Spring cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。

ribbon是一个负载均衡客户端,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon。

项目前准备:

启动eureka-server 工程;启动service-hi工程,它的端口为8762;将service-hi的配置文件的端口改为8763,并启动,这时你会发现:service-hi在eureka-server注册了2个实例,这就相当于一个小的集群。如下图:

 

创建新的boot项目,勾选Web,Eureka Discovery,Ribbon,项目命名service-ribbon

application.yml

eureka: client:   serviceUrl:     defaultZone: http://localhost:8761/eureka/server: port: 8764spring: application:   name: service-ribbon

启动类:

@SpringBootApplication@EnableDiscoveryClient//向服务中心注册public class RibbonApplication {    public static void main(String[] args) {       SpringApplication.run(RibbonApplication.class, args);    }    @Bean//向程序的ioc注入一个bean:restTemplate   @LoadBalanced//注解表明这个restRemplate开启负载均衡的功能   RestTemplate restTemplate() {       return new RestTemplate();    }}


测试类

HelloService:

@Servicepublic class HelloService {   @Autowired   private RestTemplate restTemplate;    public String hiService(String name){        /**直接用的程序名替代了具体的url地址        在ribbon中它会根据服务名来选择具体的服务实例        根据服务实例在请求的时候会用具体的url替换掉服务名*/       return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);    }}

HelloController:

@RestControllerpublic class HelloController {   @Autowired   private HelloService helloService;   @RequestMapping("/hi")    publicString hi(String name){       return helloService.hiService(name);    }}

访问http://localhost:8764/hi?name=wacmx,交替显示

(idea启动类配置的EditConfiguration中有一个Single instance only在service-hi那个服务中取消选中;
否则你启动第二遍的时候,系统会自动把之前的服务给关闭了)

hiwacmxi'm from port:8762hiwacmxi'm from port:8763

说明当我们通过调用restTemplate.getForObject(“http://SERVICE-HI/hi?name=“+name,String.class)方法时,已经做了负载均衡,访问了不同的端口的服务实例。

此时的架构图:


一个服务注册中心,eureka server,端口为8761

service-hi工程跑了两个实例,端口分别为8762,8763,分别向服务注册中心注册

sercvice-ribbon端口为8764,向服务注册中心注册

当sercvice-ribbon通过restTemplate调用service-hi的hi接口时,因为用ribbon进行了负载均衡,会轮流的调用service-hi:8762和8763两个端口的hi接口;

8.Feign(服务消费者Ⅱ)

简介:

Feign 采用的是基于接口的注解

Feign 整合了ribbon

创建项目:

勾选Web,Eureka Discovery,Feign,命名为service-feign

pom.xml

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-feign</artifactId><version>1.3.2.RELEASE</version></dependency>
application.yml

eureka:  client:    serviceUrl:      defaultZone: http://localhost:8761/eureka/server:  port: 8765spring:  application:    name: service-feign
启动类:

@SpringBootApplication@EnableDiscoveryClient@EnableFeignClientspublic class FeignApplication {public static void main(String[] args) {SpringApplication.run(FeignApplication.class, args);}}
Feign接口,通过@FeignClient("服务名")指定具体服务,和具体的接口:

@FeignClient(value = "service-hi")public interface SchedualServiceHi {    @GetMapping( "/hi")    String sayHiFromClientOne(@RequestParam(value="name") String name);}
HiController 暴露/hi接口,供SchedualServiceHi消费服务:

@RestControllerpublic class HiController {    @Autowired    private SchedualServiceHi schedualServiceHi;    @GetMapping("/hi")    public String sayHi(@RequestParam String name){        return schedualServiceHi.sayHiFromClientOne(name);    }}
启动后,多次访问http://localhost:8765/hi?name=wacmx,接替显示

hiwacmx,i'm from port:8762hiwacmx,i'm from port:8763

9.Hystrix(断路器)

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。为了解决这个问题,业界提出了断路器模型。

Netflix开源了Hystrix组件,实现了断路器模式,SpringCloud对这一组件进行了整合。在微服务架构中,一个请求需要调用多个服务是非常常见的

较底层的服务如果出现故障,会导致连锁故障。当对特定的服务的调用的不可用达到一个阀值(Hystric是5秒20次) 断路器将会被打开。

断路打开后,可用避免连锁故障,fallback方法可以直接返回一个固定值。

启动eureka-service(port:8761),eureka-hi(port:8762)

①基于service-ribbon工程

pom.xml添加依赖:

<dependency>   <groupId>org.springframework.cloud</groupId>   <artifactId>spring-cloud-starter-hystrix</artifactId></dependency>

启动类添加@EnableHystrix:

@SpringBootApplication@EnableDiscoveryClient//向服务中心注册@EnableHystrix//开启断路器public class RibbonApplication {    public static void main(String[] args) {       SpringApplication.run(RibbonApplication.class, args);    }    @Bean//向程序的ioc注入一个bean:restTemplate   @LoadBalanced//注解表明这个restRemplate开启负载均衡的功能    RestTemplaterestTemplate() {       return new RestTemplate();    }}

改造HelloService类:

@Servicepublic class HelloService {   @Autowired   private RestTemplate restTemplate;   /**该注解对该方法创建了熔断器的功能,并指定了fallbackMethod熔断方法*/   @HystrixCommand(fallbackMethod = "hiError")   public String hiService(String name){        /**直接用的程序名替代了具体的url地址        在ribbon中它会根据服务名来选择具体的服务实例        根据服务实例在请求的时候会用具体的url替换掉服务名*/       returnrestTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);    }   //熔断方法   public String hiError(String name){       return "hi\t"+name+",sorry,error";    }}

启动:service-ribbon 工程,当我们访问http://localhost:8764/hi?name=wacmx

hiwacmxi'm from port:8762

关闭service-hi工程后,执行熔断方法:

hi    wacmx,sorry,error

这就说明当 service-hi 工程不可用的时候,service-ribbon调用 service-hi的API接口时,会执行快速失败,直接返回一组字符串,而不是等待响应超时,这很好的控制了容器的线程阻塞。
②基于service-feign工程:

feign自带断路器,application.yml添加如下配置:

feign: hystrix:   enabled: true

SchedualServiceHiHystrix熔断类,继承SchedualService接口:

@Component//注入到IOC容器public class SchedualServiceHiHystriximplements SchedualServiceHi{   @Override   public String sayHiFromClientOne(String name) {       return "sorry\t"+name;    }}

SchedualService @FeignClient接口中添加fallback,指定熔断类

@FeignClient(value = "service-hi",fallback= SchedualServiceHiHystrix.class)public interface SchedualServiceHi {   @GetMapping( "/hi")   String sayHiFromClientOne(@RequestParam(value="name") Stringname);}

启动服务:

此时service-hi未开启,访问http://localhost:8765/hi?name=wacmx

sorry wacmx

开启service-hi服务:

hiwacmxi'm from port:8762

③Hystrix Dashboard(断路器,hystrix仪表盘,ribbon与feign相同处理)

pom.xml添加依赖:

<dependency>           <groupId>org.springframework.boot</groupId>           <artifactId>spring-boot-starter-actuator</artifactId>        </dependency>        <dependency>           <groupId>org.springframework.cloud</groupId>           <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>       </dependency>

启动类添加@EnableHystrixDashboard

访问 http://localhost:8765/hystrix (以feign为例),会有熊出没

点击Monitor Stream 会进入对应的监控页面.

10.zuul(路由网关)

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简单的微服务系统:

 

使用场景:

在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服。,服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理(下一篇文章讲述),配置服务的配置文件放在git仓库,方便开发人员随时改配置。

Zuul简介:

Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。

创建项目:

勾选Web,Eureka Discovery,Zuul,项目命名为service-zuul

启动类:

@EnableZuulProxy@EnableEurekaClient@SpringBootApplicationpublic class ZuulApplication {        publicstatic void main(String[] args) {              SpringApplication.run(ZuulApplication.class,args);       }}

application.yml:

首先指定服务注册中心的地址为http://localhost:8761/eureka/,服务的端口为8769,服务名为service-zuul;以/api-a/ 开头的请求都转发给service-ribbon服务;以/api-b/开头的请求都转发给service-feign服务;

eureka: client:   serviceUrl:     defaultZone: http://localhost:8761/eureka/server: port: 8769spring: application:   name: service-zuulzuul: routes:   api-a:     path: /api-a/**     serviceId: service-ribbon    api-b:     path: /api-b/**     serviceId: service-feign

依次运行这五个工程;打开浏览器访问:http://localhost:8769/api-a/hi?name=wacmx ;浏览器显示:

hi wacmx,i am from port:8762

打开浏览器访问:http://localhost:8769/api-b/hi?name=wacmx ;浏览器显示:

hi wacmx,i am from port:8762

这说明zuul起到了路由的作用

zuul的服务过滤作用,可以用作安全验证:

@Componetpublic class MyFilter extends ZuulFilter {   private static Logger log = LoggerFactory.getLogger(MyFilter.class);    /**     *返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型    * pre:路由之前    * routing:路由之时    * post: 路由之后    * error:发送错误调用    * filterOrder:过滤的顺序    * shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。    * run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。    */    @Override   public String filterType() {       return "pre";    }    @Override   public int filterOrder() {       return 0;    }    @Override   public boolean shouldFilter() {       return true;    }    @Override    publicObject run() {       RequestContext ctx = RequestContext.getCurrentContext();       HttpServletRequest request = ctx.getRequest();       log.info(String.format("%s>>>%s",request.getMethod(),request.getRequestURL().toString()));       Object accessToken = request.getParameter("token");       if (accessToken == null){           ctx.setSendZuulResponse(false);           ctx.setResponseStatusCode(401);           try {               ctx.getResponse().getWriter().write("token is empty");           } catch (IOException e) {                e.printStackTrace();           }           return  null;       }       log.info("ok");       return null;    }}


启动后,访问http://localhost:8769/api-a/hi?name=wacmx

token is empty


访问http://localhost:8769/api-a/hi?name=wacmx&token=520

hiwacmxi'm from port:8762 


以上,zuul完成了路由代理,与安全过滤的功能.

11.spring cloud config(分布式配置中心)

简介:

在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client。

①创建config-server项目:

勾选Config Server,Eureka Server,命名为config-server

启动类添加注解@EnableConfigServer:

@SpringBootApplication

@EnableConfigServer

@EnableEurekaClient

public class ConfigApplication {

      publicstatic void main(String[] args) {

              SpringApplication.run(ConfigApplication.class,args);

      }

}

application.properties

spring.application.name=config-server

server.port=8888

 

#git仓库地址

spring.cloud.config.server.git.uri=https://github.com/forezp/SpringcloudConfig/

#仓库路径

spring.cloud.config.server.git.searchPaths=respo

#仓库的分支

spring.cloud.config.label=master

#git仓库的用户名

#spring.cloud.config.server.git.username=yourusername

#git仓库的用户密码

#spring.cloud.config.server.git.password=yourpassword

 

远程仓库https://github.com/forezp/SpringcloudConfig/ 中有个文件config-client-dev.properties文件中有一个属性:

foo = foo version 3

启动程序:访问http://localhost:8888/foo/dev

{

name: "foo",

profiles: [

"dev"

],

label: null,

version:"a68876a6211369bae723348d5f8c3defe4a55e04",

state: null,

propertySources: [ ]

}

 

证明配置服务中心可以从远程程序获取配置信息。

http请求地址和资源文件映射如下:

/{application}/{profile}[/{label}]

/{application}-{profile}.yml

/{label}/{application}-{profile}.yml

/{application}-{profile}.properties

/{label}/{application}-{profile}.properties

 

②创建config-client项目:

 

勾选Web,Config Client,命名为config-client

application.properties:

spring.application.name=config-client

#远程仓库的分支

spring.cloud.config.label=master

#dev开发环境配置文件 test测试环境 pro正式环境

spring.cloud.config.profile=dev

#配置服务中心的网址

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

server.port=8881

 

启动类:

@SpringBootApplication

@RestController

@EnableEurekaClient

public class ConfigApplication {

 

  public static void main(String[] args) {

      SpringApplication.run(ConfigApplication.class, args);

    }

 

  @Value("${foo}")

  String foo;

 

  @RequestMapping("/hi")

  public String sayhi() {

      return foo;

    }

}

启动后访问:http://localhost:8881/hi

foo version 2

这就说明,config-client从config-server获取了foo的属性,而config-server是从git仓库读取的12. spring cloud config高可用的配置服务中心

当服务实例很多时,都从配置中心读取文件,这时可以考虑将配置中心做成一个微服务,将其集群化,从而达到高可用

 

①有一个Eureka-server(port:8889)

②改造Config-server

application.properties指定服务注册地址:

spring.application.name=config-server

server.port=8888

 

#git仓库地址

spring.cloud.config.server.git.uri=https://github.com/forezp/SpringcloudConfig/

#仓库路径

spring.cloud.config.server.git.searchPaths=respo

#仓库的分支

spring.cloud.config.label=master

#git仓库的用户名

#spring.cloud.config.server.git.username=yourusername

#git仓库的用户密码

#spring.cloud.config.server.git.password=yourpassword

#指定服务注册地址

eureka.client.serviceUrl.defaultZone=http://localhost:8889/eureka/

 

启动类添加@EnableEurekaServer注解

③改造config-client

pom.xml添加eureka依赖:

 

<dependency>

          <groupId>org.springframework.cloud</groupId>

          <artifactId>spring-cloud-starter-eureka</artifactId>

      </dependency>

 

application.properties加上服务注册地址:

spring.application.name=config-client

#远程仓库的分支

spring.cloud.config.label=master

#dev开发环境配置文件 test测试环境 pro正式环境

spring.cloud.config.profile=dev

#配置服务中心的网址

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

#指定服务注册地址

eureka.client.serviceUrl.defaultZone=http://localhost:8889/eureka/

#从配置中心读取文件

spring.cloud.config.discovery.enabled=true

#配置中心的servieId,即服务名

spring.cloud.config.discovery.serviceId=config-server

server.port=8881

 

在读取配置文件不再写ip地址,而是服务名,这时如果配置服务部署多份,通过负载均衡,从而高可用

依次启动eureka-servr,config-server,config-client 
访问网址:http://localhost:8889/

application中包含configserver 和 config client

访问http://localhost:8881/hi,浏览器显示:

foo version 2

12.消息总线

Spring Cloud Bus 将分布式的节点用轻量的消息代理连接起来。它可以用于广播配置文件的更改或者服务之间的通讯,也可以用于监控。本文要讲述的是用Spring Cloud Bus实现通知微服务架构的配置文件的更改。

下载rebbitmq:  http://www.rabbitmq.com/

config-client添加依赖

<dependency>

           <groupId>org.springframework.cloud</groupId>

           <artifactId>spring-cloud-starter-bus-amqp</artifactId>

       </dependency>

application.properties中加上RabbitMq的配置:

spring.rabbitmq.host=localhost

spring.rabbitmq.port=5672

# spring.rabbitmq.username=

# spring.rabbitmq.password=

依次启动eureka-server、confg-cserver,启动两个config-client,端口为:8881、8882。

访问http://localhost:8881/hi 或者http://localhost:8882/hi 浏览器显示:
foo version 2

这时我们去代码仓库将foo的值改为“foo version 4”,即改变配置文件foo的值。如果是传统的做法,需要重启服务,才能达到配置文件的更新。此时,我们只需要发送post请求:http://localhost:8881/bus/refresh,你会发现config-client会重新读取配置文件
再访问http://localhost:8881/hi 或者http://localhost:8882/hi 浏览器显示:

foo version 4

/bus/refresh接口可以指定服务,即使用”destination”参数,比如 “/bus/refresh?destination=customers:**”即刷新服务名为customers的所有服务,不管ip。
当git文件更改的时候,通过pc端用post 向端口为8882的config-client发送请求/bus/refresh/;此时8882端口会发送一个消息,由消息总线向其他服务传递,从而使整个微服务集群都达到更新配置文件。

13.spring cloud sleuth服务链接追踪

作用:在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin

http://blog.csdn.net/forezp/article/details/70162074

14.高可用服务注册中心

http://blog.csdn.net/forezp/article/details/70183572

 

特别鸣谢方志朋的博客 

 

 


原创粉丝点击