1. 程式人生 > >Spring Cloud 服務治理框架 eureka使用記錄

Spring Cloud 服務治理框架 eureka使用記錄

微服務:微服務是一種架構風格,一個大型複雜軟體應用由一個或多個微服務組成。系統中的各個微服務可被獨立部署,各個微服務之間是鬆耦合的。每個微服務僅關注於完成一件任務並很好地完成該任務。在所有情況下,每個任務代表著一個小的業務能力。

服務治理:主要用來實現各個微服務例項的自動化註冊與發現

使用服務治理的原因:在服務引用並不算多的時候,可以通過靜態配置來完成服務的呼叫,但隨著業務的發展,系統功能越來越複雜,相應的微服務也不斷增加,此時靜態配置會變得越來越難以維護。並且面對不斷髮展的業務,叢集規模,服務的位置、服務的命名等都有可能發生變化,如果還是通過手工維護的方式,極易發生錯誤或是命名衝突等問題。同時,也將消耗大量的人力來維護靜態配置的內容。為了解決微服務架構中的服務例項維護問題,就產生了大量的服務治理框架和產品。這些框架和產品的實現都圍繞著服務註冊與服務發現機制來完成對微服務應用例項的自動化管理。

服務註冊:

  在服務治理框架中,通常都會構建一個註冊中心,每個服務單元向註冊中心登記自己提供的服務,將主機與埠號、版本號、通訊協議等一些附加資訊告知註冊中心,註冊中心按服務名分類組織服務清單。比如:有兩個提供服務A的程序分別運行於192.168.0.100:8000 和192.168.0.101:8000 位置上,還有三個提供服務B的程序分別運行於192.168.0.100:9000、192.168.0.101:9000、192.168.0.102:9000位置上。當這些程序都啟動,並向註冊中心註冊自己的服務之後,註冊中心就會維護類似下面的一個服務清單。另外,註冊中心還需要以心跳的方式去監測清單中的服務是否可用,若不可用需要從服務清單中剔除,達到排除故障服務的效果。

服務發現:

  在服務治理框架的運作下,服務間的呼叫不再通過指定具體的例項地址來實現,而是通過向服務名發起請求呼叫實現。所以,服務呼叫方在呼叫服務提供方介面時,並不知道具體的服務例項位置。因此,呼叫方需要向註冊中心諮詢服務,並獲取所有服務的例項清單,以實現對具體服務例項的訪問。比如:以上述服務為例,有服務C希望呼叫服務A,服務C就向註冊中心發起諮詢請求,服務註冊中心就會將服務A的位置清單返回給服務C,當服務C要發起呼叫時,便從該清單中以某種輪詢策略取出一個位置來進行服務呼叫(客戶端負載均衡)。

服務治理架構

pom檔案,在新建專案時,建立springboot專案自動建立,勾選spring eureka server

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

註冊中心

配置檔案

server.port=8761
#不去註冊中心註冊自己(自己就是服務中心)
eureka.client.register-with-eureka=false
#不去註冊中心抓取服務檔案(自己就是服務中心)
eureka.client.fetch-registry=false
#設定與Eureka Server互動地址。查詢服務和祖冊服務都需要依賴這個地址。預設是http://localhost:8761/eureka/
eureka.client.service-url.default-zone=http://localhost:8761/eureka/

 

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

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

服務提供者

server.port=63333
#Eureka服務名稱
spring.application.name=eureka-client-provider
#Eureka的註冊中心
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
eureka.instance.prefer-ip-address=true
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientApplication {

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

 

@RestController
public class providerController {
    @RequestMapping("/getUser")
    public String getUser(HttpServletRequest request) {

        return request.getParameter("key1")+request.getParameter("key2");
    }
}

服務消費者

server.port=63332
#Eureka服務名稱
spring.application.name=eureke-client-customer
#Eureka的註冊中心
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
eureka.instance.prefer-ip-address=true
@SpringBootApplication
@EnableEurekaClient
public class EurekeClientCustomerApplication {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(EurekeClientCustomerApplication.class, args);
    }
}
@Controller
public class customerController {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/router")
    @ResponseBody
    public String router() {
        StringBuilder buf = new StringBuilder();
        List<String> servicesIds=discoveryClient.getServices();
        if(!CollectionUtils.isEmpty(servicesIds)){
            for(String s : servicesIds){
                System.out.println("serviceId:" + s);
                List<ServiceInstance> serviceInstances =  discoveryClient.getInstances(s);
                if(!CollectionUtils.isEmpty(serviceInstances)){
                    for(ServiceInstance si:serviceInstances){
                        buf.append("["+si.getServiceId() +" host=" +si.getHost()+" port="+si.getPort()+" uri="+si.getUri()+"]");
                    }
                }else{
                    buf.append("no service.");
                }
            }
        }
        System.out.println(buf);
        //到註冊中心找服務並呼叫服務
        MultiValueMap<String,Object> requset=new LinkedMultiValueMap<String,Object>();
        requset.add("key1","one");
        requset.add("key2",new Integer(2));
        String json = restTemplate.postForObject("http://eureka-client-provider/getUser",requset,String.class);
        return json;
    }


}

檢視服務列表

 

 

後續研究eureka的高可用性

如果說只有一臺註冊中心,當它掛掉了之後,那麼所有服務呼叫都會出問題。

這裡我們為了實現高可用性,可以設定2臺或以上的服務中心。

這裡我在本機配了2個註冊中心玩了一下

eureka-server1配置檔案:
server.port=9091
spring.profiles.active=peer1
spring.application.name=eureka-server
#不去註冊中心註冊自己(自己就是服務中心)
eureka.client.register-with-eureka=true
#不去註冊中心抓取服務檔案(自己就是服務中心)
eureka.client.fetch-registry=true
#設定與Eureka Server互動地址。查詢服務和註冊服務都需要依賴這個地址。預設是http://localhost:8761/eureka/
eureka.client.service-url.defaultZone=http://peer1:9091/eureka/,http://peer2:9092/eureka/
eureka.instance.hostname=peer1
eureka.instance.prefer-ip-address=false

eureka-server2配置檔案:

server.port=9092
spring.profiles.active=peer2
spring.application.name=eureka-server
#不去註冊中心註冊自己(自己就是服務中心)
eureka.client.register-with-eureka=true
#不去註冊中心抓取服務檔案(自己就是服務中心)
eureka.client.fetch-registry=true
#設定與Eureka Server互動地址。查詢服務和祖冊服務都需要依賴這個地址。預設是http://localhost:8761/eureka/
eureka.client.service-url.defaultZone=http://peer2:9092/eureka/,http://peer1:9091/eureka/
eureka.instance.hostname=peer2
eureka.instance.prefer-ip-address=false

這裡eureka.client.fetch-registry=true表示可以從其他註冊中心拉去服務列表

這裡eureka.client.register-with-eureka=true,以我個人的理解是覺得可以設定成false,但不知道為什麼設定成false之後,另外的註冊中心就變成不可用了,也許是因為eureka想從其他服務中心拉取服務列表,則那個註冊中心必須註冊到本註冊中心

這裡有個坑,defaultZone這個屬性如果設定成default-zone,不會報錯,但是設定的註冊中心地址都不會生效,而使用了預設的http://localhost:8761/eureka/

這裡還需要在host檔案配置地址對映

127.0.0.1 peer1 
127.0.0.1 peer2

如果是不同機器上,在不同的機器上都需要配置

然後將兩個服務分別註冊到不同的註冊中心上

server.port=63332
#Eureka服務名稱
spring.application.name=eureka-client-customer
#Eureka的註冊中心
eureka.client.service-url.defaultZone=http://peer2:9092/eureka/
eureka.instance.prefer-ip-address=false
server.port=63333
#Eureka服務名稱
spring.application.name=eureka-client-provider
#Eureka的註冊中心
eureka.client.service-url.defaultZone=http://peer1:9091/eureka/
eureka.instance.prefer-ip-address=false

customer註冊到service2上

provider註冊到service1上

service1的服務列表

 這裡看到peer1從peer2上拉去了服務列表

這裡把peer2給關了,peer1上面的服務列表裡還是都存在

不過這裡最好服務最好在兩個註冊中心上都註冊,不然有可能是服務拉取失敗就g了,獲取被註冊中心清掉了