Spring Cloud 上手實戰-架構解析及實做

Spring簡介

爲何要使用微服務

  • 單體應用:

目前爲止絕大部分的web應用軟件採用單體應用,全部的應用的用戶UI、業務邏輯、數據庫訪問都打包在一個應用程序上。html

在線製圖 springCloud設計

缺點:java

開發相互干擾,隨着應用的不斷升級溝通協調成本增長
應用上線因爲某個功能升級致使須要總體的構建、總體測試、總體發佈
  • 微服務

把單體應用拆分紅小的、鬆藕合分佈式服務的形式 每一個應用必定是獨立構建、獨立部署與測試,應用也是獨立發佈,應用於應用直接一般經過restful API接口的形式進行相互調用。 解決了單體應用帶來的困擾。 在線製圖 springCloud設計web

Spring cloud 是什麼

發展歷史

2002,Rod Johonson發表了<<Expert One-on-One J2EE Design and Development>>,
包含了3萬行的代碼在包com.interface21中
2003,Juerge Hoeller,Yann Caroff 聯繫Rod,將書中代碼開源,Yann提出Spring這個詞,冠於書中代碼;
併發布0.9,使用Apache 2.0協議;Thomas Risberg負責Spring JDBC;Ben Alex將Acegi Security貢獻給Rod和Juergen
2004,1.0發佈
2005,<<Professional Java Development with Spring Framework>> <<Pro Spring>>出版;1.2.6發佈。
AspectJ Leader Adrian Coyler加入Interface21做爲首席科學家;
2006,Security 1.0、Spring webflow 1.0發佈;Spring 2.0發佈;
2007,Spring Batch、WebService、Integration發佈;Spring 2.5發佈;
2008,Spring Integration 1.0,Spring 2.5.6,Spring Batch 1.0;買了g2One,一家提供Groovy and Grails的公司;
2009,被VMWare發了42億美金買下;Spring Python、STS發佈、3.0發佈(將包拆開,不提供超級包),買了Cloud Foundry;
2010,VMWare買了RabbitMQ公司,得到RabbitMQ和Redis技術;
2011,Spring 3.一、Spring AMQP、Spring Data JPA、Spring-data-common 1.0
、Spring Data Redis、Spring Data Mongodb發佈;
2012,Rod Johnson離開VMWare;Spring Android、Mobile發佈;
2013,VMWare 和 EMC 協力組建了一家公司,Pivotal。Spring 4.0、Spring Boot發佈;
2014,Spring 4.1.三、SpringBoot 1.0發佈;
2015,Spring 4.二、4.3發佈;
2016,Spring 4.3 GA
2017,Spirng 5.x

Spring的出現讓EJB等重量級的容器技術逐漸走向末路。 Spring 經過對Bean的生命週期的管理,能夠快速方便的實現業務的邏輯處理。 Spring 能夠方便的整合幾乎全部的主流的開源項目如JPA,緩存,消息組合等等,方便的進行開發。spring

Spring Cloud實戰

本實戰目的: 全程演示如何建立一個基礎的、可用的Spring cloud分佈式應用系統 演示Spring Cloud各部分組件如何在應用以前協調、調用。 瞭解整個Spring Cloud的項目基本狀況,有一個初步的認識。 本實戰JAVA採用JDK8 Spring Boot版本採用最新2.1.0 release. Spring Cloud版本採用Greenwich.M1。數據庫

2.2.1. Spring Cloud基礎搭建

使用

阿里雲的spring cloud 架構圖在線設計地址: https://www.freedgo.com 便可使用Freedgo Desing 進行圖形設計.api

架構預覽地址:緩存

<a target='blank' href='https://www.freedgo.com/draw_index.html?#Uhttps://www.freedgo.com/templates/network/springcloud_aliyun.xml'>https://www.freedgo.com/draw_index.html?#Uhttps://www.freedgo.com/templates/network/springcloud_aliyun.xml</a>安全

Freedgo Design 是一in款在線繪製專業圖形的網站。Freedgo Design能夠繪製各類類型的圖形,針對業務邏輯的流程圖,軟件設計ER模板,工做流,各類雲平臺的系統部署架構圖包括阿里雲、AWS雲、騰訊雲、Oracle、Asure雲、IBM雲平臺等。服務器

在線製圖 springCloud設計

2.2.1.1. 創建基礎代碼

開發工具:Intellij idea 一、 創建一個mvn 工程項目 使用的java jdk 採用jdk8restful

2.2.1.2. 服務發現

創建子模塊discovery-service 在線製圖 springCloud設計 在線製圖 springCloud設計 在線製圖 springCloud設計 在線製圖 springCloud設計

咱們能夠看到mvn 依賴導入了netflix-eureka-server Spring boot 會啓動服務發現服務

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2.2.1.3. 服務配置

創建子模塊config-service 在線製圖 springCloud設計 在線製圖 springCloud設計 在線製圖 springCloud設計

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-config-server</artifactId>
</dependency>

2.2.1.4. 服務路由

在線製圖 springCloud設計 在線製圖 springCloud設計 在線製圖 springCloud設計

服務路由採用 Netflix Zuul 經過服務路由做爲eureka client,能夠被發現服務監控

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

基礎的組件建立完畢

2.2.1.5. 用戶認證中心

在線製圖 springCloud設計 在線製圖 springCloud設計

2.2.1.6. 業務服務模塊

在線製圖 springCloud設計 在線製圖 springCloud設計

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-security</artifactId>
</dependency>

2.2.2. 服務發現

傳統服務發現方式經過網絡DNS和負載均衡設備實現,須要網絡和硬件設置支持,維護成本高,網絡環境複雜 居於雲的服務發現具備以下優勢 高可用,熱部署 負載均衡 健康檢查,容錯機制 抽象服務的邏輯名稱 使用Spring與Netflix Eureka實現服務發現 在線製圖 springCloud設計

實現服務發現功能須要配置服務發現端及須要註冊服務配置客戶端 一、 發現服務端配置 服務註冊須要30 s 的時間才能顯示在 Eureka 服務中,由於 Eureka 須要從服務接收3次連續心跳包 ping,每次心跳包 ping 間隔10 s,而後才能使用這個服務。在部署和測試服務時,要牢記這一點。 application.yml

server:
  port: 8761
# Eureka 服務器將要監聽的端口

eureka:
  client:
    registerWithEureka: false #不要使用 Eureka 服務進行註冊
    fetchRegistry: false #不要在本地緩存註冊表信息

使用一個新的註解@EnableEurekaServer,就可讓咱們的服務成爲一個 Eureka 服務

二、 服務發現客戶端配置 以config-service爲例 須要作2件事情 一、 成爲服務發現的客戶端

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 
</dependency>

二、 配置application.yml(對應config-server來講咱們只須要配置以下)

spring:
  cloud:
    config:
      discovery:
        enabled: true

啓動運行查看

在線製圖 springCloud設計 在線製圖 springCloud設計

http://localhost:8761/eureka/apps/config-service。 應用做爲服務發現的客戶端設置 一、 添加客戶端依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

二、 配置application.yml

spring:
  application:
    name: business_service

eureka:
  instance:
    preferIpAddress: true
    #註冊服務的 IP,而不是服務器名稱
  client:
    registerWithEureka: true #向 Eureka 註冊服務
    fetchRegistry: true
    serviceUrl:  #拉取註冊表的本地副本
      defaultZone: http://localhost:8761/eureka/  #Eureka 服務的位置

一樣經過mvn spring-boot:run 打開http://localhost:8761 ,business_service已經註冊成功

使用服務發現查找服務

2.2.3. 用戶認證中心

在線製圖 springCloud設計

OAuth2協議說明:

總體OAuth協議包括兩方面: 一、 訪問受權:用戶必須經過受權獲取令牌 二、 資源權限:經過受權的用戶訪問受保護的資源,根據定義訪問權限來決定是否能夠訪問資源 配置說明: 啓用OAuth受權服務 增長@EnableAuthorizationServer 用於告訴 Spring Cloud,該服務將做爲 OAuth2 服務

package com.yuaoq.train.business;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;

@SpringBootApplication
@EnableResourceServer
@EnableAuthorizationServer
public class DemoApplication {

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

OAuth訪問受權配置,配置註冊的客戶端應用程序

@Configuration
public class Auth2Config extends AuthorizationServerConfigurerAdapter {
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    private UserDetailsService userDetailsService;
//    覆蓋 configure()方法。這定義了哪些客戶端將註冊到服務
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("yuaoq")
                .secret("{noop}secret")
                .authorizedGrantTypes(
                         "refresh_token",
                         "password",
                          "client_credentials")
                .scopes("webclient","mobileclient");
    }
    
//    該方法定義了 AuthenticationServerConfigurer 中使用的不一樣組件。這段代碼告訴 Spring 使用 Spring 提供的默認驗證管理器和用戶詳細信息服務
    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
     throws Exception {
        endpoints
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
    }
}

配置用戶權限

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    
    @Override
    @Bean
//    AuthenticationManagerBean 被 Spring Security 用來處理驗證
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
    //      Security 使用 UserDetailsService 處理返回的用戶信息,這些用戶信息將由 Spring Security 返回
    @Override
    @Bean
    public UserDetailsService userDetailsServiceBean() throws Exception {
        return super.userDetailsServiceBean();
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//             configure()方法是定義用戶、密碼和角色的地方
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("{noop}password")
                .roles("ADMIN","USER")
                .and()
                .withUser("anyone")
                .password("{noop}password")
                .roles("USER");
    }
}

獲取用戶信息(提供給其餘服務獲取用戶信息使用)

@GetMapping(value = "/auth/user")
public Map<String, Object> user(OAuth2Authentication user) {
   Map<String, Object> userInfo = new HashMap<>();
   userInfo.put("user", user.getUserAuthentication().getPrincipal());
   userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
   return userInfo;
}

經過postman測試 在線製圖 springCloud設計 自此提供了一個用戶認證的微服務模塊.

2.2.3.1. 業務模塊微服務

一、 對外提供restful Api @RestController:由spring web提供的居於restful 的接口標籤 生成一個restful api

@PostMapping("/list")
public ResponseEntity<List<String>> getBusiness() throws Exception {
    List<String> list = new ArrayList<String>();
    list.add("a");
    list.add("b");
   return Optional.of(list)
            .map(a -> new ResponseEntity<List<String>>(a, HttpStatus.OK))
            .orElseThrow(() -> new Exception("error"));
}

使用postman調用接口

在線製圖 springCloud設計 從postman返回的結果能夠看到401,未受權。 由於business_service服務引入了spring-cloud-starter-security 那麼默認是會對全部訪問作安全控制。

二、 服務的受權保護 如今business/list 是未受權,那怎麼配置一個受保護的oauth2.0資源,經過以下步驟 設置服務是一個受oauth保護的資源 在線製圖 springCloud設計 定義應用的OAuth屬性定義回調 URL

security:
  oauth2:
    resource:
      user-info-uri: http://localhost:8282/auth/user

定義受權用戶能夠訪問

@Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
    //     antMatchers()容許開發人員限制對受保護的 URL 和 HTTP DELETE 動詞的調用
//     hasRole()方法是一個容許訪問的角色列表,該列表由逗號分隔
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(HttpMethod.POST, "/api/v1/business/**")
                .hasRole("ADMIN")
                .anyRequest()
                .authenticated();
    }  
}

該段代碼說明具備ADMIN角色的用戶能夠訪問/api/v1/business/ 下的全部的POST 請求 驗證以下: 在線製圖 springCloud設計

至此經過OAuth2.0保護微服務的基本作法已經完成。

2.2.4. 服務路由網關 服務網關:服務客戶端再也不直接調用服務。取而代之的是,服務網關做爲單個策略執行點(Policy Enforcement Point,PEP),全部調用都經過服務網關進行路由,而後被路由到最終目的地。 @EnabeZuulServer使用此註解將建立一個 Zuul 服務器,它不會加載任何 Zuul 反向代理過濾器,也不會使用 Netflix Eureka 進行服務發現.

成爲一個服務網關步驟: 一、 添加@EnableZuulProxy 在線製圖 springCloud設計 二、 在application.yml添加route 規則

zuul:
  sensitive-headers: set-cookies
  routes:
    business_service: /busi/**

經過postman測試以下:

在線製圖 springCloud設計

相關文章
相關標籤/搜索