追梦人物

追梦人物 查看完整档案

成都编辑  |  填写毕业院校  |  填写所在公司/组织编辑
编辑

个人博客:http://zmrenwu.com/

个人动态

追梦人物 赞了回答 · 2018-10-08

Pandas 如何对无法一次性载入内存的大数据量去重?

key:每一行的MD5
value:行号

可以借助redis,用hash结构,存进去的都是不重复的,然后根据行号再组织数据。

关注 7 回答 5

追梦人物 提出了问题 · 2018-10-08

gradle + jetty + Spring MVC无法启动项目

目前正在看 《Spring in action》第四版,想跟着书中第五章开始的实战项目做一下,但在使用 gradle 和 jetty 启动项目时遇到了一些问题。

代码基本抄书上的,贴几个关键的配置文件:

这是 sevelet 的配置文件

package spittr.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import spittr.web.WebConfig;

public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{RootConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}

这是根配置文件:

package spittr.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan(
        basePackages = {"spittr"},
        excludeFilters = {
                @Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)
        })
public class RootConfig {
}

注意全部使用基于java的配置,没有 xml 文件。

jsp代码如下:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
    <title>Spitter</title>
    <link rel="stylesheet"
          type="text/css"
          href="<c:url value="/resources/style.css" />">
</head>
<body>
<h1>Welcome to Spitter</h1>

<a href="<c:url value="/spittles" />">Spittles</a> |
<a href="<c:url value="/spitter/register" />">Register</a>
</body>
</html>

build.gradle 如下:

apply plugin: 'war'
apply plugin: 'idea'
apply plugin: 'java'
apply from: 'gretty.plugin'

dependencies {
    compile "org.springframework:spring-webmvc:4.0.7.RELEASE"
    compile "javax.servlet:jstl:1.2"
//    providedCompile "javax.servlet.jsp:jsp-api:2.1"
//    providedCompile "javax.el:javax.el-api:2.2.4"
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    maven { url 'http://maven.springframework.org/release' }
    maven { url 'http://maven.springframework.org/milestone' }
    maven { url 'http://maven.springframework.org/snapshot' }
    maven { url 'http://download.java.net/maven/2' }
    mavenCentral()

}

war {
    baseName = 'spittr'
    version = '0.1.0'
}

当我运行 gradle appRun 命令启动服务器时,得到如下的信息:

YangdeMBP:Spittr yangxg$ ./gradlew appRun
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (file:/Users/yangxg/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.4.15/74b7e0b99526c569e3a59cb84dbcc6204d601ee6/groovy-2.4.15.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
18:17:47 INFO  Spring WebApplicationInitializers detected on classpath: [spittr.config.SpitterWebInitializer@760cf594]
18:17:47 INFO  Initializing Spring root WebApplicationContext
10月 08, 2018 6:17:47 下午 org.springframework.web.context.ContextLoader initWebApplicationContext
信息: Root WebApplicationContext: initialization started
10月 08, 2018 6:17:48 下午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext prepareRefresh
信息: Refreshing Root WebApplicationContext: startup date [Mon Oct 08 18:17:48 CST 2018]; root of context hierarchy
10月 08, 2018 6:17:48 下午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions
信息: Registering annotated classes: [class spittr.config.RootConfig]
10月 08, 2018 6:17:48 下午 org.springframework.web.context.ContextLoader initWebApplicationContext
信息: Root WebApplicationContext: initialization completed in 301 ms
18:17:48 INFO  Initializing Spring FrameworkServlet 'dispatcher'
10月 08, 2018 6:17:48 下午 org.springframework.web.servlet.DispatcherServlet initServletBean
信息: FrameworkServlet 'dispatcher': initialization started
10月 08, 2018 6:17:48 下午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext prepareRefresh
信息: Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Mon Oct 08 18:17:48 CST 2018]; parent: Root WebApplicationContext
10月 08, 2018 6:17:48 下午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions
信息: Registering annotated classes: [class spittr.web.WebConfig]
10月 08, 2018 6:17:48 下午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping registerHandlerMethod
信息: Mapped "{[/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String spittr.web.HomeController.home()
10月 08, 2018 6:17:48 下午 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping registerHandler
信息: Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
10月 08, 2018 6:17:48 下午 org.springframework.web.servlet.DispatcherServlet initServletBean
信息: FrameworkServlet 'dispatcher': initialization completed in 510 ms
18:17:48 INFO  Jetty 9.2.24.v20180105 started and listening on port 8080
18:17:48 INFO  Spittr runs at:
18:17:48 INFO    http://localhost:8080/Spittr

> Task :appRun
Press any key to stop the server.
<===========--> 87% EXECUTING [35s]
> :appRun

比较奇怪的一个地方是进度指示器卡在 87% 不在动,访问 http://localhost:8080/Spittr 时报错信息如下:

org.apache.jasper.JasperException: /WEB-INF/views/home.jsp(1,63) PWC6188: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
    at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:92)
    at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:378)
    at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:172)
    at org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation(TagLibraryInfoImpl.java:431)
    at org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:240)
    at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:502)
    at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:582)
    at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1657)
    at org.apache.jasper.compiler.Parser.parse(Parser.java:185)
    at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
    at org.apache.jasper.compiler.ParserController.parse(ParserController.java:145)
    at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:212)
    at org.apache.jasper.compiler.Compiler.compile(Compiler.java:451)
    at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:625)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:375)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377)
    at org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:103)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:595)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:191)
    at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:72)
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:267)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1221)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1005)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:952)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
    at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:201)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:499)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.base/java.lang.Thread.run(Thread.java:844)

但显然 gradle 在 build 项目时已经为我安装了 jstl 1.2,这是为什么呢?

关注 2 回答 0

追梦人物 提出了问题 · 2018-07-13

FastDFS同一组内的文件不同步

我在 5 台服务器上部署了一个 fastdfs 文件集群,分配如下:

tracker1:117.48.231.77
tracker2:117.48.231.99

[group1]
117.48.231.94
117.48.231.88

[group2]
117.48.231.84

可以上传文件到两个group的storage里。
但现在的问题是,如果传文件到[group1],集群只会把文件传到117.48.231.88,而117.48.231.94的文件不会同步,集群也不会传文件到117.48.231.94。但按照 fastdfs 上传文件的机制,[group1]中的storage应该都有机会被选中,而文件上传后两台存储的文件应该自动同步。

相关的日志如下:

[2018-07-13 09:09:53] DEBUG - base_path=/fastdfs/storage, connect_timeout=30, network_timeout=60, tracker_server_count=2, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0

server_count=2, server_index=0

tracker server is 117.48.231.77:22122

group count: 2

Group 1:
group name = group1
disk total space = 40252 MB
disk free space = 36654 MB
trunk free space = 0 MB
storage server count = 2
active server count = 2
storage server port = 23000
storage HTTP port = 8888
store path count = 1
subdir count per path = 256
current write server index = 0
current trunk file id = 0

    Storage 1:
        id = 117.48.231.88
        ip_addr = 117.48.231.88  ACTIVE
        http domain = 
        version = 5.05
        join time = 2018-07-12 14:33:29
        up time = 2018-07-13 08:40:09
        total storage = 40252 MB
        free storage = 36654 MB
        upload priority = 10
        store_path_count = 1
        subdir_count_per_path = 256
        storage_port = 23000
        storage_http_port = 8888
        current_write_path = 0
        source storage id = 
        if_trunk_server = 0
        connection.alloc_count = 256
        connection.current_count = 2
        connection.max_count = 2
        total_upload_count = 9
        success_upload_count = 9
        total_append_count = 0
        success_append_count = 0
        total_modify_count = 0
        success_modify_count = 0
        total_truncate_count = 0
        success_truncate_count = 0
        total_set_meta_count = 0
        success_set_meta_count = 0
        total_delete_count = 0
        success_delete_count = 0
        total_download_count = 0
        success_download_count = 0
        total_get_meta_count = 0
        success_get_meta_count = 0
        total_create_link_count = 0
        success_create_link_count = 0
        total_delete_link_count = 0
        success_delete_link_count = 0
        total_upload_bytes = 1478178
        success_upload_bytes = 1478178
        total_append_bytes = 0
        success_append_bytes = 0
        total_modify_bytes = 0
        success_modify_bytes = 0
        stotal_download_bytes = 0
        success_download_bytes = 0
        total_sync_in_bytes = 165052
        success_sync_in_bytes = 0
        total_sync_out_bytes = 0
        success_sync_out_bytes = 0
        total_file_open_count = 9
        success_file_open_count = 9
        total_file_read_count = 0
        success_file_read_count = 0
        total_file_write_count = 9
        success_file_write_count = 9
        last_heart_beat_time = 2018-07-13 09:09:24
        last_source_update = 2018-07-12 17:01:48
        last_sync_update = 2018-07-12 17:01:53
        last_synced_timestamp = 1970-01-01 08:00:00 
    Storage 2:
        id = 117.48.231.94
        ip_addr = 117.48.231.94  ACTIVE
        http domain = 
        version = 5.05
        join time = 2018-07-12 17:23:33
        up time = 2018-07-13 08:40:09
        total storage = 40252 MB
        free storage = 36656 MB
        upload priority = 10
        store_path_count = 1
        subdir_count_per_path = 256
        storage_port = 23000
        storage_http_port = 8888
        current_write_path = 0
        source storage id = 117.48.231.88
        if_trunk_server = 0
        connection.alloc_count = 256
        connection.current_count = 2
        connection.max_count = 2
        total_upload_count = 0
        success_upload_count = 0
        total_append_count = 0
        success_append_count = 0
        total_modify_count = 0
        success_modify_count = 0
        total_truncate_count = 0
        success_truncate_count = 0
        total_set_meta_count = 0
        success_set_meta_count = 0
        total_delete_count = 0
        success_delete_count = 0
        total_download_count = 0
        success_download_count = 0
        total_get_meta_count = 0
        success_get_meta_count = 0
        total_create_link_count = 0
        success_create_link_count = 0
        total_delete_link_count = 0
        success_delete_link_count = 0
        total_upload_bytes = 0
        success_upload_bytes = 0
        total_append_bytes = 0
        success_append_bytes = 0
        total_modify_bytes = 0
        success_modify_bytes = 0
        stotal_download_bytes = 0
        success_download_bytes = 0
        total_sync_in_bytes = 0
        success_sync_in_bytes = 0
        total_sync_out_bytes = 0
        success_sync_out_bytes = 0
        total_file_open_count = 0
        success_file_open_count = 0
        total_file_read_count = 0
        success_file_read_count = 0
        total_file_write_count = 0
        success_file_write_count = 0
        last_heart_beat_time = 2018-07-13 09:09:26
        last_source_update = 1970-01-01 08:00:00
        last_sync_update = 1970-01-01 08:00:00
        last_synced_timestamp = 1970-01-01 08:00:00 (never synced)

Group 2:
group name = group2
disk total space = 40252 MB
disk free space = 36603 MB
trunk free space = 0 MB
storage server count = 1
active server count = 1
storage server port = 23000
storage HTTP port = 8888
store path count = 1
subdir count per path = 256
current write server index = 0
current trunk file id = 0

    Storage 1:
        id = 117.48.231.84
        ip_addr = 117.48.231.84  ACTIVE
        http domain = 
        version = 5.05
        join time = 2018-07-12 14:33:30
        up time = 2018-07-13 08:40:09
        total storage = 40252 MB
        free storage = 36603 MB
        upload priority = 10
        store_path_count = 1
        subdir_count_per_path = 256
        storage_port = 23000
        storage_http_port = 8888
        current_write_path = 0
        source storage id = 
        if_trunk_server = 0
        connection.alloc_count = 256
        connection.current_count = 1
        connection.max_count = 1
        total_upload_count = 8
        success_upload_count = 8
        total_append_count = 0
        success_append_count = 0
        total_modify_count = 0
        success_modify_count = 0
        total_truncate_count = 0
        success_truncate_count = 0
        total_set_meta_count = 0
        success_set_meta_count = 0
        total_delete_count = 0
        success_delete_count = 0
        total_download_count = 0
        success_download_count = 0
        total_get_meta_count = 0
        success_get_meta_count = 0
        total_create_link_count = 0
        success_create_link_count = 0
        total_delete_link_count = 0
        success_delete_link_count = 0
        total_upload_bytes = 1313936
        success_upload_bytes = 1313936
        total_append_bytes = 0
        success_append_bytes = 0
        total_modify_bytes = 0
        success_modify_bytes = 0
        stotal_download_bytes = 0
        success_download_bytes = 0
        total_sync_in_bytes = 164962
        success_sync_in_bytes = 0
        total_sync_out_bytes = 0
        success_sync_out_bytes = 0
        total_file_open_count = 8
        success_file_open_count = 8
        total_file_read_count = 0
        success_file_read_count = 0
        total_file_write_count = 8
        success_file_write_count = 8
        last_heart_beat_time = 2018-07-13 09:09:24
        last_source_update = 2018-07-12 17:01:49
        last_sync_update = 2018-07-12 17:01:53
        last_synced_timestamp = 1970-01-01 08:00:00 

group1 两台存储器的日志:

[2018-07-13 08:48:09] ERROR - file: storage_ip_changed_dealer.c, line: 180, connect to tracker server 117.48.231.99:22122 fail, errno: 111, error info: Connection refused
[2018-07-13 08:48:24] INFO - file: storage_param_getter.c, line: 191, use_storage_id=0, id_type_in_filename=ip, storage_ip_changed_auto_adjust=1, store_path=0, reserved_storage_space=10.00%, use_trunk_file=0, slot_min_size=256, slot_max_size=16 MB, trunk_file_size=64 MB, trunk_create_file_advance=0, trunk_create_file_time_base=02:00, trunk_create_file_interval=86400, trunk_create_file_space_threshold=20 GB, trunk_init_check_occupying=0, trunk_init_reload_from_binlog=0, trunk_compress_binlog_min_interval=0, store_slave_file_use_link=0
[2018-07-13 08:48:24] INFO - file: storage_func.c, line: 254, tracker_client_ip: 192.168.0.3, my_server_id_str: 192.168.0.3, g_server_id_in_filename: 50374848
[2018-07-13 08:48:24] ERROR - file: tracker_proto.c, line: 48, server: 117.48.231.77:22122, response status 2 != 0
[2018-07-13 08:48:24] ERROR - file: tracker_proto.c, line: 48, server: 117.48.231.99:22122, response status 2 != 0
[2018-07-13 08:48:24] INFO - local_host_ip_count: 2,  127.0.0.1  192.168.0.3
[2018-07-13 08:48:24] INFO - file: tracker_client_thread.c, line: 310, successfully connect to tracker server 117.48.231.77:22122, as a tracker client, my ip is 192.168.0.3
[2018-07-13 08:48:24] INFO - file: tracker_client_thread.c, line: 310, successfully connect to tracker server 117.48.231.99:22122, as a tracker client, my ip is 192.168.0.3
[2018-07-13 08:48:24] INFO - file: storage_sync.c, line: 2698, successfully connect to storage server 117.48.231.88:23000
[2018-07-13 08:48:24] INFO - file: storage_sync.c, line: 2698, successfully connect to storage server 117.48.231.94:23000
[2018-07-13 08:48:09] ERROR - file: storage_ip_changed_dealer.c, line: 180, connect to tracker server 117.48.231.99:22122 fail, errno: 111, error info: Connection refused
[2018-07-13 08:48:24] INFO - file: storage_param_getter.c, line: 191, use_storage_id=0, id_type_in_filename=ip, storage_ip_changed_auto_adjust=1, store_path=0, reserved_storage_space=10.00%, use_trunk_file=0, slot_min_size=256, slot_max_size=16 MB, trunk_file_size=64 MB, trunk_create_file_advance=0, trunk_create_file_time_base=02:00, trunk_create_file_interval=86400, trunk_create_file_space_threshold=20 GB, trunk_init_check_occupying=0, trunk_init_reload_from_binlog=0, trunk_compress_binlog_min_interval=0, store_slave_file_use_link=0
[2018-07-13 08:48:24] INFO - file: storage_func.c, line: 254, tracker_client_ip: 192.168.0.3, my_server_id_str: 192.168.0.3, g_server_id_in_filename: 50374848
[2018-07-13 08:48:24] ERROR - file: tracker_proto.c, line: 48, server: 117.48.231.77:22122, response status 2 != 0
[2018-07-13 08:48:24] ERROR - file: tracker_proto.c, line: 48, server: 117.48.231.99:22122, response status 2 != 0
[2018-07-13 08:48:24] INFO - local_host_ip_count: 2,  127.0.0.1  192.168.0.3
[2018-07-13 08:48:24] INFO - file: tracker_client_thread.c, line: 310, successfully connect to tracker server 117.48.231.77:22122, as a tracker client, my ip is 192.168.0.3
[2018-07-13 08:48:24] INFO - file: tracker_client_thread.c, line: 310, successfully connect to tracker server 117.48.231.99:22122, as a tracker client, my ip is 192.168.0.3
[2018-07-13 08:48:24] INFO - file: storage_sync.c, line: 2698, successfully connect to storage server 117.48.231.88:23000
[2018-07-13 08:48:55] INFO - file: storage_sync.c, line: 2698, successfully connect to storage server 117.48.231.94:23000

两台 tracker 的日志

[2018-07-13 09:14:37] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:14:41] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:14:44] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:14:48] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:14:52] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:14:53] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:15:01] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:15:11] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:15:14] INFO - file: tracker_relationship.c, line: 383, selecting leader...
[2018-07-13 09:15:19] INFO - file: tracker_relationship.c, line: 383, selecting leader...

关注 1 回答 0

追梦人物 收藏了文章 · 2018-04-10

Vue 2.0前端生产环境发布配置实战篇

前言

首先这篇文章是写给Vue 2.0新手的,老司机基本不用看了。

当我们刚接触vue的时候,特别是对于第一次用前端框架的同学来说,心情可以说是比较激动的,框架带来的种种新体验,是以前jQuery无法给你的兴奋和满足感。但是在体验了几个demo的新鲜感之后,我们就要考虑如何把框架结合到我们实际的开发中如何应用的问题了。

下面我主要总结三个和生产发布相关的问题:资源文件发布文件夹配置,图片文件的引用,以及后台接口调试方法。

一,资源文件发布配置

一般项目都是用vue-cli脚手架搭建项目,然后编写自己的代码。vue-cli脚手架生成的配置,默认资源文件都在static文件夹下面,build发布的js和css文件也是在static文件夹下面,index.html文件则是和static形成相对路径关系。

而实际我们的生产发布环境中,页面文件和资源文件不一定在同一目录下,页面文件和js,css文件也不在同一目录下。

以php的Yii2环境为例,页面文件一般都放在views文件夹,页面访问路径可能是 “http://xxxx.com/index.php/sal...” 这样的url形式。而js,css,image等资源文件则需要放在web文件夹下,访问路径则是从根目录开始访问的。如果在web目录下新建static文件夹,访问路径是 “http://xxxx.com/static/images...” 这样的url形式。实际开发中我们不能把所有项目资源文件都放在web目录下的static文件夹,需要按项目新建不同的文件夹,在每个项目文件夹里再新建js,css,images等文件夹来安放各自的资源文件,访问路径应该是 “http://xxxx.com/sales-task/im...” 这样的url形式。

因此修改配置文件如下:

  1. 把vue项目下的static文件夹名称改成项目名称,名称由小写英文字母,横杠连接符“-”,数字组成,例如sales-task。
  2. 修改config/index.js,把dev和build属性里的assetsSubDirectorys的值都改成项目名称,例如sales-task。build的assetsPublicPath值改成“/”,这样所有资源文件的引用都从根目录引用,避免相对路径错误。
  3. 修改build/webpack.dev.conf.js,把plugins的new CopyWebpackPlugin那里的from: path.resolve(__dirname, '../static'),改为from: path.resolve(__dirname, '../sales-task')。
  4. build/webpack.prod.conf.js里也做同样的修改。
  5. 上线前发布最终线上文件时,config/index.js里的build设置属性productionSourceMap: false,同时注释掉devtool: '#source-map',以避免产生.map映射文件。正式上线前这个还是要保留的,否则调试代码会很不方便。

二,图片文件的引用方式

vue项目中有2种图片引用方式,一种是静态引用,按照我们上面的资源文件夹配置,图片路径直接写到template的html代码里,格式示例:

<img data-original="/sales-task/images/logo.png">

这样在开发模式和发布模式下都能正常引用到图片,好处是和正常html代码格式一样,方便代码的编写和修改。缺点是图片文件地址是静态的,替换图片后如果不手动更换文件名无法解决缓存问题。

另一种方法就是更科学的模块化方式,用require引用图片,这样发布后图片文件名也会生成唯一识别码,图片修改后就会重新生成不同的文件名,从而能避免缓存问题,另外小图片还可以直接生成base64码,减少文件请求。require引用也有两种形式,直接写在:src属性上(注意这里和静态引用不一样,不是src而是:src了):

<img :data-original="require('../assets/images/logo.png')">

或者把图片引用数据写在data绑定数据里:

<img :data-original="logoImg">
...
<script>
export default
  {
    data()
    {
      return {
        logoImg:require('../assets/images/logo.png')
      }
    }
  }
</script>

当然我还是推荐绑定数据的方法,代码看起来更清爽,也便于维护。

另外需要说明的是在vue的<style></style>块内的样式里定义的background-image引用图片不需要require引用,直接通过相对路径引入就可以实现上面相同的效果。

三,后台接口调试方法

这里后台接口调试指的是在开发模式下的调试。

vue的开发模式是通过webpack-dev-server启动一个本地服务,所以在开发模式下调用后台接口就产生了跨域问题。这里要说明一下,如果要调用的后台接口本身就是跨域的接口,也就是说页面和接口文件不在同一个域名下,跨域问题需要在后端设置,这时其实vue项目不需要特殊配置了,因为本地访问和发布后访问都是跨域的,解决后端跨域就都解决了。所以我们这里要配置的,还是针对发布以后页面和接口不存在跨越问题,只是开发模式下本地服务和接口产生的跨越问题,如何解决。

首先还是打开config/index.js,找到module.exports里的dev,里面有一项proxyTable,默认是空的,我们要按照我们的接口路径,修改如下:

    proxyTable: {
        '/sales-task-api':{
            target:"http://xxxxx.com/sales-task-api",
            changeOrigin:true,
            pathRewrite: {"^/sales-task-api" : "/"} 
        }
    }

注意上面3个地方的接口路径名称(示例中的"sales-task-api")要保持一致。
例如实际要调用的接口地址是:http://xxxxx.com/sales-task-a... ,经过这样配置设置后,我们在vue中就可以通过 "/sales-task-api/get-user-list" 这样的地址调用,也不会产生跨域问题。同时因为是采用的根目录访问路径,在生产发布以后也不会产生接口访问路径错误问题。

查看原文

追梦人物 赞了文章 · 2018-04-10

Vue 2.0前端生产环境发布配置实战篇

前言

首先这篇文章是写给Vue 2.0新手的,老司机基本不用看了。

当我们刚接触vue的时候,特别是对于第一次用前端框架的同学来说,心情可以说是比较激动的,框架带来的种种新体验,是以前jQuery无法给你的兴奋和满足感。但是在体验了几个demo的新鲜感之后,我们就要考虑如何把框架结合到我们实际的开发中如何应用的问题了。

下面我主要总结三个和生产发布相关的问题:资源文件发布文件夹配置,图片文件的引用,以及后台接口调试方法。

一,资源文件发布配置

一般项目都是用vue-cli脚手架搭建项目,然后编写自己的代码。vue-cli脚手架生成的配置,默认资源文件都在static文件夹下面,build发布的js和css文件也是在static文件夹下面,index.html文件则是和static形成相对路径关系。

而实际我们的生产发布环境中,页面文件和资源文件不一定在同一目录下,页面文件和js,css文件也不在同一目录下。

以php的Yii2环境为例,页面文件一般都放在views文件夹,页面访问路径可能是 “http://xxxx.com/index.php/sal...” 这样的url形式。而js,css,image等资源文件则需要放在web文件夹下,访问路径则是从根目录开始访问的。如果在web目录下新建static文件夹,访问路径是 “http://xxxx.com/static/images...” 这样的url形式。实际开发中我们不能把所有项目资源文件都放在web目录下的static文件夹,需要按项目新建不同的文件夹,在每个项目文件夹里再新建js,css,images等文件夹来安放各自的资源文件,访问路径应该是 “http://xxxx.com/sales-task/im...” 这样的url形式。

因此修改配置文件如下:

  1. 把vue项目下的static文件夹名称改成项目名称,名称由小写英文字母,横杠连接符“-”,数字组成,例如sales-task。
  2. 修改config/index.js,把dev和build属性里的assetsSubDirectorys的值都改成项目名称,例如sales-task。build的assetsPublicPath值改成“/”,这样所有资源文件的引用都从根目录引用,避免相对路径错误。
  3. 修改build/webpack.dev.conf.js,把plugins的new CopyWebpackPlugin那里的from: path.resolve(__dirname, '../static'),改为from: path.resolve(__dirname, '../sales-task')。
  4. build/webpack.prod.conf.js里也做同样的修改。
  5. 上线前发布最终线上文件时,config/index.js里的build设置属性productionSourceMap: false,同时注释掉devtool: '#source-map',以避免产生.map映射文件。正式上线前这个还是要保留的,否则调试代码会很不方便。

二,图片文件的引用方式

vue项目中有2种图片引用方式,一种是静态引用,按照我们上面的资源文件夹配置,图片路径直接写到template的html代码里,格式示例:

<img data-original="/sales-task/images/logo.png">

这样在开发模式和发布模式下都能正常引用到图片,好处是和正常html代码格式一样,方便代码的编写和修改。缺点是图片文件地址是静态的,替换图片后如果不手动更换文件名无法解决缓存问题。

另一种方法就是更科学的模块化方式,用require引用图片,这样发布后图片文件名也会生成唯一识别码,图片修改后就会重新生成不同的文件名,从而能避免缓存问题,另外小图片还可以直接生成base64码,减少文件请求。require引用也有两种形式,直接写在:src属性上(注意这里和静态引用不一样,不是src而是:src了):

<img :data-original="require('../assets/images/logo.png')">

或者把图片引用数据写在data绑定数据里:

<img :data-original="logoImg">
...
<script>
export default
  {
    data()
    {
      return {
        logoImg:require('../assets/images/logo.png')
      }
    }
  }
</script>

当然我还是推荐绑定数据的方法,代码看起来更清爽,也便于维护。

另外需要说明的是在vue的<style></style>块内的样式里定义的background-image引用图片不需要require引用,直接通过相对路径引入就可以实现上面相同的效果。

三,后台接口调试方法

这里后台接口调试指的是在开发模式下的调试。

vue的开发模式是通过webpack-dev-server启动一个本地服务,所以在开发模式下调用后台接口就产生了跨域问题。这里要说明一下,如果要调用的后台接口本身就是跨域的接口,也就是说页面和接口文件不在同一个域名下,跨域问题需要在后端设置,这时其实vue项目不需要特殊配置了,因为本地访问和发布后访问都是跨域的,解决后端跨域就都解决了。所以我们这里要配置的,还是针对发布以后页面和接口不存在跨越问题,只是开发模式下本地服务和接口产生的跨越问题,如何解决。

首先还是打开config/index.js,找到module.exports里的dev,里面有一项proxyTable,默认是空的,我们要按照我们的接口路径,修改如下:

    proxyTable: {
        '/sales-task-api':{
            target:"http://xxxxx.com/sales-task-api",
            changeOrigin:true,
            pathRewrite: {"^/sales-task-api" : "/"} 
        }
    }

注意上面3个地方的接口路径名称(示例中的"sales-task-api")要保持一致。
例如实际要调用的接口地址是:http://xxxxx.com/sales-task-a... ,经过这样配置设置后,我们在vue中就可以通过 "/sales-task-api/get-user-list" 这样的地址调用,也不会产生跨域问题。同时因为是采用的根目录访问路径,在生产发布以后也不会产生接口访问路径错误问题。

查看原文

赞 5 收藏 8 评论 0

追梦人物 收藏了文章 · 2018-04-09

webpack多页应用架构系列(一):一步一步解决架构痛点

本文首发于Array_Huang的技术博客——实用至上,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006843916
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang

这系列文章讲什么?

本系列文章主要介绍如何用webpack这一当前流行的构建工具来设计一个多页应用的架构。请注意,本文并非新手教程,着重点更多是在于提供解决问题的思路,而非手把手带你装逼。

作者介绍

本人供职于某互联网物流公司,专职前端,公司虽仍处于创业阶段,但产品线已经拉得挺长的了,因此所碰到的痒点、痛点也不少。我本是PHPer出身,对传统前端茹毛饮血的境况恨之入骨,幸得webpack这一神器,我感觉现在写前端已经跟写PHP差不多了(大误)。

示例代码

诸位看本系列文章,搭配我的脚手架项目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)
上个文件目录结构让大家一睹为快:

├─build # 编译后生成的所有代码、资源(图片、字体等,虽然只是简单的从源目录迁移过来)
├─node_modules # 利用npm管理的所有包及其依赖
├─vendor # 所有不能用npm管理的第三方库
├─.babelrc # babel的配置文件
├─.eslintrc # ESLint的配置文件
├─index.html # 仅作为重定向使用
├─package.json # npm的配置文件
├─webpack.config.js # webpack的配置文件
├─src # 当前项目的源码
    ├─pages # 各个页面独有的部分,如入口文件、只有该页面使用到的css、模板文件等
    │  ├─alert # 业务模块
    │  │  └─index # 具体页面
    │  ├─index # 业务模块
    │  │  ├─index # 具体页面
    │  │  └─login # 具体页面
    │  │      └─templates # 如果一个页面的HTML比较复杂,可以分成多块再拼在一起
    │  └─user # 业务模块
    │      ├─edit-password # 具体页面
    │      └─modify-info # 具体页面
    └─public-resource # 各个页面使用到的公共资源
        ├─components # 组件,可以是纯HTML,也可以包含js/css/image等,看自己需要
        │  ├─footer # 页尾
        │  ├─header # 页头
        │  ├─side-menu # 侧边栏
        │  └─top-nav # 顶部菜单
        ├─config # 各种配置文件
        ├─iconfont # iconfont的字体文件
        ├─imgs # 公用的图片资源
        ├─layout # UI布局,组织各个组件拼起来,因应需要可以有不同的布局套路
        │  ├─layout # 具体的布局套路
        │  └─layout-without-nav # 具体的布局套路
        ├─less # less文件,用sass的也可以,又或者是纯css
        │  ├─base-dir
        │  ├─components-dir # 如果组件本身不需要js的,那么要加载组件的css比较困难,我建议可以直接用less来加载
        │  └─base.less # 组织所有的less文件
        ├─libs # 与业务逻辑无关的库都可以放到这里
        └─logic # 业务逻辑

架构痛点痒点一览(并非系列文章的所有内容)

  • SPA好复杂,我还是喜欢传统的多页应用怎么破?又或是,我司项目需要后端渲染,页面模板怎么出?
  • 每个页面相同的UI布局好难维护,UI稍微改一点就要到每个页面去改,好麻烦还容易漏,怎么破?
  • 除js外的资源如css/less、图片、swf、字体等,要怎么打包呢?不然老是要外部引用,迁移、部署起来都好麻烦呢。
  • 某些年久失修的jQuery插件怎么在webpack里使用呢?
  • 能不能整合进ESLint来检查语法?
  • 能不能整合postcss来加强浏览器兼容性?
  • 部署代码的时候如何清除用户浏览器遗留下来的上个版本的缓存?

后续发展

我相信,架构不是一蹴而就的,而是一个不断迭代的过程,每跨过一个坑、每解决一个痛点痒点,都能使架构更加健壮。

附系列文章目录(同步更新)

webpack多页应用架构系列(二):webpack配置常用部分有哪些?:https://segmentfault.com/a/1190000006863968

本文首发于Array_Huang的技术博客——实用至上,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006843916
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang
查看原文

追梦人物 赞了文章 · 2018-04-09

webpack多页应用架构系列(一):一步一步解决架构痛点

本文首发于Array_Huang的技术博客——实用至上,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006843916
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang

这系列文章讲什么?

本系列文章主要介绍如何用webpack这一当前流行的构建工具来设计一个多页应用的架构。请注意,本文并非新手教程,着重点更多是在于提供解决问题的思路,而非手把手带你装逼。

作者介绍

本人供职于某互联网物流公司,专职前端,公司虽仍处于创业阶段,但产品线已经拉得挺长的了,因此所碰到的痒点、痛点也不少。我本是PHPer出身,对传统前端茹毛饮血的境况恨之入骨,幸得webpack这一神器,我感觉现在写前端已经跟写PHP差不多了(大误)。

示例代码

诸位看本系列文章,搭配我的脚手架项目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)
上个文件目录结构让大家一睹为快:

├─build # 编译后生成的所有代码、资源(图片、字体等,虽然只是简单的从源目录迁移过来)
├─node_modules # 利用npm管理的所有包及其依赖
├─vendor # 所有不能用npm管理的第三方库
├─.babelrc # babel的配置文件
├─.eslintrc # ESLint的配置文件
├─index.html # 仅作为重定向使用
├─package.json # npm的配置文件
├─webpack.config.js # webpack的配置文件
├─src # 当前项目的源码
    ├─pages # 各个页面独有的部分,如入口文件、只有该页面使用到的css、模板文件等
    │  ├─alert # 业务模块
    │  │  └─index # 具体页面
    │  ├─index # 业务模块
    │  │  ├─index # 具体页面
    │  │  └─login # 具体页面
    │  │      └─templates # 如果一个页面的HTML比较复杂,可以分成多块再拼在一起
    │  └─user # 业务模块
    │      ├─edit-password # 具体页面
    │      └─modify-info # 具体页面
    └─public-resource # 各个页面使用到的公共资源
        ├─components # 组件,可以是纯HTML,也可以包含js/css/image等,看自己需要
        │  ├─footer # 页尾
        │  ├─header # 页头
        │  ├─side-menu # 侧边栏
        │  └─top-nav # 顶部菜单
        ├─config # 各种配置文件
        ├─iconfont # iconfont的字体文件
        ├─imgs # 公用的图片资源
        ├─layout # UI布局,组织各个组件拼起来,因应需要可以有不同的布局套路
        │  ├─layout # 具体的布局套路
        │  └─layout-without-nav # 具体的布局套路
        ├─less # less文件,用sass的也可以,又或者是纯css
        │  ├─base-dir
        │  ├─components-dir # 如果组件本身不需要js的,那么要加载组件的css比较困难,我建议可以直接用less来加载
        │  └─base.less # 组织所有的less文件
        ├─libs # 与业务逻辑无关的库都可以放到这里
        └─logic # 业务逻辑

架构痛点痒点一览(并非系列文章的所有内容)

  • SPA好复杂,我还是喜欢传统的多页应用怎么破?又或是,我司项目需要后端渲染,页面模板怎么出?
  • 每个页面相同的UI布局好难维护,UI稍微改一点就要到每个页面去改,好麻烦还容易漏,怎么破?
  • 除js外的资源如css/less、图片、swf、字体等,要怎么打包呢?不然老是要外部引用,迁移、部署起来都好麻烦呢。
  • 某些年久失修的jQuery插件怎么在webpack里使用呢?
  • 能不能整合进ESLint来检查语法?
  • 能不能整合postcss来加强浏览器兼容性?
  • 部署代码的时候如何清除用户浏览器遗留下来的上个版本的缓存?

后续发展

我相信,架构不是一蹴而就的,而是一个不断迭代的过程,每跨过一个坑、每解决一个痛点痒点,都能使架构更加健壮。

附系列文章目录(同步更新)

webpack多页应用架构系列(二):webpack配置常用部分有哪些?:https://segmentfault.com/a/1190000006863968

本文首发于Array_Huang的技术博客——实用至上,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006843916
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang
查看原文

赞 236 收藏 945 评论 57

追梦人物 关注了用户 · 2018-04-09

array_huang @array_huang

关注 4975

追梦人物 关注了专栏 · 2018-04-09

实用至上

记录和分享我在开发过程中的心得与感悟

关注 1002

追梦人物 关注了标签 · 2017-11-29

我是工具控

「我是工具控」分享

快捷键加快了你的工作速度
黑科技提升了你的逼格水平
那有没有一些开发工具
既加快你的工作速度,又提升你的逼格水平?
如果有,那就请工具控们快快分享出来,带大家走上高效开发之路

如何分享?

「 我是工具控」分享规则很简单:

  1. 在自己的专栏发文章分享你的工具,标题自拟,文体不限,语言自选。

  2. 「我是工具控」为文章标签,且在文章末尾注明:

本文参与了 SegmentFault「我是工具控」分享,如果你也手持利器,那就一起来分享吧。

发布后,我们会把你的文章加入本文列表。神器级别的工具,小编会鼎力推荐到社区首页、官方微博,微信公众号和技术交流群。

文章需包含以下问题:

  • 一行话介绍自己及现在的工作,所用开发语言

  • 推荐至少 3 款你觉着是神器的工具,没理由我不服orz

  • 贴一张你工位的高清无码图

文章只要包含了以上必写内容即可,至于文章的表现形式,当然是艺术家你们自己决定。

当然,除了代码,我们还有生活,以下是自选题

  • 生活中还有什么其他必备神器?(小编表示是电动牙刷和老干妈)

  • 哪些好玩的网站、app、软件、硬件

  • 程序员装逼技能


手持利器的你们

请加入「我是工具控」,分享你的工具仓库吧

关注 88

认证与成就

  • 获得 74 次点赞
  • 获得 58 枚徽章 获得 0 枚金徽章, 获得 21 枚银徽章, 获得 37 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2015-07-22
个人主页被 2.5k 人浏览