SpringCloud學習之soa基礎


一、soa簡單介紹

  1)面向服務的架構(SOA)是一個組件模型,它將應用程序的不同功能單元(稱為服務)通過這些服務之間定義良好的接口和契約聯系起來。SOA是解決復雜業務模塊,提高擴展性,維護性,可伸縮性的最基本方案。我們的業務服務可以根據需求通過網絡對松散耦合的粗粒度應用組件進行分布式部署、組合和使用。服務層是SOA的基礎,可以直接被應用調用,不同的服務通過不同的團隊來維護。

  有效的業務分割是soa基礎中的基礎

  2)對於大型網站常見的架構模式:
    分層:便於維護,各個模塊之間有一定的獨立性,屬於橫向切分,常見的為三層架構
    分割:屬於縱向切分,當項目業務復雜,功能越來越多時,可以將業務功能進行拆分,常見的是拆分成項目,部署在不同的服務器上,每個模塊由獨立的團隊進行維護
    分布式:分割與分層一個主要目的就是將切分后的模塊進行分布式部署,分布式意味着使用更多機器完成相同的功能,機器多意味着cpu,內存也多,處理計算的能力與並發能力也就越大
    集群:集群為了使用更多的機器來處理相同的服務,用以提高性能。
  3)常用的分布式方案:
    分布式應用和服務:最常見的方式,即將不同的業務服務部署到不同的機器上
    分布式靜態資源:動靜分離。將css資源或者圖片獨立進行分布式部署
    分布式存儲:最常見的是數據庫分布式部署,來分割海量的數據
    分布式計算:比如說hadoop等大數據處理方案
  4)分布式帶來的問題:
    分布式意味着服務調用必須通過網絡,網絡帶寬的問題是服務之間調用必不可免的問題
    多台服務器會存在數據一致性的問題以及分布式事務問題
    服務器越多宕機的概率也就越大
    維護成本以及開發成本的增加

 

  5)注意分布式一定是根據需求及業務量而定的,切不可為了分布式而分布式
  6)注冊中心:管理服務地址,並提供調用者訪問的組件,常見的有zookeeper eureka redis等

 

二、soa基本架構圖(以spring-cloud為例)

1.注冊中心:    保存服務提供方暴露的服務信息,常見的注冊中心有zookeeper eureka

2.服務提供方:提供服務者

3.消費方:當需要調用遠程服務接口時,必須在注冊中心發現服務找到服務提供者,從而進行遠程方法調用

 

三、SpringCloud項目構建

  Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智能路由,微代理,控制總線)。使用Spring Cloud開發人員可以快速地支持實現這些模式的服務和應用程序。

1、通過訪問http://start.spring.io來構建spring-cloud項目

 

 注意:在Search for dependencies里添加最基本的soa依賴項: web EurekaServer Eureka Discovery

 

2、通過IDEA工具導入下載好的項目並依次創建一下幾個項目模塊:

這里說明一下:

  register-center:注冊中心

  service-api:接口契約

  service-provider:服務提供方

  service-consumer:服務消費方

 

四.實現步驟

1、實現注冊中心

  application.yml配置:  

server:
  port: 8000

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://localhost:8000/eureka/
View Code

   注意:在默認設置下,Eureka服務注冊中心也會將自己作為客戶端來嘗試注冊它自己,所以我們需要禁用它的客戶端注冊行為。

    register-with-eureka: 代表是否向eureka服務注冊

        fetch-registry: 是否從eureka注冊中心拉取信息 

    service-url:  eureka的服務地址

編寫程序入口類,通過@EnableEurekaServer 激活Eureka服務器相關配置:
package com.bdqn.springcloud.study.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class RegisterCenterProvider {

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

 

2 實現service-api

定義暴露服務的接口契約

package com.bdqn.springcloud.study.api;

import com.bdqn.springcloud.study.dto.UserDTO;

/**
 * UserService測試接口
 *
 * @author chen.nie
 * @date 2017/11/13
 */
public interface UserService {

    UserDTO findUser();


}
View Code

定義DTO

package com.bdqn.springcloud.study.dto;

public class UserDTO {

    private Integer id;

    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
View Code

 

3 實現服務提供方:

gradle配置:先依賴service-api

dependencies{
    compile project(":service-api")
}
View Code

application-yml的配置:

server:
  port: 8001

spring:
  application:
    name: "service-provider-demo"
eureka:
  instance:
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka/
View Code

注意:這里面要配置應用名稱 注冊中心的服務地址

接口實現類:

package com.bdqn.springcloud.study.provider.impl;


import com.bdqn.springcloud.study.api.UserService;
import com.bdqn.springcloud.study.dto.UserDTO;
import org.springframework.stereotype.Service;

@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public UserDTO findUser() {
        UserDTO userDTO = new UserDTO();
        userDTO.setName("張三豐");
        userDTO.setId(10);
        return userDTO;
    }
}
View Code

Controller:

package com.bdqn.springcloud.study.provider.controller;


import com.bdqn.springcloud.study.api.UserService;
import com.bdqn.springcloud.study.dto.UserDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class UserController {
    @Resource
    private UserService userService;

    @GetMapping("/user")
    public UserDTO getUser() {
        return this.userService.findUser();
    }
}
View Code

啟動類:

package com.bdqn.springcloud.study.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class ServiceProvider {

    public static void main(String[] args) {

        SpringApplication.run(ServiceProvider.class, args);
    }
}
View Code
@EnableDiscoveryClient:用於啟用發現客戶端實現的注釋

打來瀏覽器訪問:http://localhost:8000

我們看到剛才的接口服務已經成功注冊至Eureka中心


4.實現服務消費方

gradle配置:先依賴service-api
dependencies{
    compile project(":service-api")
    compile 'org.springframework.cloud:spring-cloud-starter-eureka'
}
View Code

  application.yml配置:

server:
  port: 8002

spring:
  application:
    name: "service-consumer-demo"
eureka:
  instance:
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka/
View Code

  編寫Controller:

package com.bdqn.springcloud.study.consumer.controller;


import com.bdqn.springcloud.study.dto.UserDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @GetMapping("/getUser")
    public String getUser() {
        ResponseEntity<UserDTO> responseEntity = restTemplate.getForEntity("http://SERVICE-PROVIDER-DEMO/user", UserDTO.class);
        UserDTO userDTO = responseEntity.getBody();
        return userDTO.getName();
    }
}
View Code

注意我們通過http://service-provider-demo/user/ 指定service-provider的application name,讓系統從注冊中心去發現服務。

5.編寫啟動項:

package com.bdqn.springcloud.study.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceConsumer {
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

  在啟動項里,我們配置了一個RestTemplate 主意 @LoadBalanced注解修飾的restTemplate,具備負載均衡能力的restTemplate,即每次都會用負載均衡算法,從可用服務列表中,挑一個進行調用。

啟動完畢時,我們發現注冊中心中多了一個服務:

 

當我們訪問http://localhost:8002/getUser得到如下顯示就說明我們的服務運行成功了:

 當停止register-center時,我們發現該訪問地址依然能夠拿到結果,說明消費端本地是有緩存的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM