非springbootの従来のプロジェクトアクセスeureka登録とサービス発見を残す

20891 ワード

推奨:jeesuite開発フレームワーク、無料オープンソース、ワンストップソリューション.
最近、自動化メンテナンスと統一的な監視ニーズを計画しており、現在、社内の大部分のプロジェクトがspring cloudアーキテクチャを採用しているほか、古い伝統的なspring webのプロジェクトもあるため、古いプロジェクトを低コストで改造することでspring cloudシステムにアクセスすることを考えています.つまり、eureka登録とサービス発見、zulサービスルートを通じてアクセスすることができます.
やると言えばやるが、eurekaの公式例とspring boot登録eurekaソースコードを研究することでこれも実現しやすいことが分かったので、くだらないことは言わず、直接コードを貼りました.
まずプロジェクト依存性に参加する(mavenを例に挙げる)
<dependency>
    <groupId>com.netflix.eurekagroupId>
    <artifactId>eureka-clientartifactId>
    <version>1.4.12version>
    <exclusions>
        <exclusion>
          <groupId>javax.servletgroupId>
          <artifactId>servlet-apiartifactId>
        exclusion>
        <exclusion>
          <groupId>com.google.guavagroupId>
          <artifactId>guavaartifactId>
        exclusion>
        <exclusion>
          <groupId>com.fasterxml.jackson.coregroupId>
          <artifactId>jackson-annotationsartifactId>
        exclusion>
        <exclusion>
          <groupId>javax.ws.rsgroupId>
          <artifactId>jsr311-apiartifactId>
        exclusion>
    exclusions>
dependency>

    <dependency>
      <groupId>com.netflix.archaiusgroupId>
      <artifactId>archaius-coreartifactId>
      <version>0.7.4version>
      <exclusions>
        <exclusion>
          <groupId>com.fasterxml.jackson.coregroupId>
          <artifactId>jackson-annotationsartifactId>
        exclusion>
      exclusions>
    dependency>

    <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-netflix-coreartifactId>
      <version>1.2.6.RELEASEversion>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.bootgroupId>
          <artifactId>spring-boot-autoconfigureartifactId>
        exclusion>
      exclusions>
    dependency>

プロファイルの追加
eureka.region=default
eureka.registration.enabled=true
eureka.preferSameZone=true
eureka.shouldUseDns=false
eureka.serviceUrl.default=http://192.168.1.100:7861/eureka
eureka.decoderName=JacksonJson

eureka.name=demo
eureka.vipAddress=${eureka.name}-service
eureka.port=8081
eureka.homePageUrl=http://192.168.1.101:${eureka.port}
eureka.healthCheckUrl=http://192.168.1.101:${eureka.port}/service/health
eureka.statusPageUrl=http://192.168.1.101:${eureka.port}/service/info
  • spring.cloud.client.ipAddress:カスタム変数
  • healthCheckUrl、statusPageUrlインタフェースは不要ですが、監視のために自分で簡単なインタフェースを実現することができます
  • .
    eurekaクライアントの初期化
    private void initEurekaClient() throws Exception{
    
            Properties properties = new Properties();
    
            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("eureka.properties");
            properties.load(inputStream);
    
            //
            properties.setProperty("eureka.ipAddr", IpUtils.getLocalIpAddr());
            instanceId = properties.getProperty("eureka.ipAddr") + ":" + properties.getProperty("eureka.ipAddr") + "/" + properties.getProperty("eureka.name");
            properties.setProperty("eureka.instanceId", instanceId);
    
            ConfigurationManager.loadProperties(properties);
    
            MyDataCenterInstanceConfig instanceConfig = new MyDataCenterInstanceConfig();
            InstanceInfo instanceInfo = new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get();
            applicationInfoManager = new ApplicationInfoManager(instanceConfig, instanceInfo);
    
            DefaultEurekaClientConfig clientConfig = new DefaultEurekaClientConfig();
    
            eurekaClient = new DiscoveryClient(applicationInfoManager, clientConfig);
    
    }

    登録サービス
    private void waitForRegistrationWithEureka() {
    
            applicationInfoManager.setInstanceStatus(InstanceInfo.InstanceStatus.STARTING);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            applicationInfoManager.setInstanceStatus(InstanceInfo.InstanceStatus.UP);
    
            long startTime = System.currentTimeMillis();
            //            
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        if (System.currentTimeMillis() - startTime > VERIFY_WAIT_MILLIS) {
                            log.warn(" >>>> service registration status not verify,please check it!!!!");
                            return;
                        }
                        try {
                            List serverInfos = eurekaClient.getInstancesByVipAddress(vipAddress, false);
                            for (InstanceInfo nextServerInfo : serverInfos) {
                                if (nextServerInfo.getIPAddr().equals(IpUtils.LOCAL_BACK_IP)
                                        || nextServerInfo.getIPAddr().equals(IpUtils.getLocalIpAddr())) {
                                    String instanceInfoJson = JsonUtils.getMapper().writerWithDefaultPrettyPrinter()
                                            .writeValueAsString(nextServerInfo);
                                    log.info("verifying service registration with eureka finished,instance:
    {}"
    , instanceInfoJson); return; } } } catch (Throwable e) { } try { Thread.sleep(5000); } catch (Exception e1) { } log.info("Waiting 5s... verifying service registration with eureka ..."); } } }).start(); }

    このステップでeurekaの登録が完了し、eurekaコンソールにログインすると、対応する登録情報が表示されます.しかしzul転送呼び出しプロセスで問題が発見されました:hostnameを認識できません.もしあなたたちのサーバー間でhostname同期をしていなければ改造を続ける必要があります.そこでspringboot登録eurekaに構成項目eurekaがあるのを見ました.instance.preferIpAddressなので、私たちも彼の実現を真似することができます.クライアントを初期化するには、次のような改造が必要です.
    MyDataCenterInstanceConfig instanceConfig = new MyDataCenterInstanceConfig(){
                @Override
                public String getHostName(boolean refresh) {
                    String hostName = super.getHostName(refresh);
                    if(ResourceUtils.getBoolean("eureka.preferIpAddress")){
                        hostName = IpUtils.getLocalIpAddr();
                    }
                    return hostName;
                }
    
                @Override
                public String getIpAddress() {
                    return IpUtils.getLocalIpAddr();
                }
    
    };

    このように、登録された実際のサービスアドレスはipです.サービス登録が完了しました.
    次に、サービス発見と、他のspringbootプロジェクトと同様に登録センターvipAddressを通じて相互に呼び出されます.実際の手順は、vipAddress変数をeurekaが実際のアドレスに置き換える前に呼び出すことです.
    リアル・サービス・アドレスの取得
    public String getRealServerHost(String serviceId){
        InstanceInfo serverInfo = eurekaClient.getNextServerFromEureka(serviceId, false);
        String realServerName = serverInfo.getIPAddr() + ":" + serverInfo.getPort();
        return realServerName;
    }

    次は私が実現したいくつかのresttemplateです
    public class EurekaRestTemplateBuilder {
    
        private static Map restTemplates = new HashMap<>();
    
        public static synchronized RestTemplate build(ClientHttpRequestInterceptor ...interceptors ){
            return build("default", interceptors);
        }
    
        public static synchronized RestTemplate build(String name,ClientHttpRequestInterceptor ...interceptors ){
    
            if(restTemplates.containsKey(name))return restTemplates.get(name);
    
            SimpleClientHttpRequestFactory factory = new EurekaClientHttpRequestFactory();  
            factory.setReadTimeout(15000);//ms  
            factory.setConnectTimeout(5000);//ms 
    
            RestTemplate restTemplate = new RestTemplate(factory);
            List interceptorList = new ArrayList<>();
            interceptorList.add(new RestTemplateAutoHeaderInterceptor());
            if(interceptors != null && interceptors.length > 0){
                for (ClientHttpRequestInterceptor interceptor : interceptors) {
                    interceptorList.add(interceptor);
                }
            }
            restTemplate.setInterceptors(interceptorList);
            //
            restTemplate.setErrorHandler(new CustomResponseErrorHandler());
            //
            restTemplates.put(name, restTemplate);
    
            return restTemplate;
        }
    
        private static class EurekaClientHttpRequestFactory extends SimpleClientHttpRequestFactory{
    
            @Override
            public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
                uri = convertToRealUri(uri);
                return super.createRequest(uri, httpMethod);
            }
    
            @Override
            public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException {
                uri = convertToRealUri(uri);
                return super.createAsyncRequest(uri, httpMethod);
            }
    
            private URI convertToRealUri(URI uri){
                String serviceId = uri.getHost();
                try {               
                    String realHost = EurekaRegistry.getInstance().getRealServerHost(serviceId);
                    uri = new URI(uri.toString().replace(serviceId, realHost));
                    return uri;
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
    
        }
    }
    

    次に、他のeureka登録サービスを呼び出すことができます.
    private RestTemplate restTemplate = EurekaRestTemplateBuilder.build();
    
      public List getProvinces() {
        ParameterizedTypeReference<List> arearesponseType = new ParameterizedTypeReference<List>() {
        };
        List lists = restTemplate
            .exchange("http://DEMO-SERVICE/region/provinces", HttpMethod.GET, null, arearesponseType)
            .getBody();
        return lists;
      }

    ZUUL転送構成
    zuul.routes.demo.path=/demo/**
    zuul.routes.demo.serviceId=demo-service

    これで、サービス登録もサービス発見も完了しました.ここはdemoです
    何か問題があったら、技術グループを追加してください:230192763討論